diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index bed47a44a..ae899dde2 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -89,12 +89,12 @@
android:label="@string/title_wizard"
android:windowSoftInputMode="stateHidden" />
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
index 1b59e7cc0..9a08290e4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -38,6 +38,7 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.spongycastle.openpgp.operator.PGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.PGPDigestCalculator;
+import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
@@ -50,6 +51,9 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel;
import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType;
import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
+import org.sufficientlysecure.keychain.util.IterableIterator;
+import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Primes;
import java.io.IOException;
@@ -63,6 +67,7 @@ import java.security.SignatureException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
+import java.util.Iterator;
import java.util.TimeZone;
/**
@@ -99,18 +104,13 @@ public class PgpKeyOperation {
}
/** Creates new secret key. */
- private PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase,
- boolean isMasterKey) throws PgpGeneralMsgIdException {
+ private PGPKeyPair createKey(int algorithmChoice, int keySize) throws PgpGeneralMsgIdException {
try {
if (keySize < 512) {
throw new PgpGeneralMsgIdException(R.string.error_key_size_minimum512bit);
}
- if (passphrase == null) {
- passphrase = "";
- }
-
int algorithm;
KeyPairGenerator keyGen;
@@ -123,9 +123,6 @@ public class PgpKeyOperation {
}
case Constants.choice.algorithm.elgamal: {
- if (isMasterKey) {
- throw new PgpGeneralMsgIdException(R.string.error_master_key_must_not_be_el_gamal);
- }
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
BigInteger p = Primes.getBestPrime(keySize);
BigInteger g = new BigInteger("2");
@@ -151,19 +148,8 @@ public class PgpKeyOperation {
}
// build new key pair
- PGPKeyPair keyPair = new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
+ return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
- // define hashing and signing algos
- PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
- HashAlgorithmTags.SHA1);
-
- // Build key encrypter and decrypter based on passphrase
- PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
- PGPEncryptedData.CAST5, sha1Calc)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
-
- return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
- sha1Calc, isMasterKey, keyEncryptor);
} catch(NoSuchProviderException e) {
throw new RuntimeException(e);
} catch(NoSuchAlgorithmException e) {
@@ -175,6 +161,55 @@ public class PgpKeyOperation {
}
}
+ public UncachedKeyRing createSecretKeyRing(SaveKeyringParcel saveParcel, OperationLog log,
+ int indent) {
+
+ try {
+
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_KEYID, indent);
+ indent += 1;
+ updateProgress(R.string.progress_building_key, 0, 100);
+
+ if (saveParcel.addSubKeys == null || saveParcel.addSubKeys.isEmpty()) {
+ log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NO_MASTER, indent);
+ return null;
+ }
+
+ SubkeyAdd add = saveParcel.addSubKeys.remove(0);
+ PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize);
+
+ if (add.mAlgorithm == Constants.choice.algorithm.elgamal) {
+ throw new PgpGeneralMsgIdException(R.string.error_master_key_must_not_be_el_gamal);
+ }
+
+ // define hashing and signing algos
+ PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
+ .build().get(HashAlgorithmTags.SHA1);
+ // Build key encrypter and decrypter based on passphrase
+ PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
+ PGPEncryptedData.CAST5, sha1Calc)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
+ PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
+ sha1Calc, true, keyEncryptor);
+
+ PGPSecretKeyRing sKR = new PGPSecretKeyRing(
+ masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
+
+ return internal(sKR, masterSecretKey, saveParcel, "", log, indent);
+
+ } catch (PGPException e) {
+ Log.e(Constants.TAG, "pgp error encoding key", e);
+ return null;
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "io error encoding key", e);
+ return null;
+ } catch (PgpGeneralMsgIdException e) {
+ Log.e(Constants.TAG, "pgp msg id error", e);
+ return null;
+ }
+
+ }
+
/** This method introduces a list of modifications specified by a SaveKeyringParcel to a
* WrappedSecretKeyRing.
*
@@ -204,28 +239,49 @@ public class PgpKeyOperation {
indent += 1;
updateProgress(R.string.progress_building_key, 0, 100);
+ // Make sure this is called with a proper SaveKeyringParcel
+ if (saveParcel.mMasterKeyId == null || saveParcel.mMasterKeyId != wsKR.getMasterKeyId()) {
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_KEYID, indent);
+ return null;
+ }
+
// We work on bouncycastle object level here
PGPSecretKeyRing sKR = wsKR.getRing();
- PGPPublicKey masterPublicKey = sKR.getPublicKey();
PGPSecretKey masterSecretKey = sKR.getSecretKey();
+ // Make sure the fingerprint matches
+ if (saveParcel.mFingerprint == null
+ || !Arrays.equals(saveParcel.mFingerprint,
+ masterSecretKey.getPublicKey().getFingerprint())) {
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_FINGERPRINT, indent);
+ return null;
+ }
+
+ return internal(sKR, masterSecretKey, saveParcel, passphrase, log, indent);
+
+ }
+
+ private UncachedKeyRing internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
+ SaveKeyringParcel saveParcel, String passphrase,
+ OperationLog log, int indent) {
+
+ updateProgress(R.string.progress_certifying_master_key, 20, 100);
+
+ PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
+
// 1. Unlock private key
log.add(LogLevel.DEBUG, LogType.MSG_MF_UNLOCK, indent);
- PGPPrivateKey masterPrivateKey; {
+ PGPPrivateKey masterPrivateKey;
+ {
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
} catch (PGPException e) {
- log.add(LogLevel.ERROR, LogType.MSG_MF_UNLOCK_ERROR, indent+1);
+ log.add(LogLevel.ERROR, LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
return null;
}
}
- if (!Arrays.equals(saveParcel.mFingerprint, sKR.getPublicKey().getFingerprint())) {
- return null;
- }
-
- updateProgress(R.string.progress_certifying_master_key, 20, 100);
// work on master secret key
try {
@@ -235,14 +291,42 @@ public class PgpKeyOperation {
// 2a. Add certificates for new user ids
for (String userId : saveParcel.addUserIds) {
log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent);
+
+ // this operation supersedes all previous binding and revocation certificates,
+ // so remove those to retain assertions from canonicalization for later operations
+ @SuppressWarnings("unchecked")
+ Iterator it = modifiedPublicKey.getSignaturesForID(userId);
+ if (it != null) {
+ for (PGPSignature cert : new IterableIterator(it)) {
+ // if it's not a self cert, never mind
+ if (cert.getKeyID() != masterPublicKey.getKeyID()) {
+ continue;
+ }
+ if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION
+ || cert.getSignatureType() == PGPSignature.NO_CERTIFICATION
+ || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION
+ || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION
+ || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
+ modifiedPublicKey = PGPPublicKey.removeCertification(
+ modifiedPublicKey, userId, cert);
+ }
+ }
+ }
+
+ // if it's supposed to be primary, we can do that here as well
+ boolean isPrimary = saveParcel.changePrimaryUserId != null
+ && userId.equals(saveParcel.changePrimaryUserId);
+ // generate and add new certificate
PGPSignature cert = generateUserIdSignature(masterPrivateKey,
- masterPublicKey, userId, false);
+ masterPublicKey, userId, isPrimary);
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
}
// 2b. Add revocations for revoked user ids
for (String userId : saveParcel.revokeUserIds) {
log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent);
+ // a duplicate revocatin will be removed during canonicalization, so no need to
+ // take care of that here.
PGPSignature cert = generateRevocationSignature(masterPrivateKey,
masterPublicKey, userId);
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
@@ -251,7 +335,84 @@ public class PgpKeyOperation {
// 3. If primary user id changed, generate new certificates for both old and new
if (saveParcel.changePrimaryUserId != null) {
log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent);
- // todo
+
+ // we work on the modifiedPublicKey here, to respect new or newly revoked uids
+ // noinspection unchecked
+ for (String userId : new IterableIterator(modifiedPublicKey.getUserIDs())) {
+ boolean isRevoked = false;
+ PGPSignature currentCert = null;
+ // noinspection unchecked
+ for (PGPSignature cert : new IterableIterator(
+ masterPublicKey.getSignaturesForID(userId))) {
+ // if it's not a self cert, never mind
+ if (cert.getKeyID() != masterPublicKey.getKeyID()) {
+ continue;
+ }
+ // we know from canonicalization that if there is any revocation here, it
+ // is valid and not superseded by a newer certification.
+ if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) {
+ isRevoked = true;
+ continue;
+ }
+ // we know from canonicalization that there is only one binding
+ // certification here, so we can just work with the first one.
+ if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION ||
+ cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION ||
+ cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION ||
+ cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
+ currentCert = cert;
+ }
+ }
+
+ if (currentCert == null) {
+ // no certificate found?! error error error
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent);
+ return null;
+ }
+
+ // we definitely should not update certifications of revoked keys, so just leave it.
+ if (isRevoked) {
+ // revoked user ids cannot be primary!
+ if (userId.equals(saveParcel.changePrimaryUserId)) {
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent);
+ return null;
+ }
+ continue;
+ }
+
+ // if this is~ the/a primary user id
+ if (currentCert.hasSubpackets() && currentCert.getHashedSubPackets().isPrimaryUserID()) {
+ // if it's the one we want, just leave it as is
+ if (userId.equals(saveParcel.changePrimaryUserId)) {
+ continue;
+ }
+ // otherwise, generate new non-primary certification
+ modifiedPublicKey = PGPPublicKey.removeCertification(
+ modifiedPublicKey, userId, currentCert);
+ PGPSignature newCert = generateUserIdSignature(
+ masterPrivateKey, masterPublicKey, userId, false);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ continue;
+ }
+
+ // if we are here, this is not currently a primary user id
+
+ // if it should be
+ if (userId.equals(saveParcel.changePrimaryUserId)) {
+ // add shiny new primary user id certificate
+ modifiedPublicKey = PGPPublicKey.removeCertification(
+ modifiedPublicKey, userId, currentCert);
+ PGPSignature newCert = generateUserIdSignature(
+ masterPrivateKey, masterPublicKey, userId, true);
+ modifiedPublicKey = PGPPublicKey.addCertification(
+ modifiedPublicKey, userId, newCert);
+ }
+
+ // user id is not primary and is not supposed to be - nothing to do here.
+
+ }
+
}
// Update the secret key ring
@@ -261,8 +422,7 @@ public class PgpKeyOperation {
sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey);
}
-
- // 4a. For each subkey change, generate new subkey binding certificate
+ // 4a. For each subkey change, generate new subkey binding certificate
for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) {
log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE,
indent, PgpKeyHelper.convertKeyIdToHex(change.mKeyId));
@@ -280,7 +440,8 @@ public class PgpKeyOperation {
return null;
}
- // generate and add new signature
+ // generate and add new signature. we can be sloppy here and just leave the old one,
+ // it will be removed during canonicalization
PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
sKey, pKey, change.mFlags, change.mExpiry, passphrase);
pKey = PGPPublicKey.addCertification(pKey, sig);
@@ -316,16 +477,36 @@ public class PgpKeyOperation {
}
log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent);
- PGPSecretKey sKey = createKey(add.mAlgorithm, add.mKeysize, passphrase, false);
+
+ // generate a new secret key (privkey only for now)
+ PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize);
+
+ // add subkey binding signature (making this a sub rather than master key)
+ PGPPublicKey pKey = keyPair.getPublicKey();
+ PGPSignature cert = generateSubkeyBindingSignature(
+ masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
+ add.mFlags, add.mExpiry);
+ pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
+
+ PGPSecretKey sKey; {
+ // define hashing and signing algos
+ PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
+ .build().get(HashAlgorithmTags.SHA1);
+
+ // Build key encrypter and decrypter based on passphrase
+ PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
+ PGPEncryptedData.CAST5, sha1Calc)
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
+
+ sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey,
+ sha1Calc, false, keyEncryptor);
+ }
+
log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID,
indent+1, PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID()));
- PGPPublicKey pKey = sKey.getPublicKey();
- PGPSignature cert = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
- sKey, pKey, add.mFlags, add.mExpiry, passphrase);
- pKey = PGPPublicKey.addCertification(pKey, cert);
- sKey = PGPSecretKey.replacePublicKey(sKey, pKey);
- sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
+ sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
+
} catch (PgpGeneralMsgIdException e) {
return null;
}
@@ -420,6 +601,18 @@ public class PgpKeyOperation {
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
PGPSecretKey sKey, PGPPublicKey pKey, int flags, Long expiry, String passphrase)
throws IOException, PGPException, SignatureException {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
+ passphrase.toCharArray());
+ PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
+ return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
+ pKey, flags, expiry);
+ }
+
+ private static PGPSignature generateSubkeyBindingSignature(
+ PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
+ PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, Long expiry)
+ throws IOException, PGPException, SignatureException {
// date for signing
Date todayDate = new Date();
@@ -427,12 +620,6 @@ public class PgpKeyOperation {
// If this key can sign, we need a primary key binding signature
if ((flags & KeyFlags.SIGN_DATA) != 0) {
-
- PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- passphrase.toCharArray());
- PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
-
// cross-certify signing keys
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
subHashedPacketsGen.setSignatureCreationTime(false, todayDate);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java
index d7148f710..c737b7c46 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java
@@ -8,16 +8,13 @@ import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
-import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
-import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
-import java.security.NoSuchProviderException;
import java.util.Iterator;
public class WrappedSecretKeyRing extends WrappedKeyRing {
@@ -91,29 +88,6 @@ public class WrappedSecretKeyRing extends WrappedKeyRing {
}
}
- public UncachedKeyRing changeSecretKeyPassphrase(String oldPassphrase,
- String newPassphrase)
- throws IOException, PGPException, NoSuchProviderException {
-
- if (oldPassphrase == null) {
- oldPassphrase = "";
- }
- if (newPassphrase == null) {
- newPassphrase = "";
- }
-
- PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(
- mRing,
- new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()),
- new JcePBESecretKeyEncryptorBuilder(mRing.getSecretKey()
- .getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray()));
-
- return new UncachedKeyRing(newKeyRing);
-
- }
-
public IterableIterator secretKeyIterator() {
final Iterator it = mRing.getSecretKeys();
return new IterableIterator(new Iterator() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index 4bf3a38a0..81e218ccf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -405,7 +405,11 @@ public class ProviderHelper {
// classify and order user ids. primary are moved to the front, revoked to the back,
// otherwise the order in the keyfile is preserved.
- log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size());
+ if (trustedKeys.size() == 0) {
+ log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING_ZERO);
+ } else {
+ log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size());
+ }
mIndent += 1;
List uids = new ArrayList();
for (String userId : new IterableIterator(
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
index e49c11e08..0b1d521ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
@@ -35,7 +35,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
-import org.sufficientlysecure.keychain.ui.EditKeyActivity;
+import org.sufficientlysecure.keychain.ui.EditKeyActivityOld;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter;
import org.sufficientlysecure.keychain.util.AlgorithmNames;
@@ -163,11 +163,11 @@ public class AccountSettingsFragment extends Fragment implements
}
private void createKey() {
- Intent intent = new Intent(getActivity(), EditKeyActivity.class);
- intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
- intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
+ Intent intent = new Intent(getActivity(), EditKeyActivityOld.class);
+ intent.setAction(EditKeyActivityOld.ACTION_CREATE_KEY);
+ intent.putExtra(EditKeyActivityOld.EXTRA_GENERATE_DEFAULT_KEYS, true);
// set default user id to account name
- intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, mAccSettings.getAccountName());
+ intent.putExtra(EditKeyActivityOld.EXTRA_USER_IDS, mAccSettings.getAccountName());
startActivityForResult(intent, REQUEST_CODE_CREATE_KEY);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index d87f98775..00f210cc1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -215,6 +215,10 @@ public class KeychainIntentService extends IntentService
mMessenger = (Messenger) extras.get(EXTRA_MESSENGER);
Bundle data = extras.getBundle(EXTRA_DATA);
+ if (data == null) {
+ Log.e(Constants.TAG, "data extra is null!");
+ return;
+ }
OtherHelper.logDebugBundle(data, "EXTRA_DATA");
@@ -331,33 +335,41 @@ public class KeychainIntentService extends IntentService
try {
/* Input */
SaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL);
- long masterKeyId = saveParcel.mMasterKeyId;
+ if (saveParcel == null) {
+ Log.e(Constants.TAG, "bug: missing save_keyring_parcel in data!");
+ return;
+ }
/* Operation */
ProviderHelper providerHelper = new ProviderHelper(this);
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 10, 50, 100));
try {
- String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE);
- WrappedSecretKeyRing secRing = providerHelper.getWrappedSecretKeyRing(masterKeyId);
-
OperationLog log = new OperationLog();
- UncachedKeyRing ring = keyOperations.modifySecretKeyRing(secRing, saveParcel,
- passphrase, log, 0);
- providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100));
+ UncachedKeyRing ring;
+ if (saveParcel.mMasterKeyId != null) {
+ String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE);
+ WrappedSecretKeyRing secRing =
+ providerHelper.getWrappedSecretKeyRing(saveParcel.mMasterKeyId);
+
+ ring = keyOperations.modifySecretKeyRing(secRing, saveParcel,
+ passphrase, log, 0);
+ } else {
+ ring = keyOperations.createSecretKeyRing(saveParcel, log, 0);
+ }
+
+ providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 10, 95, 100));
+
+ // cache new passphrase
+ if (saveParcel.newPassphrase != null) {
+ PassphraseCacheService.addCachedPassphrase(this, ring.getMasterKeyId(),
+ saveParcel.newPassphrase);
+ }
} catch (ProviderHelper.NotFoundException e) {
- // UncachedKeyRing ring = keyOperations.(saveParcel); //new Keyring
- // save the pair
- setProgress(R.string.progress_saving_key_ring, 95, 100);
- // providerHelper.saveSecretKeyRing(ring);
sendErrorToHandler(e);
}
setProgress(R.string.progress_done, 100, 100);
- if (saveParcel.newPassphrase != null) {
- PassphraseCacheService.addCachedPassphrase(this, masterKeyId, saveParcel.newPassphrase);
- }
-
/* Output */
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
} catch (Exception e) {
@@ -458,7 +470,7 @@ public class KeychainIntentService extends IntentService
outStream);
if (mIsCanceled && outputFile != null) {
- boolean isDeleted = new File(outputFile).delete();
+ new File(outputFile).delete();
}
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
@@ -614,6 +626,7 @@ public class KeychainIntentService extends IntentService
return;
}
Message msg = Message.obtain();
+ assert msg != null;
msg.arg1 = arg1;
if (arg2 != null) {
msg.arg2 = arg2;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
index d5d02081a..755827482 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
@@ -27,8 +27,10 @@ import android.support.v4.app.FragmentManager;
import com.devspark.appmsg.AppMsg;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
+import org.sufficientlysecure.keychain.util.Log;
public class KeychainIntentServiceHandler extends Handler {
@@ -126,6 +128,7 @@ public class KeychainIntentServiceHandler extends Handler {
break;
default:
+ Log.e(Constants.TAG, "unknown handler message!");
break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
index 7f91ab490..6bf6b655d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
@@ -165,6 +165,7 @@ public class OperationResultParcel implements Parcelable {
MSG_IP_UID_CERT_ERROR (R.string.msg_ip_uid_cert_error),
MSG_IP_UID_CERT_GOOD (R.string.msg_ip_uid_cert_good),
MSG_IP_UID_CERTS_UNKNOWN (R.plurals.msg_ip_uid_certs_unknown),
+ MSG_IP_UID_CLASSIFYING_ZERO (R.string.msg_ip_uid_classifying_zero),
MSG_IP_UID_CLASSIFYING (R.plurals.msg_ip_uid_classifying),
MSG_IP_UID_REORDER(R.string.msg_ip_uid_reorder),
MSG_IP_UID_PROCESSING (R.string.msg_ip_uid_processing),
@@ -233,9 +234,16 @@ public class OperationResultParcel implements Parcelable {
MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey),
MSG_MG_FOUND_NEW (R.string.msg_mg_found_new),
+ // secret key create
+ MSG_CR_ERROR_NO_MASTER (R.string.msg_mr),
+
// secret key modify
MSG_MF (R.string.msg_mr),
MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode),
+ MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint),
+ MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid),
+ MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity),
+ MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary),
MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp),
MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig),
MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase),
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index d42bae67a..28f230f71 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -49,7 +49,6 @@ import java.util.Date;
* convenience.
*/
public class PassphraseCacheService extends Service {
- public static final String TAG = Constants.TAG + ": PassphraseCacheService";
public static final String ACTION_PASSPHRASE_CACHE_ADD = Constants.INTENT_PREFIX
+ "PASSPHRASE_CACHE_ADD";
@@ -83,7 +82,7 @@ public class PassphraseCacheService extends Service {
* @param passphrase
*/
public static void addCachedPassphrase(Context context, long keyId, String passphrase) {
- Log.d(TAG, "cacheNewPassphrase() for " + keyId);
+ Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + keyId);
Intent intent = new Intent(context, PassphraseCacheService.class);
intent.setAction(ACTION_PASSPHRASE_CACHE_ADD);
@@ -103,7 +102,7 @@ public class PassphraseCacheService extends Service {
* @return passphrase or null (if no passphrase is cached for this keyId)
*/
public static String getCachedPassphrase(Context context, long keyId) {
- Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId);
+ Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() get masterKeyId for " + keyId);
Intent intent = new Intent(context, PassphraseCacheService.class);
intent.setAction(ACTION_PASSPHRASE_CACHE_GET);
@@ -159,7 +158,7 @@ public class PassphraseCacheService extends Service {
private String getCachedPassphraseImpl(long keyId) {
// passphrase for symmetric encryption?
if (keyId == Constants.key.symmetric) {
- Log.d(TAG, "getCachedPassphraseImpl() for symmetric encryption");
+ Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
String cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric);
if (cachedPassphrase == null) {
return null;
@@ -170,7 +169,7 @@ public class PassphraseCacheService extends Service {
// try to get master key id which is used as an identifier for cached passphrases
try {
- Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId);
+ Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for masterKeyId " + keyId);
WrappedSecretKeyRing key = new ProviderHelper(this).getWrappedSecretKeyRing(
KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId));
// no passphrase needed? just add empty string and return it, then
@@ -184,18 +183,18 @@ public class PassphraseCacheService extends Service {
// get cached passphrase
String cachedPassphrase = mPassphraseCache.get(keyId);
if (cachedPassphrase == null) {
- Log.d(TAG, "Passphrase not (yet) cached, returning null");
+ Log.d(Constants.TAG, "PassphraseCacheService Passphrase not (yet) cached, returning null");
// not really an error, just means the passphrase is not cached but not empty either
return null;
}
// set it again to reset the cache life cycle
- Log.d(TAG, "Cache passphrase again when getting it!");
+ Log.d(Constants.TAG, "PassphraseCacheService Cache passphrase again when getting it!");
addCachedPassphrase(this, keyId, cachedPassphrase);
return cachedPassphrase;
} catch (ProviderHelper.NotFoundException e) {
- Log.e(TAG, "Passphrase for unknown key was requested!");
+ Log.e(Constants.TAG, "PassphraseCacheService Passphrase for unknown key was requested!");
return null;
}
}
@@ -212,7 +211,7 @@ public class PassphraseCacheService extends Service {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- Log.d(TAG, "Received broadcast...");
+ Log.d(Constants.TAG, "PassphraseCacheService Received broadcast...");
if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
@@ -248,7 +247,7 @@ public class PassphraseCacheService extends Service {
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "onStartCommand()");
+ Log.d(Constants.TAG, "PassphraseCacheService.onStartCommand()");
// register broadcastreceiver
registerReceiver();
@@ -259,8 +258,8 @@ public class PassphraseCacheService extends Service {
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
- Log.d(TAG,
- "Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: "
+ Log.d(Constants.TAG,
+ "PassphraseCacheService Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: "
+ keyId + ", ttl: " + ttl);
// add keyId and passphrase to memory
@@ -285,10 +284,10 @@ public class PassphraseCacheService extends Service {
try {
messenger.send(msg);
} catch (RemoteException e) {
- Log.e(Constants.TAG, "Sending message failed", e);
+ Log.e(Constants.TAG, "PassphraseCacheService Sending message failed", e);
}
} else {
- Log.e(Constants.TAG, "Intent or Intent Action not supported!");
+ Log.e(Constants.TAG, "PassphraseCacheService Intent or Intent Action not supported!");
}
}
@@ -305,11 +304,11 @@ public class PassphraseCacheService extends Service {
// remove passphrase corresponding to keyId from memory
mPassphraseCache.remove(keyId);
- Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!");
+ Log.d(Constants.TAG, "PassphraseCacheService Timeout of keyId " + keyId + ", removed from memory!");
// stop whole service if no cached passphrases remaining
if (mPassphraseCache.size() == 0) {
- Log.d(TAG, "No passphrases remaining in memory, stopping service!");
+ Log.d(Constants.TAG, "PassphraseCacheServic No passphrases remaining in memory, stopping service!");
stopSelf();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
index 020b808b9..a56095767 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
@@ -22,10 +22,10 @@ import java.util.ArrayList;
*/
public class SaveKeyringParcel implements Parcelable {
- // the master key id to be edited
- public final long mMasterKeyId;
- // the key fingerprint, for safety
- public final byte[] mFingerprint;
+ // the master key id to be edited. if this is null, a new one will be created
+ public Long mMasterKeyId;
+ // the key fingerprint, for safety. MUST be null for a new key.
+ public byte[] mFingerprint;
public String newPassphrase;
@@ -38,9 +38,7 @@ public class SaveKeyringParcel implements Parcelable {
public ArrayList revokeUserIds;
public ArrayList revokeSubKeys;
- public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) {
- mMasterKeyId = masterKeyId;
- mFingerprint = fingerprint;
+ public SaveKeyringParcel() {
addUserIds = new ArrayList();
addSubKeys = new ArrayList();
changeSubKeys = new ArrayList();
@@ -48,13 +46,19 @@ public class SaveKeyringParcel implements Parcelable {
revokeSubKeys = new ArrayList();
}
+ public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) {
+ this();
+ mMasterKeyId = masterKeyId;
+ mFingerprint = fingerprint;
+ }
+
// performance gain for using Parcelable here would probably be negligible,
// use Serializable instead.
public static class SubkeyAdd implements Serializable {
- public final int mAlgorithm;
- public final int mKeysize;
- public final int mFlags;
- public final Long mExpiry;
+ public int mAlgorithm;
+ public int mKeysize;
+ public int mFlags;
+ public Long mExpiry;
public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) {
mAlgorithm = algorithm;
mKeysize = keysize;
@@ -64,9 +68,9 @@ public class SaveKeyringParcel implements Parcelable {
}
public static class SubkeyChange implements Serializable {
- public final long mKeyId;
- public final Integer mFlags;
- public final Long mExpiry;
+ public long mKeyId;
+ public Integer mFlags;
+ public Long mExpiry;
public SubkeyChange(long keyId, Integer flags, Long expiry) {
mKeyId = keyId;
mFlags = flags;
@@ -75,9 +79,11 @@ public class SaveKeyringParcel implements Parcelable {
}
public SaveKeyringParcel(Parcel source) {
- mMasterKeyId = source.readLong();
+ mMasterKeyId = source.readInt() != 0 ? source.readLong() : null;
mFingerprint = source.createByteArray();
+ newPassphrase = source.readString();
+
addUserIds = source.createStringArrayList();
addSubKeys = (ArrayList) source.readSerializable();
@@ -90,9 +96,14 @@ public class SaveKeyringParcel implements Parcelable {
@Override
public void writeToParcel(Parcel destination, int flags) {
- destination.writeLong(mMasterKeyId);
+ destination.writeInt(mMasterKeyId == null ? 0 : 1);
+ if(mMasterKeyId != null) {
+ destination.writeLong(mMasterKeyId);
+ }
destination.writeByteArray(mFingerprint);
+ destination.writeString(newPassphrase);
+
destination.writeStringList(addUserIds);
destination.writeSerializable(addSubKeys);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index 33659f3e5..5d82fca6a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -155,7 +155,7 @@ public class DecryptActivity extends DrawerActivity {
} else if (ACTION_DECRYPT.equals(action) && uri != null) {
mFileFragmentBundle.putParcelable(DecryptFileFragment.ARG_URI, uri);
mSwitchToTab = PAGER_TAB_FILE;
- } else {
+ } else if (ACTION_DECRYPT.equals(action)) {
Log.e(Constants.TAG,
"Include the extra 'text' or an Uri with setData() in your Intent!");
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index d734c31db..d80425c3c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2012-2014 Dominik Schürmann
- * Copyright (C) 2010-2014 Thialfihar
+ * Copyright (C) 2014 Dominik Schürmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,732 +17,52 @@
package org.sufficientlysecure.keychain.ui;
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBarActivity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
-import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.LinearLayout;
-import android.widget.Toast;
-
-import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.ActionBarHelper;
-import org.sufficientlysecure.keychain.helper.ExportHelper;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
-import org.sufficientlysecure.keychain.pgp.UncachedSecretKey;
-import org.sufficientlysecure.keychain.pgp.WrappedSecretKey;
-import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing;
-import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.service.PassphraseCacheService;
-import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
-import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
-import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
-import org.sufficientlysecure.keychain.ui.widget.Editor;
-import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
-import org.sufficientlysecure.keychain.ui.widget.KeyEditor;
-import org.sufficientlysecure.keychain.ui.widget.SectionView;
-import org.sufficientlysecure.keychain.ui.widget.UserIdEditor;
import org.sufficientlysecure.keychain.util.Log;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-import java.util.Vector;
+public class EditKeyActivity extends ActionBarActivity {
-public class EditKeyActivity extends ActionBarActivity implements EditorListener {
-
- // Actions for internal use only:
- public static final String ACTION_CREATE_KEY = Constants.INTENT_PREFIX + "CREATE_KEY";
- public static final String ACTION_EDIT_KEY = Constants.INTENT_PREFIX + "EDIT_KEY";
-
- // possible extra keys
- public static final String EXTRA_USER_IDS = "user_ids";
- public static final String EXTRA_NO_PASSPHRASE = "no_passphrase";
- public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generate_default_keys";
-
- // EDIT
- private Uri mDataUri;
-
- private SectionView mUserIdsView;
- private SectionView mKeysView;
-
- private String mCurrentPassphrase = null;
- private String mNewPassphrase = null;
- private String mSavedNewPassphrase = null;
- private boolean mIsPassphraseSet;
- private boolean mNeedsSaving;
- private boolean mIsBrandNewKeyring = false;
-
- private Button mChangePassphrase;
-
- private CheckBox mNoPassphrase;
-
- Vector mUserIds;
- Vector mKeys;
- Vector mKeysUsages;
- boolean mMasterCanSign = true;
-
- ExportHelper mExportHelper;
-
- public boolean needsSaving() {
- mNeedsSaving = (mUserIdsView == null) ? false : mUserIdsView.needsSaving();
- mNeedsSaving |= (mKeysView == null) ? false : mKeysView.needsSaving();
- mNeedsSaving |= hasPassphraseChanged();
- mNeedsSaving |= mIsBrandNewKeyring;
- return mNeedsSaving;
- }
-
-
- public void somethingChanged() {
- ActivityCompat.invalidateOptionsMenu(this);
- }
-
- public void onDeleted(Editor e, boolean wasNewItem) {
- somethingChanged();
- }
-
- public void onEdited() {
- somethingChanged();
- }
+ private EditKeyFragment mEditKeyFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mExportHelper = new ExportHelper(this);
+ setContentView(R.layout.edit_key_activity_new);
- // Inflate a "Done"/"Cancel" custom action bar view
- ActionBarHelper.setTwoButtonView(getSupportActionBar(),
- R.string.btn_save, R.drawable.ic_action_save,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Save
- saveClicked();
- }
- }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Cancel
- cancelClicked();
- }
- }
- );
-
- mUserIds = new Vector();
- mKeys = new Vector();
- mKeysUsages = new Vector();
-
- // Catch Intents opened from other apps
- Intent intent = getIntent();
- String action = intent.getAction();
- if (ACTION_CREATE_KEY.equals(action)) {
- handleActionCreateKey(intent);
- } else if (ACTION_EDIT_KEY.equals(action)) {
- handleActionEditKey(intent);
- }
- }
-
- /**
- * Handle intent action to create new key
- *
- * @param intent
- */
- private void handleActionCreateKey(Intent intent) {
- Bundle extras = intent.getExtras();
-
- mCurrentPassphrase = "";
- mIsBrandNewKeyring = true;
-
- if (extras != null) {
- // if userId is given, prefill the fields
- if (extras.containsKey(EXTRA_USER_IDS)) {
- Log.d(Constants.TAG, "UserIds are given!");
- mUserIds.add(extras.getString(EXTRA_USER_IDS));
- }
-
- // if no passphrase is given
- if (extras.containsKey(EXTRA_NO_PASSPHRASE)) {
- boolean noPassphrase = extras.getBoolean(EXTRA_NO_PASSPHRASE);
- if (noPassphrase) {
- // check "no passphrase" checkbox and remove button
- mNoPassphrase.setChecked(true);
- mChangePassphrase.setVisibility(View.GONE);
- }
- }
-
- // generate key
- if (extras.containsKey(EXTRA_GENERATE_DEFAULT_KEYS)) {
- /*
- boolean generateDefaultKeys = extras.getBoolean(EXTRA_GENERATE_DEFAULT_KEYS);
- if (generateDefaultKeys) {
-
- // fill values for this action
- Bundle data = new Bundle();
- data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE,
- mCurrentPassphrase);
-
- serviceIntent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Message is received after generating is done in KeychainIntentService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
- this, getResources().getQuantityString(R.plurals.progress_generating, 1),
- ProgressDialog.STYLE_HORIZONTAL, true,
-
- new DialogInterface.OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- // Stop key generation on cancel
- stopService(serviceIntent);
- EditKeyActivity.this.setResult(Activity.RESULT_CANCELED);
- EditKeyActivity.this.finish();
- }
- }) {
-
- @Override
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- // get new key from data bundle returned from service
- Bundle data = message.getData();
-
- ArrayList newKeys =
- PgpConversionHelper.BytesToPGPSecretKeyList(data
- .getByteArray(KeychainIntentService.RESULT_NEW_KEY));
-
- ArrayList keyUsageFlags = data.getIntegerArrayList(
- KeychainIntentService.RESULT_KEY_USAGES);
-
- if (newKeys.size() == keyUsageFlags.size()) {
- for (int i = 0; i < newKeys.size(); ++i) {
- mKeys.add(newKeys.get(i));
- mKeysUsages.add(keyUsageFlags.get(i));
- }
- }
-
- buildLayout(true);
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- serviceIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- saveHandler.showProgressDialog(this);
-
- // start service with intent
- startService(serviceIntent);
- }
- */
- }
- } else {
- buildLayout(false);
- }
- }
-
- /**
- * Handle intent action to edit existing key
- *
- * @param intent
- */
- private void handleActionEditKey(Intent intent) {
- mDataUri = intent.getData();
- if (mDataUri == null) {
- Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!");
+ Uri dataUri = getIntent().getData();
+ if (dataUri == null) {
+ Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
finish();
- } else {
- Log.d(Constants.TAG, "uri: " + mDataUri);
-
- try {
- Uri secretUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
- WrappedSecretKeyRing keyRing = new ProviderHelper(this).getWrappedSecretKeyRing(secretUri);
-
- mMasterCanSign = keyRing.getSubKey().canCertify();
- for (WrappedSecretKey key : keyRing.secretKeyIterator()) {
- // Turn into uncached instance
- mKeys.add(key.getUncached());
- mKeysUsages.add(key.getKeyUsage()); // get usage when view is created
- }
-
- boolean isSet = false;
- for (String userId : keyRing.getSubKey().getUserIds()) {
- Log.d(Constants.TAG, "Added userId " + userId);
- if (!isSet) {
- isSet = true;
- String[] parts = KeyRing.splitUserId(userId);
- if (parts[0] != null) {
- setTitle(parts[0]);
- }
- }
- mUserIds.add(userId);
- }
-
- buildLayout(false);
-
- mCurrentPassphrase = "";
- mIsPassphraseSet = keyRing.hasPassphrase();
- if (!mIsPassphraseSet) {
- // check "no passphrase" checkbox and remove button
- mNoPassphrase.setChecked(true);
- mChangePassphrase.setVisibility(View.GONE);
- }
-
- } catch (ProviderHelper.NotFoundException e) {
- Log.e(Constants.TAG, "Keyring not found: " + e.getMessage(), e);
- Toast.makeText(this, R.string.error_no_secret_key_found, Toast.LENGTH_SHORT).show();
- finish();
- }
-
+ return;
}
+
+ loadFragment(savedInstanceState, dataUri);
}
- /**
- * Shows the dialog to set a new passphrase
- */
- private void showSetPassphraseDialog() {
- // Message is received after passphrase is cached
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) {
- Bundle data = message.getData();
-
- // set new returned passphrase!
- mNewPassphrase = data
- .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE);
-
- updatePassphraseButtonText();
- somethingChanged();
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(returnHandler);
-
- // set title based on isPassphraseSet()
- int title;
- if (isPassphraseSet()) {
- title = R.string.title_change_passphrase;
- } else {
- title = R.string.title_set_passphrase;
+ private void loadFragment(Bundle savedInstanceState, Uri dataUri) {
+ // However, if we're being restored from a previous state,
+ // then we don't need to do anything and should return or else
+ // we could end up with overlapping fragments.
+ if (savedInstanceState != null) {
+ return;
}
- SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
- messenger, title);
+ // Create an instance of the fragment
+ mEditKeyFragment = EditKeyFragment.newInstance(dataUri);
- setPassphraseDialog.show(getSupportFragmentManager(), "setPassphraseDialog");
- }
-
- /**
- * Build layout based on mUserId, mKeys and mKeysUsages Vectors. It creates Views for every user
- * id and key.
- *
- * @param newKeys
- */
- private void buildLayout(boolean newKeys) {
- setContentView(R.layout.edit_key_activity);
-
- // find views
- mChangePassphrase = (Button) findViewById(R.id.edit_key_btn_change_passphrase);
- mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase);
- // Build layout based on given userIds and keys
-
- LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
- if (mIsPassphraseSet) {
- mChangePassphrase.setText(getString(R.string.btn_change_passphrase));
- }
- mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
- mUserIdsView.setType(SectionView.TYPE_USER_ID);
- mUserIdsView.setCanBeEdited(mMasterCanSign);
- mUserIdsView.setUserIds(mUserIds);
- mUserIdsView.setEditorListener(this);
- container.addView(mUserIdsView);
- mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
- mKeysView.setType(SectionView.TYPE_KEY);
- mKeysView.setCanBeEdited(mMasterCanSign);
- mKeysView.setKeys(mKeys, mKeysUsages, newKeys);
- mKeysView.setEditorListener(this);
- container.addView(mKeysView);
-
- updatePassphraseButtonText();
-
- mChangePassphrase.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- showSetPassphraseDialog();
- }
- });
-
- // disable passphrase when no passphrase checkbox is checked!
- mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() {
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (isChecked) {
- // remove passphrase
- mSavedNewPassphrase = mNewPassphrase;
- mNewPassphrase = "";
- mChangePassphrase.setVisibility(View.GONE);
- } else {
- mNewPassphrase = mSavedNewPassphrase;
- mChangePassphrase.setVisibility(View.VISIBLE);
- }
- somethingChanged();
- }
- });
- }
-
- private long getMasterKeyId() {
- if (mKeysView.getEditors().getChildCount() == 0) {
- return 0;
- }
- return ((KeyEditor) mKeysView.getEditors().getChildAt(0)).getValue().getKeyId();
- }
-
- public boolean isPassphraseSet() {
- if (mNoPassphrase.isChecked()) {
- return true;
- } else if ((mIsPassphraseSet)
- || (mNewPassphrase != null && !mNewPassphrase.equals(""))) {
- return true;
- } else {
- return false;
- }
- }
-
- public boolean hasPassphraseChanged() {
- if (mNoPassphrase != null) {
- if (mNoPassphrase.isChecked()) {
- return mIsPassphraseSet;
- } else {
- return (mNewPassphrase != null && !mNewPassphrase.equals(""));
- }
- } else {
- return false;
- }
- }
-
- private void saveClicked() {
- final long masterKeyId = getMasterKeyId();
- if (needsSaving()) { //make sure, as some versions don't support invalidateOptionsMenu
- try {
- if (!isPassphraseSet()) {
- throw new PgpGeneralException(this.getString(R.string.set_a_passphrase));
- }
-
- String passphrase;
- if (mIsPassphraseSet) {
- passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
- } else {
- passphrase = "";
- }
- if (passphrase == null) {
- PassphraseDialogFragment.show(this, masterKeyId,
- new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(
- EditKeyActivity.this, masterKeyId);
- checkEmptyIDsWanted();
- }
- }
- });
- } else {
- mCurrentPassphrase = passphrase;
- checkEmptyIDsWanted();
- }
- } catch (PgpGeneralException e) {
- AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()),
- AppMsg.STYLE_ALERT).show();
- }
- } else {
- AppMsg.makeText(this, R.string.error_change_something_first, AppMsg.STYLE_ALERT).show();
- }
- }
-
- private void checkEmptyIDsWanted() {
- try {
- ArrayList userIDs = getUserIds(mUserIdsView);
- List newIDs = mUserIdsView.getNewIDFlags();
- ArrayList originalIDs = mUserIdsView.getOriginalIDs();
- int curID = 0;
- for (String userID : userIDs) {
- if (userID.equals("") && (!userID.equals(originalIDs.get(curID)) || newIDs.get(curID))) {
- CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(
- EditKeyActivity.this);
-
- alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
- alert.setTitle(R.string.warning);
- alert.setMessage(EditKeyActivity.this.getString(R.string.ask_empty_id_ok));
-
- alert.setPositiveButton(EditKeyActivity.this.getString(android.R.string.yes),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- finallySaveClicked();
- }
- }
- );
- alert.setNegativeButton(this.getString(android.R.string.no),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- }
- }
- );
- alert.setCancelable(false);
- alert.show();
- return;
- }
- curID++;
- }
- } catch (PgpGeneralException e) {
- Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage()));
- AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()), AppMsg.STYLE_ALERT).show();
- }
- finallySaveClicked();
- }
-
- private boolean[] toPrimitiveArray(final List booleanList) {
- final boolean[] primitives = new boolean[booleanList.size()];
- int index = 0;
- for (Boolean object : booleanList) {
- primitives[index++] = object;
- }
- return primitives;
- }
-
- private void finallySaveClicked() {
- /*
- try {
- // Send all information needed to service to edit key in other thread
- Intent intent = new Intent(this, KeychainIntentService.class);
-
- intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING);
-
- OldSaveKeyringParcel saveParams = new OldSaveKeyringParcel();
- saveParams.userIds = getUserIds(mUserIdsView);
- saveParams.originalIDs = mUserIdsView.getOriginalIDs();
- saveParams.deletedIDs = mUserIdsView.getDeletedIDs();
- saveParams.newIDs = toPrimitiveArray(mUserIdsView.getNewIDFlags());
- saveParams.primaryIDChanged = mUserIdsView.primaryChanged();
- saveParams.moddedKeys = toPrimitiveArray(mKeysView.getNeedsSavingArray());
- saveParams.deletedKeys = mKeysView.getDeletedKeys();
- saveParams.keysExpiryDates = getKeysExpiryDates(mKeysView);
- saveParams.keysUsages = getKeysUsages(mKeysView);
- saveParams.newPassphrase = mNewPassphrase;
- saveParams.oldPassphrase = mCurrentPassphrase;
- saveParams.newKeys = toPrimitiveArray(mKeysView.getNewKeysArray());
- saveParams.keys = getKeys(mKeysView);
- saveParams.originalPrimaryID = mUserIdsView.getOriginalPrimaryID();
-
- // fill values for this action
- Bundle data = new Bundle();
- data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, mMasterCanSign);
- data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, saveParams);
-
- intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Message is received after saving is done in KeychainIntentService
- KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this,
- getString(R.string.progress_saving), ProgressDialog.STYLE_HORIZONTAL) {
- public void handleMessage(Message message) {
- // handle messages by standard KeychainIntentServiceHandler first
- super.handleMessage(message);
-
- if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- Intent data = new Intent();
-
- // return uri pointing to new created key
- Uri uri = KeyRings.buildGenericKeyRingUri(getMasterKeyId());
- data.setData(uri);
-
- setResult(RESULT_OK, data);
- finish();
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(saveHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- saveHandler.showProgressDialog(this);
-
- // start service with intent
- startService(intent);
- } catch (PgpGeneralException e) {
- Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage()));
- AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()),
- AppMsg.STYLE_ALERT).show();
- }
- */
- }
-
- private void cancelClicked() {
- if (needsSaving()) { //ask if we want to save
- CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(
- EditKeyActivity.this);
-
- alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
- alert.setTitle(R.string.warning);
- alert.setMessage(EditKeyActivity.this.getString(R.string.ask_save_changed_key));
-
- alert.setPositiveButton(EditKeyActivity.this.getString(android.R.string.yes),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- saveClicked();
- }
- });
- alert.setNegativeButton(this.getString(android.R.string.no),
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- dialog.dismiss();
- setResult(RESULT_CANCELED);
- finish();
- }
- });
- alert.setCancelable(false);
- alert.show();
- } else {
- setResult(RESULT_CANCELED);
- finish();
- }
- }
-
- /**
- * Returns user ids from the SectionView
- *
- * @param userIdsView
- * @return
- */
- private ArrayList getUserIds(SectionView userIdsView) throws PgpGeneralException {
- ArrayList userIds = new ArrayList();
-
- ViewGroup userIdEditors = userIdsView.getEditors();
-
- boolean gotMainUserId = false;
- for (int i = 0; i < userIdEditors.getChildCount(); ++i) {
- UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i);
- String userId;
- userId = editor.getValue();
-
- if (editor.isMainUserId()) {
- userIds.add(0, userId);
- gotMainUserId = true;
- } else {
- userIds.add(userId);
- }
- }
-
- if (userIds.size() == 0) {
- throw new PgpGeneralException(getString(R.string.error_key_needs_a_user_id));
- }
-
- if (!gotMainUserId) {
- throw new PgpGeneralException(getString(R.string.error_main_user_id_must_not_be_empty));
- }
-
- return userIds;
- }
-
- /**
- * Returns keys from the SectionView
- *
- * @param keysView
- * @return
- */
- private ArrayList getKeys(SectionView keysView) throws PgpGeneralException {
- ArrayList keys = new ArrayList();
-
- ViewGroup keyEditors = keysView.getEditors();
-
- if (keyEditors.getChildCount() == 0) {
- throw new PgpGeneralException(getString(R.string.error_key_needs_master_key));
- }
-
- for (int i = 0; i < keyEditors.getChildCount(); ++i) {
- KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
- keys.add(editor.getValue());
- }
-
- return keys;
- }
-
- /**
- * Returns usage selections of keys from the SectionView
- *
- * @param keysView
- * @return
- */
- private ArrayList getKeysUsages(SectionView keysView) throws PgpGeneralException {
- ArrayList keysUsages = new ArrayList();
-
- ViewGroup keyEditors = keysView.getEditors();
-
- if (keyEditors.getChildCount() == 0) {
- throw new PgpGeneralException(getString(R.string.error_key_needs_master_key));
- }
-
- for (int i = 0; i < keyEditors.getChildCount(); ++i) {
- KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
- keysUsages.add(editor.getUsage());
- }
-
- return keysUsages;
- }
-
- private ArrayList getKeysExpiryDates(SectionView keysView) throws PgpGeneralException {
- ArrayList keysExpiryDates = new ArrayList();
-
- ViewGroup keyEditors = keysView.getEditors();
-
- if (keyEditors.getChildCount() == 0) {
- throw new PgpGeneralException(getString(R.string.error_key_needs_master_key));
- }
-
- for (int i = 0; i < keyEditors.getChildCount(); ++i) {
- KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
- keysExpiryDates.add(editor.getExpiryDate());
- }
-
- return keysExpiryDates;
- }
-
- private void updatePassphraseButtonText() {
- mChangePassphrase.setText(isPassphraseSet() ? getString(R.string.btn_change_passphrase)
- : getString(R.string.btn_set_passphrase));
+ // Add the fragment to the 'fragment_container' FrameLayout
+ // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
+ getSupportFragmentManager().beginTransaction()
+ .replace(R.id.edit_key_fragment_container, mEditKeyFragment)
+ .commitAllowingStateLoss();
+ // do it immediately!
+ getSupportFragmentManager().executePendingTransactions();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java
deleted file mode 100644
index b45e8a6bb..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Log;
-
-public class EditKeyActivityNew extends ActionBarActivity {
-
- private EditKeyFragment mEditKeyFragment;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.edit_key_activity_new);
-
- Uri dataUri = getIntent().getData();
- if (dataUri == null) {
- Log.e(Constants.TAG, "Data missing. Should be Uri of key!");
- finish();
- return;
- }
-
- loadFragment(savedInstanceState, dataUri);
- }
-
- private void loadFragment(Bundle savedInstanceState, Uri dataUri) {
- // However, if we're being restored from a previous state,
- // then we don't need to do anything and should return or else
- // we could end up with overlapping fragments.
- if (savedInstanceState != null) {
- return;
- }
-
- // Create an instance of the fragment
- mEditKeyFragment = EditKeyFragment.newInstance(dataUri);
-
- // Add the fragment to the 'fragment_container' FrameLayout
- // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.edit_key_fragment_container, mEditKeyFragment)
- .commitAllowingStateLoss();
- // do it immediately!
- getSupportFragmentManager().executePendingTransactions();
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java
new file mode 100644
index 000000000..51457cd45
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (C) 2012-2014 Dominik Schürmann
+ * Copyright (C) 2010-2014 Thialfihar
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v4.app.ActivityCompat;
+import android.support.v7.app.ActionBarActivity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.LinearLayout;
+import android.widget.Toast;
+
+import com.devspark.appmsg.AppMsg;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.ActionBarHelper;
+import org.sufficientlysecure.keychain.helper.ExportHelper;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.UncachedSecretKey;
+import org.sufficientlysecure.keychain.pgp.WrappedSecretKey;
+import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
+import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
+import org.sufficientlysecure.keychain.ui.widget.Editor;
+import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener;
+import org.sufficientlysecure.keychain.ui.widget.KeyEditor;
+import org.sufficientlysecure.keychain.ui.widget.SectionView;
+import org.sufficientlysecure.keychain.ui.widget.UserIdEditor;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Vector;
+
+public class EditKeyActivityOld extends ActionBarActivity implements EditorListener {
+
+ // Actions for internal use only:
+ public static final String ACTION_CREATE_KEY = Constants.INTENT_PREFIX + "CREATE_KEY";
+ public static final String ACTION_EDIT_KEY = Constants.INTENT_PREFIX + "EDIT_KEY";
+
+ // possible extra keys
+ public static final String EXTRA_USER_IDS = "user_ids";
+ public static final String EXTRA_NO_PASSPHRASE = "no_passphrase";
+ public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generate_default_keys";
+
+ // EDIT
+ private Uri mDataUri;
+
+ private SectionView mUserIdsView;
+ private SectionView mKeysView;
+
+ private String mCurrentPassphrase = null;
+ private String mNewPassphrase = null;
+ private String mSavedNewPassphrase = null;
+ private boolean mIsPassphraseSet;
+ private boolean mNeedsSaving;
+ private boolean mIsBrandNewKeyring = false;
+
+ private Button mChangePassphrase;
+
+ private CheckBox mNoPassphrase;
+
+ Vector mUserIds;
+ Vector mKeys;
+ Vector mKeysUsages;
+ boolean mMasterCanSign = true;
+
+ ExportHelper mExportHelper;
+
+ public boolean needsSaving() {
+ mNeedsSaving = (mUserIdsView == null) ? false : mUserIdsView.needsSaving();
+ mNeedsSaving |= (mKeysView == null) ? false : mKeysView.needsSaving();
+ mNeedsSaving |= hasPassphraseChanged();
+ mNeedsSaving |= mIsBrandNewKeyring;
+ return mNeedsSaving;
+ }
+
+
+ public void somethingChanged() {
+ ActivityCompat.invalidateOptionsMenu(this);
+ }
+
+ public void onDeleted(Editor e, boolean wasNewItem) {
+ somethingChanged();
+ }
+
+ public void onEdited() {
+ somethingChanged();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mExportHelper = new ExportHelper(this);
+
+ // Inflate a "Done"/"Cancel" custom action bar view
+ ActionBarHelper.setTwoButtonView(getSupportActionBar(),
+ R.string.btn_save, R.drawable.ic_action_save,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Save
+ saveClicked();
+ }
+ }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Cancel
+ cancelClicked();
+ }
+ }
+ );
+
+ mUserIds = new Vector();
+ mKeys = new Vector();
+ mKeysUsages = new Vector();
+
+ // Catch Intents opened from other apps
+ Intent intent = getIntent();
+ String action = intent.getAction();
+ if (ACTION_CREATE_KEY.equals(action)) {
+ handleActionCreateKey(intent);
+ } else if (ACTION_EDIT_KEY.equals(action)) {
+ handleActionEditKey(intent);
+ }
+ }
+
+ /**
+ * Handle intent action to create new key
+ *
+ * @param intent
+ */
+ private void handleActionCreateKey(Intent intent) {
+ Bundle extras = intent.getExtras();
+
+ mCurrentPassphrase = "";
+ mIsBrandNewKeyring = true;
+
+ if (extras != null) {
+ // if userId is given, prefill the fields
+ if (extras.containsKey(EXTRA_USER_IDS)) {
+ Log.d(Constants.TAG, "UserIds are given!");
+ mUserIds.add(extras.getString(EXTRA_USER_IDS));
+ }
+
+ // if no passphrase is given
+ if (extras.containsKey(EXTRA_NO_PASSPHRASE)) {
+ boolean noPassphrase = extras.getBoolean(EXTRA_NO_PASSPHRASE);
+ if (noPassphrase) {
+ // check "no passphrase" checkbox and remove button
+ mNoPassphrase.setChecked(true);
+ mChangePassphrase.setVisibility(View.GONE);
+ }
+ }
+
+ // generate key
+ if (extras.containsKey(EXTRA_GENERATE_DEFAULT_KEYS)) {
+ /*
+ boolean generateDefaultKeys = extras.getBoolean(EXTRA_GENERATE_DEFAULT_KEYS);
+ if (generateDefaultKeys) {
+
+ // fill values for this action
+ Bundle data = new Bundle();
+ data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE,
+ mCurrentPassphrase);
+
+ serviceIntent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Message is received after generating is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
+ this, getResources().getQuantityString(R.plurals.progress_generating, 1),
+ ProgressDialog.STYLE_HORIZONTAL, true,
+
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ // Stop key generation on cancel
+ stopService(serviceIntent);
+ EditKeyActivity.this.setResult(Activity.RESULT_CANCELED);
+ EditKeyActivity.this.finish();
+ }
+ }) {
+
+ @Override
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ // get new key from data bundle returned from service
+ Bundle data = message.getDataAsStringList();
+
+ ArrayList newKeys =
+ PgpConversionHelper.BytesToPGPSecretKeyList(data
+ .getByteArray(KeychainIntentService.RESULT_NEW_KEY));
+
+ ArrayList keyUsageFlags = data.getIntegerArrayList(
+ KeychainIntentService.RESULT_KEY_USAGES);
+
+ if (newKeys.size() == keyUsageFlags.size()) {
+ for (int i = 0; i < newKeys.size(); ++i) {
+ mKeys.add(newKeys.get(i));
+ mKeysUsages.add(keyUsageFlags.get(i));
+ }
+ }
+
+ buildLayout(true);
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ serviceIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ saveHandler.showProgressDialog(this);
+
+ // start service with intent
+ startService(serviceIntent);
+ }
+ */
+ }
+ } else {
+ buildLayout(false);
+ }
+ }
+
+ /**
+ * Handle intent action to edit existing key
+ *
+ * @param intent
+ */
+ private void handleActionEditKey(Intent intent) {
+ mDataUri = intent.getData();
+ if (mDataUri == null) {
+ Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!");
+ finish();
+ } else {
+ Log.d(Constants.TAG, "uri: " + mDataUri);
+
+ try {
+ Uri secretUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
+ WrappedSecretKeyRing keyRing = new ProviderHelper(this).getWrappedSecretKeyRing(secretUri);
+
+ mMasterCanSign = keyRing.getSubKey().canCertify();
+ for (WrappedSecretKey key : keyRing.secretKeyIterator()) {
+ // Turn into uncached instance
+ mKeys.add(key.getUncached());
+ mKeysUsages.add(key.getKeyUsage()); // get usage when view is created
+ }
+
+ boolean isSet = false;
+ for (String userId : keyRing.getSubKey().getUserIds()) {
+ Log.d(Constants.TAG, "Added userId " + userId);
+ if (!isSet) {
+ isSet = true;
+ String[] parts = KeyRing.splitUserId(userId);
+ if (parts[0] != null) {
+ setTitle(parts[0]);
+ }
+ }
+ mUserIds.add(userId);
+ }
+
+ buildLayout(false);
+
+ mCurrentPassphrase = "";
+ mIsPassphraseSet = keyRing.hasPassphrase();
+ if (!mIsPassphraseSet) {
+ // check "no passphrase" checkbox and remove button
+ mNoPassphrase.setChecked(true);
+ mChangePassphrase.setVisibility(View.GONE);
+ }
+
+ } catch (ProviderHelper.NotFoundException e) {
+ Log.e(Constants.TAG, "Keyring not found: " + e.getMessage(), e);
+ Toast.makeText(this, R.string.error_no_secret_key_found, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+
+ }
+ }
+
+ /**
+ * Shows the dialog to set a new passphrase
+ */
+ private void showSetPassphraseDialog() {
+ // Message is received after passphrase is cached
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) {
+ Bundle data = message.getData();
+
+ // set new returned passphrase!
+ mNewPassphrase = data
+ .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE);
+
+ updatePassphraseButtonText();
+ somethingChanged();
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+
+ // set title based on isPassphraseSet()
+ int title;
+ if (isPassphraseSet()) {
+ title = R.string.title_change_passphrase;
+ } else {
+ title = R.string.title_set_passphrase;
+ }
+
+ SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
+ messenger, null, title);
+
+ setPassphraseDialog.show(getSupportFragmentManager(), "setPassphraseDialog");
+ }
+
+ /**
+ * Build layout based on mUserId, mKeys and mKeysUsages Vectors. It creates Views for every user
+ * id and key.
+ *
+ * @param newKeys
+ */
+ private void buildLayout(boolean newKeys) {
+ setContentView(R.layout.edit_key_activity);
+
+ // find views
+ mChangePassphrase = (Button) findViewById(R.id.edit_key_btn_change_passphrase);
+ mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase);
+ // Build layout based on given userIds and keys
+
+ LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
+ if (mIsPassphraseSet) {
+ mChangePassphrase.setText(getString(R.string.btn_change_passphrase));
+ }
+ mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
+ mUserIdsView.setType(SectionView.TYPE_USER_ID);
+ mUserIdsView.setCanBeEdited(mMasterCanSign);
+ mUserIdsView.setUserIds(mUserIds);
+ mUserIdsView.setEditorListener(this);
+ container.addView(mUserIdsView);
+ mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
+ mKeysView.setType(SectionView.TYPE_KEY);
+ mKeysView.setCanBeEdited(mMasterCanSign);
+ mKeysView.setKeys(mKeys, mKeysUsages, newKeys);
+ mKeysView.setEditorListener(this);
+ container.addView(mKeysView);
+
+ updatePassphraseButtonText();
+
+ mChangePassphrase.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showSetPassphraseDialog();
+ }
+ });
+
+ // disable passphrase when no passphrase checkbox is checked!
+ mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ // remove passphrase
+ mSavedNewPassphrase = mNewPassphrase;
+ mNewPassphrase = "";
+ mChangePassphrase.setVisibility(View.GONE);
+ } else {
+ mNewPassphrase = mSavedNewPassphrase;
+ mChangePassphrase.setVisibility(View.VISIBLE);
+ }
+ somethingChanged();
+ }
+ });
+ }
+
+ private long getMasterKeyId() {
+ if (mKeysView.getEditors().getChildCount() == 0) {
+ return 0;
+ }
+ return ((KeyEditor) mKeysView.getEditors().getChildAt(0)).getValue().getKeyId();
+ }
+
+ public boolean isPassphraseSet() {
+ if (mNoPassphrase.isChecked()) {
+ return true;
+ } else if ((mIsPassphraseSet)
+ || (mNewPassphrase != null && !mNewPassphrase.equals(""))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean hasPassphraseChanged() {
+ if (mNoPassphrase != null) {
+ if (mNoPassphrase.isChecked()) {
+ return mIsPassphraseSet;
+ } else {
+ return (mNewPassphrase != null && !mNewPassphrase.equals(""));
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private void saveClicked() {
+ final long masterKeyId = getMasterKeyId();
+ if (needsSaving()) { //make sure, as some versions don't support invalidateOptionsMenu
+ try {
+ if (!isPassphraseSet()) {
+ throw new PgpGeneralException(this.getString(R.string.set_a_passphrase));
+ }
+
+ String passphrase;
+ if (mIsPassphraseSet) {
+ passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
+ } else {
+ passphrase = "";
+ }
+ if (passphrase == null) {
+ PassphraseDialogFragment.show(this, masterKeyId,
+ new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
+ mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(
+ EditKeyActivityOld.this, masterKeyId);
+ checkEmptyIDsWanted();
+ }
+ }
+ });
+ } else {
+ mCurrentPassphrase = passphrase;
+ checkEmptyIDsWanted();
+ }
+ } catch (PgpGeneralException e) {
+ AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()),
+ AppMsg.STYLE_ALERT).show();
+ }
+ } else {
+ AppMsg.makeText(this, R.string.error_change_something_first, AppMsg.STYLE_ALERT).show();
+ }
+ }
+
+ private void checkEmptyIDsWanted() {
+ try {
+ ArrayList userIDs = getUserIds(mUserIdsView);
+ List newIDs = mUserIdsView.getNewIDFlags();
+ ArrayList originalIDs = mUserIdsView.getOriginalIDs();
+ int curID = 0;
+ for (String userID : userIDs) {
+ if (userID.equals("") && (!userID.equals(originalIDs.get(curID)) || newIDs.get(curID))) {
+ CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(
+ EditKeyActivityOld.this);
+
+ alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
+ alert.setTitle(R.string.warning);
+ alert.setMessage(EditKeyActivityOld.this.getString(R.string.ask_empty_id_ok));
+
+ alert.setPositiveButton(EditKeyActivityOld.this.getString(android.R.string.yes),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ finallySaveClicked();
+ }
+ }
+ );
+ alert.setNegativeButton(this.getString(android.R.string.no),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ }
+ );
+ alert.setCancelable(false);
+ alert.show();
+ return;
+ }
+ curID++;
+ }
+ } catch (PgpGeneralException e) {
+ Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage()));
+ AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()), AppMsg.STYLE_ALERT).show();
+ }
+ finallySaveClicked();
+ }
+
+ private boolean[] toPrimitiveArray(final List booleanList) {
+ final boolean[] primitives = new boolean[booleanList.size()];
+ int index = 0;
+ for (Boolean object : booleanList) {
+ primitives[index++] = object;
+ }
+ return primitives;
+ }
+
+ private void finallySaveClicked() {
+ /*
+ try {
+ // Send all information needed to service to edit key in other thread
+ Intent intent = new Intent(this, KeychainIntentService.class);
+
+ intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING);
+
+ OldSaveKeyringParcel saveParams = new OldSaveKeyringParcel();
+ saveParams.userIds = getUserIds(mUserIdsView);
+ saveParams.originalIDs = mUserIdsView.getOriginalIDs();
+ saveParams.deletedIDs = mUserIdsView.getDeletedIDs();
+ saveParams.newIDs = toPrimitiveArray(mUserIdsView.getNewIDFlags());
+ saveParams.primaryIDChanged = mUserIdsView.primaryChanged();
+ saveParams.moddedKeys = toPrimitiveArray(mKeysView.getNeedsSavingArray());
+ saveParams.deletedKeys = mKeysView.getDeletedKeys();
+ saveParams.keysExpiryDates = getKeysExpiryDates(mKeysView);
+ saveParams.keysUsages = getKeysUsages(mKeysView);
+ saveParams.newPassphrase = mNewPassphrase;
+ saveParams.oldPassphrase = mCurrentPassphrase;
+ saveParams.newKeys = toPrimitiveArray(mKeysView.getNewKeysArray());
+ saveParams.keys = getKeys(mKeysView);
+ saveParams.originalPrimaryID = mUserIdsView.getOriginalPrimaryID();
+
+ // fill values for this action
+ Bundle data = new Bundle();
+ data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, mMasterCanSign);
+ data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, saveParams);
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Message is received after saving is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this,
+ getString(R.string.progress_saving), ProgressDialog.STYLE_HORIZONTAL) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ Intent data = new Intent();
+
+ // return uri pointing to new created key
+ Uri uri = KeyRings.buildGenericKeyRingUri(getMasterKeyId());
+ data.setData(uri);
+
+ setResult(RESULT_OK, data);
+ finish();
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ saveHandler.showProgressDialog(this);
+
+ // start service with intent
+ startService(intent);
+ } catch (PgpGeneralException e) {
+ Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage()));
+ AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()),
+ AppMsg.STYLE_ALERT).show();
+ }
+ */
+ }
+
+ private void cancelClicked() {
+ if (needsSaving()) { //ask if we want to save
+ CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(
+ EditKeyActivityOld.this);
+
+ alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
+ alert.setTitle(R.string.warning);
+ alert.setMessage(EditKeyActivityOld.this.getString(R.string.ask_save_changed_key));
+
+ alert.setPositiveButton(EditKeyActivityOld.this.getString(android.R.string.yes),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ saveClicked();
+ }
+ });
+ alert.setNegativeButton(this.getString(android.R.string.no),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ });
+ alert.setCancelable(false);
+ alert.show();
+ } else {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ /**
+ * Returns user ids from the SectionView
+ *
+ * @param userIdsView
+ * @return
+ */
+ private ArrayList getUserIds(SectionView userIdsView) throws PgpGeneralException {
+ ArrayList userIds = new ArrayList();
+
+ ViewGroup userIdEditors = userIdsView.getEditors();
+
+ boolean gotMainUserId = false;
+ for (int i = 0; i < userIdEditors.getChildCount(); ++i) {
+ UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i);
+ String userId;
+ userId = editor.getValue();
+
+ if (editor.isMainUserId()) {
+ userIds.add(0, userId);
+ gotMainUserId = true;
+ } else {
+ userIds.add(userId);
+ }
+ }
+
+ if (userIds.size() == 0) {
+ throw new PgpGeneralException(getString(R.string.error_key_needs_a_user_id));
+ }
+
+ if (!gotMainUserId) {
+ throw new PgpGeneralException(getString(R.string.error_main_user_id_must_not_be_empty));
+ }
+
+ return userIds;
+ }
+
+ /**
+ * Returns keys from the SectionView
+ *
+ * @param keysView
+ * @return
+ */
+ private ArrayList getKeys(SectionView keysView) throws PgpGeneralException {
+ ArrayList keys = new ArrayList();
+
+ ViewGroup keyEditors = keysView.getEditors();
+
+ if (keyEditors.getChildCount() == 0) {
+ throw new PgpGeneralException(getString(R.string.error_key_needs_master_key));
+ }
+
+ for (int i = 0; i < keyEditors.getChildCount(); ++i) {
+ KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
+ keys.add(editor.getValue());
+ }
+
+ return keys;
+ }
+
+ /**
+ * Returns usage selections of keys from the SectionView
+ *
+ * @param keysView
+ * @return
+ */
+ private ArrayList getKeysUsages(SectionView keysView) throws PgpGeneralException {
+ ArrayList keysUsages = new ArrayList();
+
+ ViewGroup keyEditors = keysView.getEditors();
+
+ if (keyEditors.getChildCount() == 0) {
+ throw new PgpGeneralException(getString(R.string.error_key_needs_master_key));
+ }
+
+ for (int i = 0; i < keyEditors.getChildCount(); ++i) {
+ KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
+ keysUsages.add(editor.getUsage());
+ }
+
+ return keysUsages;
+ }
+
+ private ArrayList getKeysExpiryDates(SectionView keysView) throws PgpGeneralException {
+ ArrayList keysExpiryDates = new ArrayList();
+
+ ViewGroup keyEditors = keysView.getEditors();
+
+ if (keyEditors.getChildCount() == 0) {
+ throw new PgpGeneralException(getString(R.string.error_key_needs_master_key));
+ }
+
+ for (int i = 0; i < keyEditors.getChildCount(); ++i) {
+ KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
+ keysExpiryDates.add(editor.getExpiryDate());
+ }
+
+ return keysExpiryDates;
+ }
+
+ private void updatePassphraseButtonText() {
+ mChangePassphrase.setText(isPassphraseSet() ? getString(R.string.btn_change_passphrase)
+ : getString(R.string.btn_set_passphrase));
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
index b6a95a517..c76dc0164 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -37,6 +37,7 @@ import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
+import org.spongycastle.bcpg.sig.KeyFlags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
@@ -50,38 +51,48 @@ import org.sufficientlysecure.keychain.service.OperationResults;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
+import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
-import org.sufficientlysecure.keychain.ui.adapter.UserIdsArrayAdapter;
-import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment;
+import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter;
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
+import java.util.ArrayList;
+
public class EditKeyFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks {
public static final String ARG_DATA_URI = "uri";
private ListView mUserIdsList;
- private ListView mKeysList;
+ private ListView mSubkeysList;
private ListView mUserIdsAddedList;
- private ListView mKeysAddedList;
+ private ListView mSubkeysAddedList;
private View mChangePassphrase;
private View mAddUserId;
- private View mAddKey;
+ private View mAddSubkey;
private static final int LOADER_ID_USER_IDS = 0;
- private static final int LOADER_ID_KEYS = 1;
+ private static final int LOADER_ID_SUBKEYS = 1;
+ // cursor adapter
private UserIdsAdapter mUserIdsAdapter;
- private SubkeysAdapter mKeysAdapter;
- private UserIdsArrayAdapter mUserIdsAddedAdapter;
+ private SubkeysAdapter mSubkeysAdapter;
+
+ // array adapter
+ private UserIdsAddedAdapter mUserIdsAddedAdapter;
+ private SubkeysAddedAdapter mSubkeysAddedAdapter;
+
+ private ArrayList mUserIdsAddedData;
private Uri mDataUri;
private SaveKeyringParcel mSaveKeyringParcel;
+ private String mCurrentPassphrase;
+
/**
* Creates new instance of this fragment
*/
@@ -102,12 +113,12 @@ public class EditKeyFragment extends LoaderFragment implements
View view = inflater.inflate(R.layout.edit_key_fragment, getContainer());
mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids);
- mKeysList = (ListView) view.findViewById(R.id.edit_key_keys);
+ mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys);
mUserIdsAddedList = (ListView) view.findViewById(R.id.edit_key_user_ids_added);
- mKeysAddedList = (ListView) view.findViewById(R.id.edit_key_keys_added);
+ mSubkeysAddedList = (ListView) view.findViewById(R.id.edit_key_subkeys_added);
mChangePassphrase = view.findViewById(R.id.edit_key_action_change_passphrase);
mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id);
- mAddKey = view.findViewById(R.id.edit_key_action_add_key);
+ mAddSubkey = view.findViewById(R.id.edit_key_action_add_key);
return root;
}
@@ -123,7 +134,7 @@ public class EditKeyFragment extends LoaderFragment implements
@Override
public void onClick(View v) {
// Save
- save();
+ save(mCurrentPassphrase);
}
}, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel,
new OnClickListener() {
@@ -164,6 +175,8 @@ public class EditKeyFragment extends LoaderFragment implements
getActivity().finish();
}
+ cachePassphraseForEdit();
+
mChangePassphrase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -178,6 +191,13 @@ public class EditKeyFragment extends LoaderFragment implements
}
});
+ mAddSubkey.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ addSubkey();
+ }
+ });
+
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, mSaveKeyringParcel);
mUserIdsList.setAdapter(mUserIdsAdapter);
@@ -189,17 +209,21 @@ public class EditKeyFragment extends LoaderFragment implements
}
});
- mUserIdsAddedAdapter = new UserIdsArrayAdapter(getActivity());
+ // TODO: mUserIdsAddedData and SaveParcel from savedInstance?!
+ mUserIdsAddedData = new ArrayList();
+ mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mUserIdsAddedData);
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
- mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds);
- mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
- mKeysList.setAdapter(mKeysAdapter);
+ mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
+ mSubkeysList.setAdapter(mSubkeysAdapter);
+
+ mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.addSubKeys);
+ mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
- getLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
+ getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, this);
}
public Loader onCreateLoader(int id, Bundle args) {
@@ -212,10 +236,10 @@ public class EditKeyFragment extends LoaderFragment implements
UserIdsAdapter.USER_IDS_PROJECTION, null, null, null);
}
- case LOADER_ID_KEYS: {
+ case LOADER_ID_SUBKEYS: {
Uri baseUri = KeychainContract.Keys.buildKeysUri(mDataUri);
return new CursorLoader(getActivity(), baseUri,
- SubkeysAdapter.KEYS_PROJECTION, null, null, null);
+ SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null);
}
default:
@@ -231,8 +255,8 @@ public class EditKeyFragment extends LoaderFragment implements
mUserIdsAdapter.swapCursor(data);
break;
- case LOADER_ID_KEYS:
- mKeysAdapter.swapCursor(data);
+ case LOADER_ID_SUBKEYS:
+ mSubkeysAdapter.swapCursor(data);
break;
}
@@ -248,8 +272,8 @@ public class EditKeyFragment extends LoaderFragment implements
case LOADER_ID_USER_IDS:
mUserIdsAdapter.swapCursor(null);
break;
- case LOADER_ID_KEYS:
- mKeysAdapter.swapCursor(null);
+ case LOADER_ID_SUBKEYS:
+ mSubkeysAdapter.swapCursor(null);
break;
}
}
@@ -262,11 +286,9 @@ public class EditKeyFragment extends LoaderFragment implements
if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) {
Bundle data = message.getData();
- // set new returned passphrase!
- String newPassphrase = data
+ // cache new returned passphrase!
+ mSaveKeyringParcel.newPassphrase = data
.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE);
-
- mSaveKeyringParcel.newPassphrase = newPassphrase;
}
}
};
@@ -275,7 +297,7 @@ public class EditKeyFragment extends LoaderFragment implements
Messenger messenger = new Messenger(returnHandler);
SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
- messenger, R.string.title_change_passphrase);
+ messenger, mCurrentPassphrase, R.string.title_change_passphrase);
setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog");
}
@@ -321,56 +343,41 @@ public class EditKeyFragment extends LoaderFragment implements
}
private void addUserId() {
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case AddUserIdDialogFragment.MESSAGE_OKAY:
- Bundle data = message.getData();
- String userId = data.getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID);
-
- if (userId != null) {
- mSaveKeyringParcel.addUserIds.add(userId);
- mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds);
- }
- }
- getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad();
- }
- };
-
- // Create a new Messenger for the communication back
- final Messenger messenger = new Messenger(returnHandler);
-
- DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
- public void run() {
- AddUserIdDialogFragment dialogFragment =
- AddUserIdDialogFragment.newInstance(messenger);
-
- dialogFragment.show(getActivity().getSupportFragmentManager(), "addUserIdDialog");
- }
- });
+ mUserIdsAddedAdapter.add(new UserIdsAddedAdapter.UserIdModel());
}
- private void save() {
- String passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(),
+ private void addSubkey() {
+ // default values
+ mSubkeysAddedAdapter.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null));
+ }
+
+ private void cachePassphraseForEdit() {
+ mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(getActivity(),
mSaveKeyringParcel.mMasterKeyId);
- if (passphrase == null) {
+ if (mCurrentPassphrase == null) {
PassphraseDialogFragment.show(getActivity(), mSaveKeyringParcel.mMasterKeyId,
new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
- saveFinal();
+ mCurrentPassphrase =
+ message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE);
+ Log.d(Constants.TAG, "after caching passphrase");
+ } else {
+ EditKeyFragment.this.getActivity().finish();
}
}
}
);
-
}
-
}
- private void saveFinal() {
+ private void save(String passphrase) {
+ Log.d(Constants.TAG, "add userids to parcel: " + mUserIdsAddedAdapter.getDataAsStringList());
+ Log.d(Constants.TAG, "mSaveKeyringParcel.newPassphrase: " + mSaveKeyringParcel.newPassphrase);
+
+ mSaveKeyringParcel.addUserIds = mUserIdsAddedAdapter.getDataAsStringList();
+
// Message is received after importing is done in KeychainIntentService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
getActivity(),
@@ -381,6 +388,9 @@ public class EditKeyFragment extends LoaderFragment implements
super.handleMessage(message);
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ getActivity().finish();
+
+ // TODO below
// get returned data bundle
Bundle returnData = message.getData();
if (returnData == null) {
@@ -408,6 +418,7 @@ public class EditKeyFragment extends LoaderFragment implements
// fill values for this action
Bundle data = new Bundle();
+ data.putString(KeychainIntentService.SAVE_KEYRING_PASSPHRASE, passphrase);
data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, mSaveKeyringParcel);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 5542cccd1..c98171230 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -298,7 +298,7 @@ public class EncryptActivity extends DrawerActivity implements
// encrypt file based on Uri
mFileFragmentBundle.putParcelableArrayList(EncryptFileFragment.ARG_URIS, uris);
mSwitchToContent = PAGER_CONTENT_FILE;
- } else {
+ } else if (ACTION_ENCRYPT.equals(action)) {
Log.e(Constants.TAG,
"Include the extra 'text' or an Uri with setData() in your Intent!");
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
index 7ce7a06aa..849576284 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
@@ -17,21 +17,33 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
import android.view.Menu;
import android.view.MenuItem;
import com.devspark.appmsg.AppMsg;
+import org.spongycastle.bcpg.sig.KeyFlags;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Constants.choice.algorithm;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ExportHelper;
+import org.sufficientlysecure.keychain.helper.OtherHelper;
+import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
+import java.util.ArrayList;
public class KeyListActivity extends DrawerActivity {
@@ -121,9 +133,42 @@ public class KeyListActivity extends DrawerActivity {
}
private void createKeyExpert() {
- Intent intent = new Intent(this, EditKeyActivity.class);
- intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
- startActivityForResult(intent, 0);
- }
+ Intent intent = new Intent(this, KeychainIntentService.class);
+ intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING);
-}
+ // Message is received after importing is done in KeychainIntentService
+ KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
+ this,
+ getString(R.string.progress_importing),
+ ProgressDialog.STYLE_HORIZONTAL) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
+ Bundle data = message.getData();
+ // OtherHelper.logDebugBundle(data, "message reply");
+ }
+ };
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ SaveKeyringParcel parcel = new SaveKeyringParcel();
+ parcel.addSubKeys.add(new SubkeyAdd(algorithm.rsa, 1024, KeyFlags.CERTIFY_OTHER, null));
+ parcel.addSubKeys.add(new SubkeyAdd(algorithm.rsa, 1024, KeyFlags.SIGN_DATA, null));
+ parcel.addUserIds.add("swagerinho");
+ parcel.newPassphrase = "swag";
+
+ // get selected key entries
+ data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, parcel);
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ saveHandler.showProgressDialog(this);
+
+ startService(intent);
+ }
+}
\ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
index 0940d5632..e2ca50a4c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -47,7 +47,6 @@ import android.view.ViewGroup;
import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.FrameLayout;
-import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
@@ -59,7 +58,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ExportHelper;
import org.sufficientlysecure.keychain.pgp.KeyRing;
-import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.util.Highlighter;
@@ -106,10 +104,10 @@ public class KeyListFragment extends LoaderFragment
@Override
public void onClick(View v) {
- Intent intent = new Intent(getActivity(), EditKeyActivity.class);
- intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
- intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
- intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view
+ Intent intent = new Intent(getActivity(), EditKeyActivityOld.class);
+ intent.setAction(EditKeyActivityOld.ACTION_CREATE_KEY);
+ intent.putExtra(EditKeyActivityOld.EXTRA_GENERATE_DEFAULT_KEYS, true);
+ intent.putExtra(EditKeyActivityOld.EXTRA_USER_IDS, ""); // show user id view
startActivityForResult(intent, 0);
}
});
@@ -205,7 +203,7 @@ public class KeyListFragment extends LoaderFragment
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) {
if (checked) {
- mAdapter.setNewSelection(position, true);
+ mAdapter.setNewSelection(position, checked);
} else {
mAdapter.removeSelection(position);
}
@@ -439,9 +437,7 @@ public class KeyListFragment extends LoaderFragment
private class ItemViewHolder {
TextView mMainUserId;
TextView mMainUserIdRest;
- View mStatusDivider;
FrameLayout mStatusLayout;
- ImageButton mButton;
TextView mRevoked;
ImageView mVerified;
}
@@ -452,9 +448,7 @@ public class KeyListFragment extends LoaderFragment
ItemViewHolder holder = new ItemViewHolder();
holder.mMainUserId = (TextView) view.findViewById(R.id.mainUserId);
holder.mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
- holder.mStatusDivider = view.findViewById(R.id.status_divider);
holder.mStatusLayout = (FrameLayout) view.findViewById(R.id.status_layout);
- holder.mButton = (ImageButton) view.findViewById(R.id.edit);
holder.mRevoked = (TextView) view.findViewById(R.id.revoked);
holder.mVerified = (ImageView) view.findViewById(R.id.verified);
view.setTag(holder);
@@ -491,26 +485,12 @@ public class KeyListFragment extends LoaderFragment
{ // set edit button and revoked info, specific by key type
if (cursor.getInt(KeyListFragment.INDEX_HAS_ANY_SECRET) != 0) {
- // this is a secret key - show the edit mButton
- h.mStatusDivider.setVisibility(View.VISIBLE);
+ // this is a secret key
h.mStatusLayout.setVisibility(View.VISIBLE);
h.mRevoked.setVisibility(View.GONE);
h.mVerified.setVisibility(View.GONE);
- h.mButton.setVisibility(View.VISIBLE);
-
- final long id = cursor.getLong(INDEX_MASTER_KEY_ID);
- h.mButton.setOnClickListener(new OnClickListener() {
- public void onClick(View view) {
- Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
- editIntent.setData(KeyRingData.buildSecretKeyRingUri(Long.toString(id)));
- editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
- startActivityForResult(editIntent, 0);
- }
- });
} else {
- // this is a public key - hide the edit mButton, show if it's revoked
- h.mStatusDivider.setVisibility(View.GONE);
- h.mButton.setVisibility(View.GONE);
+ // this is a public key - show if it's revoked
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
boolean isExpired = !cursor.isNull(INDEX_EXPIRY)
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java
index 87ab1bb8c..8634070cc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
@@ -9,14 +26,14 @@ import android.view.animation.AnimationUtils;
import org.sufficientlysecure.keychain.R;
-/** This is a fragment helper class, which implements a generic
+/**
+ * This is a fragment helper class, which implements a generic
* progressbar/container view.
- *
+ *
* To use it in a fragment, simply subclass, use onCreateView to create the
* layout's root view, and ues getContainer() as root view of your subclass.
* The layout shows a progress bar by default, and can be switched to the
* actual contents by calling setContentShown().
- *
*/
public class LoaderFragment extends Fragment {
private boolean mContentShown;
@@ -35,7 +52,6 @@ public class LoaderFragment extends Fragment {
mContentShown = false;
return root;
-
}
protected ViewGroup getContainer() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java
index 4be572b4e..e46637871 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java
@@ -87,7 +87,7 @@ public class ViewKeyKeysFragment extends LoaderFragment implements
setContentShown(false);
Uri baseUri = Keys.buildKeysUri(mDataUri);
return new CursorLoader(getActivity(), baseUri,
- SubkeysAdapter.KEYS_PROJECTION, null, null, null);
+ SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null);
}
public void onLoadFinished(Loader loader, Cursor data) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
index dd48f193c..f0636cf2c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java
@@ -49,7 +49,6 @@ public class ViewKeyMainFragment extends LoaderFragment implements
public static final String ARG_DATA_URI = "uri";
private View mActionEdit;
- private View mActionEditNew;
private View mActionEditDivider;
private View mActionEncrypt;
private View mActionCertify;
@@ -74,7 +73,6 @@ public class ViewKeyMainFragment extends LoaderFragment implements
mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
mActionEdit = view.findViewById(R.id.view_key_action_edit);
- mActionEditNew = view.findViewById(R.id.view_key_action_edit_new);
mActionEditDivider = view.findViewById(R.id.view_key_action_edit_divider);
mActionEncrypt = view.findViewById(R.id.view_key_action_encrypt);
mActionCertify = view.findViewById(R.id.view_key_action_certify);
@@ -118,11 +116,6 @@ public class ViewKeyMainFragment extends LoaderFragment implements
editKey(mDataUri);
}
});
- mActionEditNew.setOnClickListener(new View.OnClickListener() {
- public void onClick(View view) {
- editKeyNew(mDataUri);
- }
- });
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
mUserIds.setAdapter(mUserIdsAdapter);
@@ -259,16 +252,9 @@ public class ViewKeyMainFragment extends LoaderFragment implements
private void editKey(Uri dataUri) {
Intent editIntent = new Intent(getActivity(), EditKeyActivity.class);
editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri));
- editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
- startActivityForResult(editIntent, 0);
- }
-
- private void editKeyNew(Uri dataUri) {
- Intent editIntent = new Intent(getActivity(), EditKeyActivityNew.class);
-// editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri));
- editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri));
- editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
- startActivityForResult(editIntent, 0);
+// editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
+// startActivityForResult(editIntent, 0);
+ startActivity(editIntent);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java
index 20b47ed01..601fc09f9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java
@@ -142,7 +142,7 @@ public class WizardActivity extends ActionBarActivity {
emailView.setThreshold(1); // Start working from first character
emailView.setAdapter(
new ArrayAdapter
- (getActivity(), android.R.layout.simple_dropdown_item_1line,
+ (getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserEmails(getActivity())
)
);
@@ -177,7 +177,7 @@ public class WizardActivity extends ActionBarActivity {
nameView.setThreshold(1); // Start working from first character
nameView.setAdapter(
new ArrayAdapter
- (getActivity(), android.R.layout.simple_dropdown_item_1line,
+ (getActivity(), android.R.layout.simple_spinner_dropdown_item,
ContactHelper.getPossibleUserNames(getActivity())
)
);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index 6d8455589..02b1f31e2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -38,22 +38,11 @@ import java.util.Date;
public class SubkeysAdapter extends CursorAdapter {
private LayoutInflater mInflater;
- private int mIndexKeyId;
- private int mIndexAlgorithm;
- private int mIndexKeySize;
- private int mIndexRank;
- private int mIndexCanCertify;
- private int mIndexCanEncrypt;
- private int mIndexCanSign;
- private int mIndexHasSecret;
- private int mIndexRevokedKey;
- private int mIndexExpiry;
-
private boolean hasAnySecret;
private ColorStateList mDefaultTextColor;
- public static final String[] KEYS_PROJECTION = new String[] {
+ public static final String[] SUBKEYS_PROJECTION = new String[]{
Keys._ID,
Keys.KEY_ID,
Keys.RANK,
@@ -68,24 +57,32 @@ public class SubkeysAdapter extends CursorAdapter {
Keys.EXPIRY,
Keys.FINGERPRINT
};
+ private static final int INDEX_ID = 0;
+ private static final int INDEX_KEY_ID = 1;
+ private static final int INDEX_RANK = 2;
+ private static final int INDEX_ALGORITHM = 3;
+ private static final int INDEX_KEY_SIZE = 4;
+ private static final int INDEX_HAS_SECRET = 5;
+ private static final int INDEX_CAN_CERTIFY = 6;
+ private static final int INDEX_CAN_ENCRYPT = 7;
+ private static final int INDEX_CAN_SIGN = 8;
+ private static final int INDEX_IS_REVOKED = 9;
+ private static final int INDEX_CREATION = 10;
+ private static final int INDEX_EXPIRY = 11;
+ private static final int INDEX_FINGERPRINT = 12;
public SubkeysAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
-
- initIndex(c);
}
@Override
public Cursor swapCursor(Cursor newCursor) {
- initIndex(newCursor);
-
hasAnySecret = false;
- if (newCursor != null) {
- newCursor.moveToFirst();
+ if (newCursor != null && newCursor.moveToFirst()) {
do {
- if (newCursor.getInt(mIndexHasSecret) != 0) {
+ if (newCursor.getInt(INDEX_HAS_SECRET) != 0) {
hasAnySecret = true;
break;
}
@@ -95,27 +92,6 @@ public class SubkeysAdapter extends CursorAdapter {
return super.swapCursor(newCursor);
}
- /**
- * Get column indexes for performance reasons just once in constructor and swapCursor. For a
- * performance comparison see http://stackoverflow.com/a/17999582
- *
- * @param cursor
- */
- private void initIndex(Cursor cursor) {
- if (cursor != null) {
- mIndexKeyId = cursor.getColumnIndexOrThrow(Keys.KEY_ID);
- mIndexAlgorithm = cursor.getColumnIndexOrThrow(Keys.ALGORITHM);
- mIndexKeySize = cursor.getColumnIndexOrThrow(Keys.KEY_SIZE);
- mIndexRank = cursor.getColumnIndexOrThrow(Keys.RANK);
- mIndexCanCertify = cursor.getColumnIndexOrThrow(Keys.CAN_CERTIFY);
- mIndexCanEncrypt = cursor.getColumnIndexOrThrow(Keys.CAN_ENCRYPT);
- mIndexCanSign = cursor.getColumnIndexOrThrow(Keys.CAN_SIGN);
- mIndexHasSecret = cursor.getColumnIndexOrThrow(Keys.HAS_SECRET);
- mIndexRevokedKey = cursor.getColumnIndexOrThrow(Keys.IS_REVOKED);
- mIndexExpiry = cursor.getColumnIndexOrThrow(Keys.EXPIRY);
- }
- }
-
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView keyId = (TextView) view.findViewById(R.id.keyId);
@@ -127,16 +103,16 @@ public class SubkeysAdapter extends CursorAdapter {
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
ImageView revokedKeyIcon = (ImageView) view.findViewById(R.id.ic_revokedKey);
- String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId));
+ String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(INDEX_KEY_ID));
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
context,
- cursor.getInt(mIndexAlgorithm),
- cursor.getInt(mIndexKeySize)
+ cursor.getInt(INDEX_ALGORITHM),
+ cursor.getInt(INDEX_KEY_SIZE)
);
keyId.setText(keyIdStr);
// may be set with additional "stripped" later on
- if (hasAnySecret && cursor.getInt(mIndexHasSecret) == 0) {
+ if (hasAnySecret && cursor.getInt(INDEX_HAS_SECRET) == 0) {
keyDetails.setText(algorithmStr + ", " +
context.getString(R.string.key_stripped));
} else {
@@ -144,13 +120,13 @@ public class SubkeysAdapter extends CursorAdapter {
}
// Set icons according to properties
- masterKeyIcon.setVisibility(cursor.getInt(mIndexRank) == 0 ? View.VISIBLE : View.INVISIBLE);
- certifyIcon.setVisibility(cursor.getInt(mIndexCanCertify) != 0 ? View.VISIBLE : View.GONE);
- encryptIcon.setVisibility(cursor.getInt(mIndexCanEncrypt) != 0 ? View.VISIBLE : View.GONE);
- signIcon.setVisibility(cursor.getInt(mIndexCanSign) != 0 ? View.VISIBLE : View.GONE);
+ masterKeyIcon.setVisibility(cursor.getInt(INDEX_RANK) == 0 ? View.VISIBLE : View.INVISIBLE);
+ certifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE);
+ encryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE);
+ signIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE);
boolean valid = true;
- if (cursor.getInt(mIndexRevokedKey) > 0) {
+ if (cursor.getInt(INDEX_IS_REVOKED) > 0) {
revokedKeyIcon.setVisibility(View.VISIBLE);
valid = false;
@@ -162,17 +138,19 @@ public class SubkeysAdapter extends CursorAdapter {
revokedKeyIcon.setVisibility(View.GONE);
}
- if (!cursor.isNull(mIndexExpiry)) {
- Date expiryDate = new Date(cursor.getLong(mIndexExpiry) * 1000);
+ if (!cursor.isNull(INDEX_EXPIRY)) {
+ Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000);
valid = valid && expiryDate.after(new Date());
keyExpiry.setText(
context.getString(R.string.label_expiry) + ": " +
- DateFormat.getDateFormat(context).format(expiryDate));
+ DateFormat.getDateFormat(context).format(expiryDate)
+ );
} else {
keyExpiry.setText(
context.getString(R.string.label_expiry) + ": " +
- context.getString(R.string.none));
+ context.getString(R.string.none)
+ );
}
// if key is expired or revoked, strike through text
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java
new file mode 100644
index 000000000..25509fee5
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Build;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Patterns;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.ContactHelper;
+import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
+import org.sufficientlysecure.keychain.ui.dialog.CreateKeyDialogFragment;
+import org.sufficientlysecure.keychain.util.Choice;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+
+public class SubkeysAddedAdapter extends ArrayAdapter {
+ private LayoutInflater mInflater;
+ private Activity mActivity;
+
+ public interface OnAlgorithmSelectedListener {
+ public void onAlgorithmSelected(Choice algorithmChoice, int keySize);
+ }
+
+ // hold a private reference to the underlying data List
+ private List mData;
+
+ public SubkeysAddedAdapter(Activity activity, List data) {
+ super(activity, -1, data);
+ mActivity = activity;
+ mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mData = data;
+ }
+
+ static class ViewHolder {
+ public OnAlgorithmSelectedListener mAlgorithmSelectedListener;
+ public Spinner mAlgorithmSpinner;
+ public Spinner mKeySizeSpinner;
+ public TextView mCustomKeyTextView;
+ public EditText mCustomKeyEditText;
+ public TextView mCustomKeyInfoTextView;
+ public ImageButton vDelete;
+ // also hold a reference to the model item
+ public SaveKeyringParcel.SubkeyAdd mModel;
+ }
+
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ // Not recycled, inflate a new view
+ convertView = mInflater.inflate(R.layout.edit_key_subkey_added_item, null);
+ final ViewHolder holder = new ViewHolder();
+ holder.mAlgorithmSpinner = (Spinner) convertView.findViewById(R.id.create_key_algorithm);
+ holder.mKeySizeSpinner = (Spinner) convertView.findViewById(R.id.create_key_size);
+ holder.mCustomKeyTextView = (TextView) convertView.findViewById(R.id.custom_key_size_label);
+ holder.mCustomKeyEditText = (EditText) convertView.findViewById(R.id.custom_key_size_input);
+ holder.mCustomKeyInfoTextView = (TextView) convertView.findViewById(R.id.custom_key_size_info);
+ holder.vDelete = (ImageButton) convertView.findViewById(R.id.subkey_added_item_delete);
+ convertView.setTag(holder);
+
+ holder.mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ Choice newKeyAlgorithmChoice = (Choice) holder.mAlgorithmSpinner.getSelectedItem();
+ // update referenced model item
+ holder.mModel.mAlgorithm = newKeyAlgorithmChoice.getId();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+
+ holder.mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ Choice newKeyAlgorithmChoice = (Choice) holder.mAlgorithmSpinner.getSelectedItem();
+ int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(),
+ getSelectedKeyLength(holder.mKeySizeSpinner, holder.mCustomKeyEditText));
+ // update referenced model item
+ holder.mModel.mKeysize = newKeySize;
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+
+ holder.vDelete.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // remove reference model item from adapter (data and notify about change)
+ SubkeysAddedAdapter.this.remove(holder.mModel);
+ }
+ });
+
+ }
+ final ViewHolder holder = (ViewHolder) convertView.getTag();
+
+ // save reference to model item
+ holder.mModel = getItem(position);
+
+ // TODO
+ boolean wouldBeMasterKey = false;
+// boolean wouldBeMasterKey = (childCount == 0);
+
+ ArrayList choices = new ArrayList();
+ choices.add(new Choice(Constants.choice.algorithm.dsa, mActivity.getResources().getString(
+ R.string.dsa)));
+ if (!wouldBeMasterKey) {
+ choices.add(new Choice(Constants.choice.algorithm.elgamal, mActivity.getResources().getString(
+ R.string.elgamal)));
+ }
+
+ choices.add(new Choice(Constants.choice.algorithm.rsa, mActivity.getResources().getString(
+ R.string.rsa)));
+
+ ArrayAdapter adapter = new ArrayAdapter(mActivity,
+ android.R.layout.simple_spinner_item, choices);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ holder.mAlgorithmSpinner.setAdapter(adapter);
+ // make RSA the default
+ for (int i = 0; i < choices.size(); ++i) {
+ if (choices.get(i).getId() == Constants.choice.algorithm.rsa) {
+ holder.mAlgorithmSpinner.setSelection(i);
+ break;
+ }
+ }
+
+ // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change
+ ArrayAdapter keySizeAdapter = new ArrayAdapter(mActivity, android.R.layout.simple_spinner_item,
+ new ArrayList(Arrays.asList(mActivity.getResources().getStringArray(R.array.rsa_key_size_spinner_values))));
+ keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ holder.mKeySizeSpinner.setAdapter(keySizeAdapter);
+ holder.mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length
+
+ holder.mCustomKeyEditText.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+// setOkButtonAvailability(alertDialog);
+ }
+ });
+
+ holder.mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ setCustomKeyVisibility(holder.mKeySizeSpinner, holder.mCustomKeyEditText,
+ holder.mCustomKeyTextView, holder.mCustomKeyInfoTextView);
+// setOkButtonAvailability(alertDialog);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+
+ holder.mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ setKeyLengthSpinnerValuesForAlgorithm(((Choice) parent.getSelectedItem()).getId(),
+ holder.mKeySizeSpinner, holder.mCustomKeyInfoTextView);
+
+ setCustomKeyVisibility(holder.mKeySizeSpinner, holder.mCustomKeyEditText,
+ holder.mCustomKeyTextView, holder.mCustomKeyInfoTextView);
+// setOkButtonAvailability(alertDialog);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+//
+// holder.vAddress.setText(holder.mModel.address);
+// holder.vAddress.setThreshold(1); // Start working from first character
+// holder.vAddress.setAdapter(mAutoCompleteEmailAdapter);
+//
+// holder.vName.setText(holder.mModel.name);
+// holder.vName.setThreshold(1); // Start working from first character
+// holder.vName.setAdapter(mAutoCompleteNameAdapter);
+//
+// holder.vComment.setText(holder.mModel.comment);
+
+ return convertView;
+ }
+
+
+ private int getSelectedKeyLength(Spinner keySizeSpinner, EditText customKeyEditText) {
+ final String selectedItemString = (String) keySizeSpinner.getSelectedItem();
+ final String customLengthString = mActivity.getResources().getString(R.string.key_size_custom);
+ final boolean customSelected = customLengthString.equals(selectedItemString);
+ String keyLengthString = customSelected ? customKeyEditText.getText().toString() : selectedItemString;
+ int keySize;
+ try {
+ keySize = Integer.parseInt(keyLengthString);
+ } catch (NumberFormatException e) {
+ keySize = 0;
+ }
+ return keySize;
+ }
+
+ /**
+ *
RSA
+ *
for RSA algorithm, key length must be greater than 1024 (according to
+ * #102). Possibility to generate keys bigger
+ * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check
+ * RSA key length plot and
+ * Cryptographic Key Length Recommendation). Also, key length must be a
+ * multiplicity of 8.
+ *
ElGamal
+ *
For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.
+ *
DSA
+ *
For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.
+ *
+ * @return correct key length, according to SpongyCastle specification. Returns -1, if key length is
+ * inappropriate.
+ */
+ private int getProperKeyLength(int algorithmId, int currentKeyLength) {
+ final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192};
+ int properKeyLength = -1;
+ switch (algorithmId) {
+ case Constants.choice.algorithm.rsa:
+ if (currentKeyLength > 1024 && currentKeyLength <= 8192) {
+ properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8);
+ }
+ break;
+ case Constants.choice.algorithm.elgamal:
+ int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length];
+ for (int i = 0; i < elGamalSupportedLengths.length; i++) {
+ elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength);
+ }
+ int minimalValue = Integer.MAX_VALUE;
+ int minimalIndex = -1;
+ for (int i = 0; i < elGammalKeyDiff.length; i++) {
+ if (elGammalKeyDiff[i] <= minimalValue) {
+ minimalValue = elGammalKeyDiff[i];
+ minimalIndex = i;
+ }
+ }
+ properKeyLength = elGamalSupportedLengths[minimalIndex];
+ break;
+ case Constants.choice.algorithm.dsa:
+ if (currentKeyLength >= 512 && currentKeyLength <= 1024) {
+ properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64);
+ }
+ break;
+ }
+ return properKeyLength;
+ }
+
+ // TODO: make this an error message on the field
+// private boolean setOkButtonAvailability(AlertDialog alertDialog) {
+// final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem();
+// final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem());
+// final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize);
+// alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0);
+// }
+
+ private void setCustomKeyVisibility(Spinner keySizeSpinner, EditText customkeyedittext, TextView customKeyTextView, TextView customKeyInfoTextView) {
+ final String selectedItemString = (String) keySizeSpinner.getSelectedItem();
+ final String customLengthString = mActivity.getResources().getString(R.string.key_size_custom);
+ final boolean customSelected = customLengthString.equals(selectedItemString);
+ final int visibility = customSelected ? View.VISIBLE : View.GONE;
+
+ customkeyedittext.setVisibility(visibility);
+ customKeyTextView.setVisibility(visibility);
+ customKeyInfoTextView.setVisibility(visibility);
+
+ // hide keyboard after setting visibility to gone
+ if (visibility == View.GONE) {
+ InputMethodManager imm = (InputMethodManager)
+ mActivity.getSystemService(mActivity.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(customkeyedittext.getWindowToken(), 0);
+ }
+ }
+
+ private void setKeyLengthSpinnerValuesForAlgorithm(int algorithmId, Spinner keySizeSpinner, TextView customKeyInfoTextView) {
+ final ArrayAdapter keySizeAdapter = (ArrayAdapter) keySizeSpinner.getAdapter();
+ final Object selectedItem = keySizeSpinner.getSelectedItem();
+ keySizeAdapter.clear();
+ switch (algorithmId) {
+ case Constants.choice.algorithm.rsa:
+ replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values);
+ customKeyInfoTextView.setText(mActivity.getResources().getString(R.string.key_size_custom_info_rsa));
+ break;
+ case Constants.choice.algorithm.elgamal:
+ replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values);
+ customKeyInfoTextView.setText(""); // ElGamal does not support custom key length
+ break;
+ case Constants.choice.algorithm.dsa:
+ replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values);
+ customKeyInfoTextView.setText(mActivity.getResources().getString(R.string.key_size_custom_info_dsa));
+ break;
+ }
+ keySizeAdapter.notifyDataSetChanged();
+
+ // when switching algorithm, try to select same key length as before
+ for (int i = 0; i < keySizeAdapter.getCount(); i++) {
+ if (selectedItem.equals(keySizeAdapter.getItem(i))) {
+ keySizeSpinner.setSelection(i);
+ break;
+ }
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void replaceArrayAdapterContent(ArrayAdapter arrayAdapter, int stringArrayResourceId) {
+ final String[] spinnerValuesStringArray = mActivity.getResources().getStringArray(stringArrayResourceId);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ arrayAdapter.addAll(spinnerValuesStringArray);
+ } else {
+ for (final String value : spinnerValuesStringArray) {
+ arrayAdapter.add(value);
+ }
+ }
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
index 7fc78dc41..d729648e5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
@@ -41,9 +41,6 @@ import java.util.ArrayList;
public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemClickListener {
private LayoutInflater mInflater;
- private int mIndexUserId, mIndexRank;
- private int mVerifiedId, mIsRevoked, mIsPrimary;
-
private final ArrayList mCheckStates;
private SaveKeyringParcel mSaveKeyringParcel;
@@ -56,6 +53,13 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
UserIds.IS_PRIMARY,
UserIds.IS_REVOKED
};
+ private static final int INDEX_ID = 0;
+ private static final int INDEX_USER_ID = 1;
+ private static final int INDEX_RANK = 2;
+ private static final int INDEX_VERIFIED = 3;
+ private static final int INDEX_IS_PRIMARY = 4;
+ private static final int INDEX_IS_REVOKED = 5;
+
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
SaveKeyringParcel saveKeyringParcel) {
@@ -64,8 +68,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
mCheckStates = showCheckBoxes ? new ArrayList() : null;
mSaveKeyringParcel = saveKeyringParcel;
-
- initIndex(c);
}
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) {
@@ -82,7 +84,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
@Override
public Cursor swapCursor(Cursor newCursor) {
- initIndex(newCursor);
if (mCheckStates != null) {
mCheckStates.clear();
if (newCursor != null) {
@@ -91,7 +92,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
// initialize to true (use case knowledge: we usually want to sign all uids)
for (int i = 0; i < count; i++) {
newCursor.moveToPosition(i);
- int verified = newCursor.getInt(mVerifiedId);
+ int verified = newCursor.getInt(INDEX_VERIFIED);
mCheckStates.add(verified != Certs.VERIFIED_SECRET);
}
}
@@ -100,31 +101,15 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
return super.swapCursor(newCursor);
}
- /**
- * Get column indexes for performance reasons just once in constructor and swapCursor. For a
- * performance comparison see http://stackoverflow.com/a/17999582
- *
- * @param cursor
- */
- private void initIndex(Cursor cursor) {
- if (cursor != null) {
- mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID);
- mIndexRank = cursor.getColumnIndexOrThrow(UserIds.RANK);
- mVerifiedId = cursor.getColumnIndexOrThrow(UserIds.VERIFIED);
- mIsRevoked = cursor.getColumnIndexOrThrow(UserIds.IS_REVOKED);
- mIsPrimary = cursor.getColumnIndexOrThrow(UserIds.IS_PRIMARY);
- }
- }
-
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView vName = (TextView) view.findViewById(R.id.userId);
TextView vAddress = (TextView) view.findViewById(R.id.address);
TextView vComment = (TextView) view.findViewById(R.id.comment);
ImageView vVerified = (ImageView) view.findViewById(R.id.certified);
- ImageView vHasChanges = (ImageView) view.findViewById(R.id.has_changes);
+ ImageView vEditImage = (ImageView) view.findViewById(R.id.edit_image);
- String userId = cursor.getString(mIndexUserId);
+ String userId = cursor.getString(INDEX_USER_ID);
String[] splitUserId = KeyRing.splitUserId(userId);
if (splitUserId[0] != null) {
vName.setText(splitUserId[0]);
@@ -144,31 +129,29 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
vComment.setVisibility(View.GONE);
}
- boolean isPrimary = cursor.getInt(mIsPrimary) != 0;
- boolean isRevoked = cursor.getInt(mIsRevoked) > 0;
+ boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0;
+ boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
// for edit key
if (mSaveKeyringParcel != null) {
- boolean changeUserId = (mSaveKeyringParcel.changePrimaryUserId != null
+ boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.changePrimaryUserId != null);
+ boolean changeThisPrimaryUserId = (mSaveKeyringParcel.changePrimaryUserId != null
&& mSaveKeyringParcel.changePrimaryUserId.equals(userId));
- boolean revoke = (mSaveKeyringParcel.revokeUserIds.contains(userId));
+ boolean revokeThisUserId = (mSaveKeyringParcel.revokeUserIds.contains(userId));
- if (changeUserId) {
- isPrimary = !isPrimary;
+ if (changeAnyPrimaryUserId) {
+ // change all user ids, only this one should be primary
+ isPrimary = changeThisPrimaryUserId;
}
- if (revoke) {
+ if (revokeThisUserId) {
if (!isRevoked) {
isRevoked = true;
}
}
- if (changeUserId || revoke) {
- vHasChanges.setVisibility(View.VISIBLE);
- } else {
- vHasChanges.setVisibility(View.GONE);
- }
+ vEditImage.setVisibility(View.VISIBLE);
} else {
- vHasChanges.setVisibility(View.GONE);
+ vEditImage.setVisibility(View.GONE);
}
if (isRevoked) {
@@ -178,15 +161,18 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
// disable and strike through text for revoked user ids
vName.setEnabled(false);
vAddress.setEnabled(false);
+ vComment.setEnabled(false);
vName.setText(OtherHelper.strikeOutText(vName.getText()));
vAddress.setText(OtherHelper.strikeOutText(vAddress.getText()));
+ vComment.setText(OtherHelper.strikeOutText(vComment.getText()));
} else {
vName.setEnabled(true);
vAddress.setEnabled(true);
+ vComment.setEnabled(true);
// verified: has been verified
// isPrimary: show small star icon for primary user ids
- int verified = cursor.getInt(mVerifiedId);
+ int verified = cursor.getInt(INDEX_VERIFIED);
switch (verified) {
case Certs.VERIFIED_SECRET:
vVerified.setImageResource(isPrimary
@@ -234,7 +220,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
for (int i = 0; i < mCheckStates.size(); i++) {
if (mCheckStates.get(i)) {
mCursor.moveToPosition(i);
- result.add(mCursor.getString(mIndexUserId));
+ result.add(mCursor.getString(INDEX_USER_ID));
}
}
return result;
@@ -242,7 +228,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
public String getUserId(int position) {
mCursor.moveToPosition(position);
- return mCursor.getString(mIndexUserId);
+ return mCursor.getString(INDEX_USER_ID);
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
new file mode 100644
index 000000000..3fe5574ee
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import android.app.Activity;
+import android.content.Context;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Patterns;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.EditText;
+import android.widget.ImageButton;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.ContactHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+
+public class UserIdsAddedAdapter extends ArrayAdapter {
+ private LayoutInflater mInflater;
+ private Activity mActivity;
+
+ private ArrayAdapter mAutoCompleteNameAdapter;
+ private ArrayAdapter mAutoCompleteEmailAdapter;
+
+ // hold a private reference to the underlying data List
+ private List mData;
+
+ public static class UserIdModel {
+ String name = "";
+ String address = "";
+ String comment = "";
+
+ @Override
+ public String toString() {
+ String userId = name;
+ if (!TextUtils.isEmpty(comment)) {
+ userId += " (" + comment + ")";
+ }
+ if (!TextUtils.isEmpty(address)) {
+ userId += " <" + address + ">";
+ }
+ return userId;
+ }
+ }
+
+ public UserIdsAddedAdapter(Activity activity, List data) {
+ super(activity, -1, data);
+ mActivity = activity;
+ mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mData = data;
+ mAutoCompleteNameAdapter = new ArrayAdapter
+ (mActivity, android.R.layout.simple_spinner_dropdown_item,
+ ContactHelper.getPossibleUserNames(mActivity)
+ );
+ mAutoCompleteEmailAdapter = new ArrayAdapter
+ (mActivity, android.R.layout.simple_spinner_dropdown_item,
+ ContactHelper.getPossibleUserEmails(mActivity)
+ );
+ }
+
+ public ArrayList getDataAsStringList() {
+ ArrayList out = new ArrayList();
+ for (UserIdModel id : mData) {
+ // ignore empty user ids
+ if (!TextUtils.isEmpty(id.toString())) {
+ out.add(id.toString());
+ }
+ }
+
+ return out;
+ }
+
+ static class ViewHolder {
+ public AutoCompleteTextView vAddress;
+ public AutoCompleteTextView vName;
+ public EditText vComment;
+ public ImageButton vDelete;
+ // also hold a reference to the model item
+ public UserIdModel mModel;
+ }
+
+ public View getView(final int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ // Not recycled, inflate a new view
+ convertView = mInflater.inflate(R.layout.edit_key_user_id_added_item, null);
+ final ViewHolder holder = new ViewHolder();
+ holder.vAddress = (AutoCompleteTextView) convertView.findViewById(R.id.user_id_added_item_address);
+ holder.vName = (AutoCompleteTextView) convertView.findViewById(R.id.user_id_added_item_name);
+ holder.vComment = (EditText) convertView.findViewById(R.id.user_id_added_item_comment);
+ holder.vDelete = (ImageButton) convertView.findViewById(R.id.user_id_added_item_delete);
+ convertView.setTag(holder);
+
+ holder.vAddress.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ // update referenced item in view holder
+ holder.mModel.address = s.toString();
+
+ // show icon on valid email addresses
+ if (holder.mModel.address.length() > 0) {
+ Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(holder.mModel.address);
+ if (emailMatcher.matches()) {
+ holder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.uid_mail_ok, 0);
+ } else {
+ holder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.uid_mail_bad, 0);
+ }
+ } else {
+ // remove drawable if email is empty
+ holder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+ }
+ }
+ });
+
+ holder.vName.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ // update referenced item in view holder
+ holder.mModel.name = s.toString();
+ }
+ });
+
+ holder.vComment.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ // update referenced item in view holder
+ holder.mModel.comment = s.toString();
+ }
+ });
+
+ holder.vDelete.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // remove reference model item from adapter (data and notify about change)
+ UserIdsAddedAdapter.this.remove(holder.mModel);
+ }
+ });
+
+ }
+ final ViewHolder holder = (ViewHolder) convertView.getTag();
+
+ // save reference to model item
+ holder.mModel = getItem(position);
+
+ holder.vAddress.setText(holder.mModel.address);
+ holder.vAddress.setThreshold(1); // Start working from first character
+ holder.vAddress.setAdapter(mAutoCompleteEmailAdapter);
+
+ holder.vName.setText(holder.mModel.name);
+ holder.vName.setThreshold(1); // Start working from first character
+ holder.vName.setAdapter(mAutoCompleteNameAdapter);
+
+ holder.vComment.setText(holder.mModel.comment);
+
+ return convertView;
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java
deleted file mode 100644
index e6445c074..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.sufficientlysecure.keychain.ui.adapter;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Context;
-import android.os.Build;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.CheckBox;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
-
-import java.util.List;
-
-public class UserIdsArrayAdapter extends ArrayAdapter {
- protected LayoutInflater mInflater;
- protected Activity mActivity;
-
- protected List mData;
-
- static class ViewHolder {
- public TextView vName;
- public TextView vAddress;
- public TextView vComment;
- public ImageView vVerified;
- public ImageView vHasChanges;
- public CheckBox vCheckBox;
- }
-
- public UserIdsArrayAdapter(Activity activity) {
- super(activity, -1);
- mActivity = activity;
- mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- }
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public void setData(List data) {
- clear();
- if (data != null) {
- this.mData = data;
-
- // add data to extended ArrayAdapter
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- addAll(data);
- } else {
- for (String entry : data) {
- add(entry);
- }
- }
- }
- }
-
- public List getData() {
- return mData;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- String entry = mData.get(position);
- ViewHolder holder;
- if (convertView == null) {
- holder = new ViewHolder();
- convertView = mInflater.inflate(R.layout.view_key_userids_item, null);
- holder.vName = (TextView) convertView.findViewById(R.id.userId);
- holder.vAddress = (TextView) convertView.findViewById(R.id.address);
- holder.vComment = (TextView) convertView.findViewById(R.id.comment);
- holder.vVerified = (ImageView) convertView.findViewById(R.id.certified);
- holder.vHasChanges = (ImageView) convertView.findViewById(R.id.has_changes);
- holder.vCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox);
- convertView.setTag(holder);
- } else {
- holder = (ViewHolder) convertView.getTag();
- }
-
- // user id
- String[] splitUserId = KeyRing.splitUserId(entry);
- if (splitUserId[0] != null) {
- holder.vName.setText(splitUserId[0]);
- } else {
- holder.vName.setText(R.string.user_id_no_name);
- }
- if (splitUserId[1] != null) {
- holder.vAddress.setText(splitUserId[1]);
- holder.vAddress.setVisibility(View.VISIBLE);
- } else {
- holder.vAddress.setVisibility(View.GONE);
- }
- if (splitUserId[2] != null) {
- holder.vComment.setText(splitUserId[2]);
- holder.vComment.setVisibility(View.VISIBLE);
- } else {
- holder.vComment.setVisibility(View.GONE);
- }
-
- holder.vCheckBox.setVisibility(View.GONE);
-
- holder.vVerified.setImageResource(R.drawable.key_certify_ok_depth0);
-
- // all items are "new"
- holder.vHasChanges.setVisibility(View.VISIBLE);
-
- return convertView;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
deleted file mode 100644
index c27266e3f..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.sufficientlysecure.keychain.ui.dialog;
-
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
-import android.support.v4.app.DialogFragment;
-import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.WindowManager;
-import android.view.inputmethod.EditorInfo;
-import android.widget.EditText;
-import android.widget.TextView;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Log;
-
-public class AddUserIdDialogFragment extends DialogFragment implements EditText.OnEditorActionListener {
- private static final String ARG_MESSENGER = "messenger";
-
- public static final int MESSAGE_OKAY = 1;
-
- public static final String MESSAGE_DATA_USER_ID = "user_id";
-
- private Messenger mMessenger;
-
- EditText mName;
- EditText mAddress;
- EditText mComment;
-
- /**
- * Creates new instance of this dialog fragment
- */
- public static AddUserIdDialogFragment newInstance(Messenger messenger) {
- AddUserIdDialogFragment frag = new AddUserIdDialogFragment();
- Bundle args = new Bundle();
- args.putParcelable(ARG_MESSENGER, messenger);
-
- frag.setArguments(args);
-
- return frag;
- }
-
- /**
- * Creates dialog
- */
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- mMessenger = getArguments().getParcelable(ARG_MESSENGER);
-
- CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(getActivity());
- LayoutInflater inflater = getActivity().getLayoutInflater();
- View view = inflater.inflate(R.layout.add_user_id_dialog, null);
- alert.setView(view);
- alert.setTitle("Add Identity");
-
- mName = (EditText) view.findViewById(R.id.name);
- mAddress = (EditText) view.findViewById(R.id.address);
- mComment = (EditText) view.findViewById(R.id.comment);
-
- alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- done();
- }
- });
-
- alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
-
-
- return alert.show();
- }
-
- @Override
- public void onActivityCreated(Bundle arg0) {
- super.onActivityCreated(arg0);
- // Show soft keyboard automatically
- mName.requestFocus();
- getDialog().getWindow().setSoftInputMode(
- WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
- mComment.setOnEditorActionListener(this);
- }
-
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- if (EditorInfo.IME_ACTION_DONE == actionId) {
- done();
- return true;
- }
- return false;
- }
-
- private void done() {
- String name = mName.getText().toString();
- String email = mAddress.getText().toString();
- String comment = mComment.getText().toString();
-
- String userId = null;
- if (!TextUtils.isEmpty(name)) {
- userId = name;
- if (!TextUtils.isEmpty(comment)) {
- userId += " (" + comment + ")";
- }
- if (!TextUtils.isEmpty(email)) {
- userId += " <" + email + ">";
- }
- }
- Bundle data = new Bundle();
- data.putString(MESSAGE_DATA_USER_ID, userId);
- sendMessageToHandler(MESSAGE_OKAY, data);
-
- this.dismiss();
- }
-
- /**
- * Send message back to handler which is initialized in a activity
- *
- * @param what Message integer you want to send
- */
- private void sendMessageToHandler(Integer what, Bundle data) {
- Message msg = Message.obtain();
- msg.what = what;
- if (data != null) {
- msg.setData(data);
- }
-
- try {
- mMessenger.send(msg);
- } catch (RemoteException e) {
- Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
- } catch (NullPointerException e) {
- Log.w(Constants.TAG, "Messenger is null!", e);
- }
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
index 6c012cb94..920743a9b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java
@@ -51,8 +51,6 @@ public class CreateKeyDialogFragment extends DialogFragment {
private static final String ARG_EDITOR_CHILD_COUNT = "child_count";
- private int mNewKeySize;
- private Choice mNewKeyAlgorithmChoice;
private OnAlgorithmSelectedListener mAlgorithmSelectedListener;
private Spinner mAlgorithmSpinner;
private Spinner mKeySizeSpinner;
@@ -131,9 +129,9 @@ public class CreateKeyDialogFragment extends DialogFragment {
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di, int id) {
di.dismiss();
- mNewKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem();
- mNewKeySize = getProperKeyLength(mNewKeyAlgorithmChoice.getId(), getSelectedKeyLength());
- mAlgorithmSelectedListener.onAlgorithmSelected(mNewKeyAlgorithmChoice, mNewKeySize);
+ Choice newKeyAlgorithmChoice = (Choice) mAlgorithmSpinner.getSelectedItem();
+ int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), getSelectedKeyLength());
+ mAlgorithmSelectedListener.onAlgorithmSelected(newKeyAlgorithmChoice, newKeySize);
}
}
);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java
index f0ca73f0d..5eba3a463 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java
@@ -26,6 +26,7 @@ import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.Log;
public class EditUserIdDialogFragment extends DialogFragment {
@@ -57,9 +58,9 @@ public class EditUserIdDialogFragment extends DialogFragment {
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity());
- CharSequence[] array = {"change to primary user id", "revoke"};
+ CharSequence[] array = getResources().getStringArray(R.array.edit_key_edit_user_id);
- builder.setTitle("select action!");
+ builder.setTitle(R.string.edit_key_edit_user_id_title);
builder.setItems(array, new DialogInterface.OnClickListener() {
@Override
@@ -76,7 +77,7 @@ public class EditUserIdDialogFragment extends DialogFragment {
}
}
});
- builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dismiss();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
index 04bec3282..93da48b75 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
@@ -26,12 +26,15 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
+import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
@@ -44,6 +47,7 @@ import org.sufficientlysecure.keychain.util.Log;
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "messenger";
private static final String ARG_TITLE = "title";
+ private static final String ARG_OLD_PASSPHRASE = "old_passphrase";
public static final int MESSAGE_OKAY = 1;
@@ -52,6 +56,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
private Messenger mMessenger;
private EditText mPassphraseEditText;
private EditText mPassphraseAgainEditText;
+ private CheckBox mNoPassphraseCheckBox;
/**
* Creates new instance of this dialog fragment
@@ -60,11 +65,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
* @param messenger to communicate back after setting the passphrase
* @return
*/
- public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) {
+ public static SetPassphraseDialogFragment newInstance(Messenger messenger, String oldPassphrase, int title) {
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_TITLE, title);
args.putParcelable(ARG_MESSENGER, messenger);
+ args.putString(ARG_OLD_PASSPHRASE, oldPassphrase);
frag.setArguments(args);
@@ -80,6 +86,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
int title = getArguments().getInt(ARG_TITLE);
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
+ String oldPassphrase = getArguments().getString(ARG_OLD_PASSPHRASE);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
@@ -92,6 +99,21 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
+ mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
+
+ if (TextUtils.isEmpty(oldPassphrase)) {
+ mNoPassphraseCheckBox.setChecked(true);
+ mPassphraseEditText.setEnabled(false);
+ mPassphraseAgainEditText.setEnabled(false);
+ }
+
+ mNoPassphraseCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mPassphraseEditText.setEnabled(!isChecked);
+ mPassphraseAgainEditText.setEnabled(!isChecked);
+ }
+ });
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@@ -99,24 +121,31 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
public void onClick(DialogInterface dialog, int id) {
dismiss();
- String passphrase1 = mPassphraseEditText.getText().toString();
- String passphrase2 = mPassphraseAgainEditText.getText().toString();
- if (!passphrase1.equals(passphrase2)) {
- Toast.makeText(
- activity,
- getString(R.string.error_message,
- getString(R.string.passphrases_do_not_match)), Toast.LENGTH_SHORT)
- .show();
- return;
- }
+ String passphrase1;
+ if (mNoPassphraseCheckBox.isChecked()) {
+ passphrase1 = "";
+ } else {
+ passphrase1 = mPassphraseEditText.getText().toString();
+ String passphrase2 = mPassphraseAgainEditText.getText().toString();
+ if (!passphrase1.equals(passphrase2)) {
+ Toast.makeText(
+ activity,
+ getString(R.string.error_message,
+ getString(R.string.passphrases_do_not_match)), Toast.LENGTH_SHORT
+ )
+ .show();
+ return;
+ }
- if (passphrase1.equals("")) {
- Toast.makeText(
- activity,
- getString(R.string.error_message,
- getString(R.string.passphrase_must_not_be_empty)),
- Toast.LENGTH_SHORT).show();
- return;
+ if (passphrase1.equals("")) {
+ Toast.makeText(
+ activity,
+ getString(R.string.error_message,
+ getString(R.string.passphrase_must_not_be_empty)),
+ Toast.LENGTH_SHORT
+ ).show();
+ return;
+ }
}
// return resulting data back to activity
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java
index da29f808a..294ff1500 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java
@@ -25,9 +25,7 @@ import android.widget.ListView;
* Automatically calculate height of ListView based on contained items. This enables to put this
* ListView into a ScrollView without messing up.
*
- * from
- * http://stackoverflow.com/questions/2419246/how-do-i-create-a-listview-thats-not-in-a-scrollview-
- * or-has-the-scrollview-dis
+ * from http://stackoverflow.com/a/3580117
*/
public class FixedListView extends ListView {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java
index 4ecc96cee..cd5671801 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java
@@ -388,7 +388,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
// get new key from data bundle returned from service
- Bundle data = message.getData();
+ Bundle data = message.getDataAsStringList();
UncachedSecretKey newKey = PgpConversionHelper
.BytesToPGPSecretKey(data
.getByteArray(KeychainIntentService.RESULT_NEW_KEY));
diff --git a/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml b/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml
deleted file mode 100644
index 502ca1c70..000000000
--- a/OpenKeychain/src/main/res/layout/add_user_id_dialog.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/decrypt_content.xml b/OpenKeychain/src/main/res/layout/decrypt_content.xml
index ff75f20ee..f62cf615c 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_content.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_content.xml
@@ -6,7 +6,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
-
+
+ android:textColor="@color/emphasis" />
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml
index 7f94cb3cd..2ffbc66f4 100644
--- a/OpenKeychain/src/main/res/layout/edit_key_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/edit_key_fragment.xml
@@ -14,7 +14,7 @@
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="8dp"
- android:text="Passphrase"
+ android:text="@string/label_passphrase"
android:layout_weight="1" />
@@ -109,9 +109,9 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:text="add key"
+ android:text="@string/edit_key_action_add_subkey"
android:minHeight="?android:attr/listPreferredItemHeight"
- android:drawableRight="@drawable/ic_action_add_person"
+ android:drawableRight="@drawable/ic_action_new_account"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:clickable="true"
diff --git a/OpenKeychain/src/main/res/layout/edit_key_subkey_added_item.xml b/OpenKeychain/src/main/res/layout/edit_key_subkey_added_item.xml
new file mode 100644
index 000000000..856bef36a
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/edit_key_subkey_added_item.xml
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/edit_key_user_id_added_item.xml b/OpenKeychain/src/main/res/layout/edit_key_user_id_added_item.xml
new file mode 100644
index 000000000..e69452db1
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/edit_key_user_id_added_item.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/layout/key_list_item.xml b/OpenKeychain/src/main/res/layout/key_list_item.xml
index 73a20bd2e..99e4c0268 100644
--- a/OpenKeychain/src/main/res/layout/key_list_item.xml
+++ b/OpenKeychain/src/main/res/layout/key_list_item.xml
@@ -38,32 +38,11 @@
android:textAppearance="?android:attr/textAppearanceSmall" />
-
-
-
-
+ android:stretchColumns="1">
-
+
+
+
-
+
-
-
-
-
@@ -68,4 +63,13 @@
+
+
+
diff --git a/OpenKeychain/src/main/res/raw-de/help_changelog.html b/OpenKeychain/src/main/res/raw-de/help_changelog.html
index 9ef142382..d84002e80 100644
--- a/OpenKeychain/src/main/res/raw-de/help_changelog.html
+++ b/OpenKeychain/src/main/res/raw-de/help_changelog.html
@@ -40,7 +40,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
viel mehr interne Arbeit an der API
zertifizieren von Benutzer IDs
Schlüsselserver Anfragen basieren auf Maschinenlesbaren Ausgaben.
-
lock navigation drawer on tablets
+
fixiere Navigationsmenu in Tabletcomputers
suggestions for emails on creation of keys
suchen in öffentlichen Schlüssellisten
und viele weitere Verbesserungen und Fehlerbehebungen...
@@ -63,7 +63,7 @@ Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Pa
2.2
-
new design with navigation drawer
+
neues Design mit Naivgationsmenu
Neus Design für die Liste der öffentlichen Schlüssel
Zuerst benötigen Sie einen geheimen privaten Schlüssel. Erstellen Sie einen Schlüssel über den Eintrag "Schlüssel" im Menu oder importieren Sie bestehende private Schlüssel. Anschließend können Sie die Schlüssel ihrer Freunde runterladen oder Sie über QR-Codes oder NFC austauschen.
+
Zuerst benötigen Sie einen privaten Schlüssel. Erstellen Sie einen Schlüssel über den Eintrag "Schlüssel" im Menu oder importieren Sie bestehende private Schlüssel. Anschließend können Sie die Schlüssel ihrer Freunde runterladen oder Sie über QR-Codes oder NFC austauschen.
Es wird empfohlen, dass Sie den OI File Manager für ein verbessertes Dateihandling installieren, sowie den Barcode Scanner installieren um erstellte QR-Codes zu scannen. Die Links führen entweder zu Google Play oder zu F-Droid zur Installation.
support for GnuPG partial secret keys (thanks to Vincent Breitmoser)
+
new design for signature verification
+
custom key length (thanks to Greg Witczak)
+
fix share-functionality from other apps
+
+
2.5
+
+
fix decryption of symmetric pgp messages/files
+
refactored edit key screen (thanks to Ash Hughes)
+
new modern design for encrypt/decrypt screens
+
OpenPGP API version 3 (multiple api accounts, internal fixes, key lookup)
+
+
2.4
+
Thanks to all applicants of Google Summer of Code 2014 who made this release feature rich and bug free!
+Besides several small patches, a notable number of patches are made by the following people (in alphabetical order):
+Daniel Hammann, Daniel Haß, Greg Witczak, Miroojin Bakshi, Nikhil Peter Raj, Paul Sarbinowski, Sreeram Boyapati, Vincent Breitmoser.
+
+
new unified key list
+
colorized key fingerprint
+
support for keyserver ports
+
deactivate possibility to generate weak keys
+
much more internal work on the API
+
certify user ids
+
keyserver query based on machine-readable output
+
lock navigation drawer on tablets
+
suggestions for emails on creation of keys
+
search in public key lists
+
and much more improvements and fixes…
+
+
2.3.1
+
+
hotfix for crash when upgrading from old versions
+
+
2.3
+
+
remove unnecessary export of public keys when exporting secret key (thanks to Ash Hughes)
+
fix setting expiry dates on keys (thanks to Ash Hughes)
+
more internal fixes when editing keys (thanks to Ash Hughes)
+
querying keyservers directly from the import screen
+
fix layout and dialog style on Android 2.2-3.0
+
fix crash on keys with empty user ids
+
fix crash and empty lists when coming back from signing screen
+
Bouncy Castle (cryptography library) updated from 1.47 to 1.50 and build from source
+
fix upload of key from signing screen
+
+
2.2
+
+
new design with navigation drawer
+
new public key list design
+
new public key view
+
bug fixes for importing of keys
+
key cross-certification (thanks to Ash Hughes)
+
handle UTF-8 passwords properly (thanks to Ash Hughes)
+
first version with new languages (thanks to the contributors on Transifex)
+
sharing of keys via QR Codes fixed and improved
+
package signature verification for API
+
+
2.1.1
+
+
API Updates, preparation for K-9 Mail integration
+
+
2.1
+
+
lots of bug fixes
+
new API for developers
+
PRNG bug fix by Google
+
+
2.0
+
+
complete redesign
+
share public keys via qr codes, nfc beam
+
sign keys
+
upload keys to server
+
fixes import issues
+
new AIDL API
+
+
1.0.8
+
+
basic keyserver support
+
app2sd
+
more choices for pass phrase cache: 1, 2, 4, 8, hours
+
translations: Norwegian (thanks, Sander Danielsen), Chinese (thanks, Zhang Fredrick)
+
bugfixes
+
optimizations
+
+
1.0.7
+
+
fixed problem with signature verification of texts with trailing newline
+
more options for pass phrase cache time to live (20, 40, 60 mins)
+
+
1.0.6
+
+
account adding crash on Froyo fixed
+
secure file deletion
+
option to delete key file after import
+
stream encryption/decryption (gallery, etc.)
+
new options (language, force v3 signatures)
+
interface changes
+
bugfixes
+
+
1.0.5
+
+
German and Italian translation
+
much smaller package, due to reduced BC sources
+
new preferences GUI
+
layout adjustment for localization
+
signature bugfix
+
+
1.0.4
+
+
fixed another crash caused by some SDK bug with query builder
+
+
1.0.3
+
+
fixed crashes during encryption/signing and possibly key export
+
+
1.0.2
+
+
filterable key lists
+
smarter pre-selection of encryption keys
+
new Intent handling for VIEW and SEND, allows files to be encrypted/decrypted out of file managers
+
fixes and additional features (key preselection) for K-9 Mail, new beta build available
+
+
1.0.1
+
+
GMail account listing was broken in 1.0.0, fixed again
+
+
1.0.0
+
+
K-9 Mail integration, APG supporting beta build of K-9 Mail
+
support of more file managers (including ASTRO)
+
Slovenian translation
+
new database, much faster, less memory usage
+
defined Intents and content provider for other apps
Go to your partners contacts and open the contact you want to share.
+
Hold the two devices back to back (they have to be almost touching) and you’ll feel a vibration.
+
After it vibrates you’ll see the content on your partners device turn into a card-like object with Star Trek warp speed-looking animation in the background.
+
Tap the card and the content will then load on the your device.
First you need a personal secret key. Create one via the option menus in "Keys" or import existing secret keys. Afterwards, you can download your friends' keys or exchange them via QR Codes or NFC.
+
+
It is recommended that you install OI File Manager for enhanced file selection and Barcode Scanner to scan generated QR Codes. Clicking on the links will open Google Play Store or F-Droid for installation.
+
+
Applications
+
Several applications support OpenKeychain to encrypt/sign your private communication: K-9 Mail: OpenKeychain support available in current alpha build! Conversations: Jabber/XMPP client PGPAuth: App to send a PGP-signed request to a server to open or close something, e.g. a door
The Web of Trust describes the part of PGP which deals with creation and bookkeeping of certifications. It provides mechanisms to help the user keep track of who a public key belongs to, and share this information with others; To ensure the privacy of encrypted communication, it is essential to know that the public key you encrypt to belongs to the person you think it does.
+
+
Support in OpenKeychain
+
There is only basic support for Web of Trust in OpenKeychain. This is a heavy work in progress and subject to changes in upcoming releases.
+
+
Trust Model
+
Trust evaluation is based on the simple assumption that all keys which have secret keys available are trusted. Public keys which contain at least one user id certified by a trusted key will be marked with a green dot in the key listings. It is not (yet) possible to specify trust levels for certificates of other known public keys.
+
+
Certifying keys
+
Support for key certification is available, and user ids can be certified individually. It is not yet possible to specify the level of trust or create local and other special types of certificates.
Make sure that NFC is turned on in Settings > More > NFC and make sure that Android Beam is also on in the same section.
+
Hold the two devices back to back (they have to be almost touching) and you'll feel a vibration.
+
After it vibrates you'll see the content on your device turn into a card-like object with Star Trek warp speed-looking animation in the background.
+
Tap the card and the content will then load on the other person’s device.
+
+
+
diff --git a/OpenKeychain/src/main/res/values-ar/strings.xml b/OpenKeychain/src/main/res/values-ar/strings.xml
index e3d3a6493..593fc2d11 100644
--- a/OpenKeychain/src/main/res/values-ar/strings.xml
+++ b/OpenKeychain/src/main/res/values-ar/strings.xml
@@ -19,6 +19,7 @@
+
@@ -27,5 +28,10 @@
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml
index e3d3a6493..a7c24cd0e 100644
--- a/OpenKeychain/src/main/res/values-cs/strings.xml
+++ b/OpenKeychain/src/main/res/values-cs/strings.xml
@@ -1,16 +1,150 @@
+ Vybrat veřejný klíč
+ Vybrat veřjný klíč
+ Zašifrovat
+ Rozšifrovat
+ Heslo
+ Vytvořit klíč
+ Editovat klíč
+ Možnosti
+ Appky
+ Nastavení keyservrů
+ Nastavit heslo
+ Zašifrovat do souboru
+ Rozšifrovat do souboru
+ Importovat klíče
+ Exportovat klíče
+ Exportovat klíče
+ Klíč nebyl nalezen
+ Nahrát na keyserver
+ Nápověda
+ Identity
+ Podklíče
+ Obecné
+ Výchozí hodnoty
+ Pokročilé
+ Zaširovat a uložit soubor
+ Uložit
+ Zrušit
+ Smazat
+ Nic
+ OK
+ Změnit nové heslo
+ Nastavit nové heslo
+ Nahrát na keyserver
+ Další
+ Zpět
+ Nastavení
+ Exportovat do souboru
+ Smazat klíč
+ Vytvořit klíč
+ Vytvořit klíč (pokročilé)
+ Hledat
+ Keyserver...
+ Obnovit z keyservru
+ Obnovit na keyserveru
+ Sdílet...
+ pomocí QR kódu
+ pomocí NFC
+ Beam settings
+ Podepsat
+ Zpráva
+ Soubor
+ Bez hesla
+ Heslo
+ Znovu
+ Algoritmus
+ ASCII Armor
+ Příjemci
+ Smazat po zašifrování
+ Smazat po rozšifrování
+ Šifrovací algoritmus
+ Hashovací algoritmus
+ veřejným klíčem
+ heslem
+ Cache hesel
+ Komprimovat zprávu
+ Komprimovat soubor
+ Vynutit staré OpenPGPv3 podpisy
+ ID klíče
+ Vytvořeno
+ Expirace
+ Použití
+ Délka klíče
+ Hlavní identita
+ Jméno
+ Komentář
+ Email
+ Po vytvoření nahrt na vybraný keyserver
+ <žádný>
+ <žádný klíč>
+ slouží k šifrovní
+ slouží k podpisu
+ po epiraci
+ Tajný klíč:
+ Žádný
+ 15 sekund
+ 1 minuta
+ 3 minuty
+ 5 minut
+ 10 minut
+ 20 minut
+ 40 minut
+ 1 hodina
+ 2 hodiny
+ 4 hodiny
+ 8 hodin
+ DSA
+ Otevřít...
+ Varovnání
+ Chyba
+ Chyba: %s
+ Špatné heslo.
+ Nejprve nastavit heslo.
+ Není nainstalován žádný compatibilní správce souborů.
+ Hesla se neshodují.
+ Prosím zadejte heslo.
+ Symetrická šifra.
+ Zadejte heslo pro \'%s\'
+ Určitě smazat\n%s?
+ Úspěšně smazáno.
+ Nejprve vyberte soubor.
+ Heslo zadejte dvakrát.
+ Vyberte alespoň jeden šifrovací klíč.
+ Vyberte alespoň jeden šifrovací nebo podpisový klíč.
+ Prosím specifikujte do kterého souboru zašifrovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.
+ Prosím specifikujte do kterého souboru rozšifrovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.
+ Prosím specifikujte do kterého souboru exportovat.\nVAROVÁNÍ: Pokud soubor již existuje, bude přepsán.
+ Opravdu chcete smazat TAJNÝ klíč \'%s\'?\nToto je nevratná operace!
+ Úspěšně exportován 1 klíč.
+ Úspěšně exportován %d klíč.
+ Žádný kláč pro export.
+ Žádný: pouze podklíče podporují ElGamal.
+ Nemohu najít klíč %08X.
+ Úspěšně nahráno na keyserver.
+ Seznam je prázný!
+ mazání \'%s\' selhalo
+ soubor nenalezen
+ žádný vhodný tajný klíč nenalezen
+ externí úložiště není připraveno
+ délka klíče musí být alespoň 512 bitů
+ hlavní klíč nemůže být typu ElGamal
+ neznámý typ algoritmu
+ potřebuji alespoň jednu identitu
+ hlavní identita nesmí být prázdná
+ potřebuji alespoň hlavní klíč
@@ -19,6 +153,7 @@
+
@@ -27,5 +162,10 @@
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml
index d5cf037c8..de6962dc9 100644
--- a/OpenKeychain/src/main/res/values-de/strings.xml
+++ b/OpenKeychain/src/main/res/values-de/strings.xml
@@ -9,7 +9,7 @@
Schlüssel erstellenSchlüssel bearbeitenEinstellungen
- Registrierte Anwendungen
+ AppsSchlüsselserverPassphrase ändernPasswort setzen
@@ -65,21 +65,16 @@
Schlüssel nachschlagenErweiterte Einstellungen anzeigenErweiterte Einstellungen verbergen
- Verschlüsselt/signierten Text teilen…
+ Verschlüsselt/signierte Nachricht teilen…Beglaubigungsschlüssel anzeigenEinstellungenHilfe
- Datei
- QR-Code
- NFCIn Datei exportierenSchlüssel löschenSchlüssel erstellenSchlüssel erstellen (Experte)Suchen
- Schlüsselserver
- Keybase.ioSchlüsselserver…Von einem Schlüsselserver aktualisierenAuf Schlüsselserver hochladen
@@ -98,6 +93,7 @@
Alles auswählenSchlüssel hinzufügenAlle Schlüssel exportieren
+ Erweiterte Info anzeigenSignierenNachricht
@@ -206,33 +202,12 @@
Es wurde eine leere Identität hinzugefügt. Wirklich fortfahren?Soll der öffentliche Schlüssel \'%s\' wirklich gelöscht werden?\nDies kann nicht rückgängig gemacht werden! Private Schlüssel auch exportieren
-
- %d Schlüssel erfolgreich hinzugefügt
- %d Schlüssel erfolgreich hinzugefügt
-
-
- und %d Schlüssel erfolgreich aktualisiert.
- und %d Schlüssel erfolgreich aktualisiert.
-
-
- %d Schlüssel erfolgreich hinzugefügt.
- %d Schlüssel erfolgreich hinzugefügt.
-
-
- %d Schlüssel erfolgreich aktualisiert.
- %d Schlüssel erfolgreich aktualisiert.
-
- Keine Schlüssel hinzugefügt oder aktualisiert.1 Schlüssel erfolgreich exportiert.%d Schlüssel erfolgreich exportiert.Keine Schlüssel exportiert.Beachte: Nur Unterschlüssel unterstützen ElGamal.Beachte: RSA-Schlüssel mit einer Schlüssellänge von 1024-Bits oder weniger werden als unsicher angesehen und können daher nicht für neue Schlüssel erstellt werden.Schlüssel %08X konnte nicht gefunden werden.
-
- %d Schlüssel gefunden.
- %d Schlüssel gefunden.
- %d schlechter privater Schlüssel ignoriert. Evtl. wurde er mit folgender Option exportiert:\n --export-secret-subkeys\nUnbedingt mit der Option \n --export-secret-keys\nexportieren.%d schlechte private Schlüssel ignoriert. Evtl. wurden sie mit folgender Option exportiert:\n --export-secret-subkeys\nUnbedingt mit der Option \n --export-secret-keys\nexportieren.
@@ -272,8 +247,8 @@
Binäre Daten ohne ohne Datei im Dateisystem werden nicht unterstützt.Android 4.1 wird benötigt um Androids NFC Beam nutzen zu können!NFC steht auf diesem Gerät nicht zur Verfügung!
- Nichts zu importieren!
- Datei ist leer
+ zu kurze Schlüsselanfrage
+ Die Schlüsselanfrage liefert zu viele Ergebnisse. Bitte verfeinern sie sie Anfrage.Ein allgemeiner Fehler trat auf, bitte schreiben Sie einen neuen Bugreport für OpenKeychain.Ein Teil der geladenen Datei ist ein gültiges OpenPGP Objekt aber kein OpenPGP Schlüssel
@@ -366,6 +341,7 @@
HilfeSchlüssel aus der Zwischenablage einfügenSchlüssel von Keybase.io erhalten
+
Datei entschlüsseln mit OpenKeychainSchlüssel importieren mit OpenKeychain
@@ -429,7 +405,7 @@
Signieren und VerschlüsselnEntschlüsseln und VerifizierenSchlüssel Importieren
- Registrierte Anwendungen
+ AppsMenü öffnenMenü schließenBearbeiten
@@ -438,8 +414,8 @@
verfügbarnicht verfügbar
- Hier den Text schreiben welche verschlüsselt und/oder signiert werden soll...
- Hier den verschlüsselten Text eingeben um ihn zu entschlüsseln und/oder zu verifzieren…
+ Hier die Nachricht schreiben welche verschlüsselt und/oder signiert werden soll…
+ Hier die verschlüsselte Nachricht eingeben um sie zu entschlüsseln und/oder zu verifzieren…normalkein
@@ -450,6 +426,19 @@
fehlgeschlagen!Fehler!Schlüssel nicht verfügbar
+
+ Alte Schlüssel aus der Datenbank löschen
+ Die Anwendung ist wegen Kodierungsfehler fehlgeschlagen
+ Die Anwendung is wegen Eingabe/Ausgabe-Fehler fehlgeschlagen
+ Die Anwendung ist wegen internen Fehler fehlgeschlagen
+ Schlüsselbund-daten werden kodiert
+ Datenbank-Transaktionen werden vorbereitet
+ Unterschlüssel %s wird bearbeitet
+
+ Geheime Unterschlüssel werden bearbeitet
+
+
+
BeglaubigerZertifikatdetails
@@ -468,5 +457,7 @@
Zertifikatdetails anzeigenunbekanntKann nicht unterschreiben
+ KodierungsfehlerKein Unterschlüssel zum Verschlüsseln verfügbar!
+ Schlüssel anzeigen (%s)
diff --git a/OpenKeychain/src/main/res/values-el/strings.xml b/OpenKeychain/src/main/res/values-el/strings.xml
index 9a9e74223..5cd62952b 100644
--- a/OpenKeychain/src/main/res/values-el/strings.xml
+++ b/OpenKeychain/src/main/res/values-el/strings.xml
@@ -41,6 +41,7 @@
+
@@ -49,5 +50,10 @@
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml
index f1e4e347d..50afd5c57 100644
--- a/OpenKeychain/src/main/res/values-es/strings.xml
+++ b/OpenKeychain/src/main/res/values-es/strings.xml
@@ -8,8 +8,9 @@
Frase de contraseñaCrear clave Editar clave
+ Bienvenido a OpenKeychain Preferencias
- Aplicaciones registradas
+ AplicacionesPrioridad del servidor de clavesCambiar frase de contraseñaEstablecer frase de contraseña
@@ -27,6 +28,7 @@
Certificar identidadesDetalles de la claveAyuda
+ Registro (log)IdentidadesSubclaves
@@ -70,16 +72,11 @@
AjustesAyuda
- Importar desde archivo
- Importar desde código QR
- Importar desde NFCExportar hacia archivoBorrar claveCrear claveCrear clave (experto)Buscar
- Servidor de claves...
- Importar desde Keybase.ioServidor de claves...Actualizar desde servidor de clavesCargar al servidor de claves
@@ -98,6 +95,7 @@
Seleccionar todoAñadir clavesExportar todas las claves
+ Mostrar información avanzadaFirmarMensaje
@@ -206,33 +204,12 @@
Ha añadido una identidad vacía, ¿está seguro de que quiere continuar?¿De veras quiere borrar la clave pública \'%s\'?\n¡No puede deshacer esto!¿Exportar también las claves secretas?
-
- %d clave añadida satisfactoriamente
- %d claves añadidas satisfactoriamente
-
-
- y actualizada %d clave.
- y actualizadas %d claves.
-
-
- %d clave añadida satisfactoriamente.
- %d claves añadidas satisfactoriamente.
-
-
- %d clave actualizada satisfactoriamente.
- %d claves actualizadas satisfactoriamente.
-
- No se han añadido o actualizado claves.Se ha exportado 1 clave satisfactoriamente.%d claves exportadas satisfactoriamente.No se han exportado claves.Nota: Sólo las subclaves soportan ElGamal.Nota: generar una clave RSA de longitud 1024-bit o menos está considerado inseguro y desactivado para generar nuevas claves.No se puede encontrar la clave %08X.
-
- Se ha encontrado %d clave.
- Se han encontrado %d claves.
- %d mala clave secreta ignorada. Quizás hayas exportado con la opción\n--export-secret-subkeys\nAsegúrate de que exportas con\n--export-secret-keys\nen su lugar.%d malas claves secretas ignoradas. Quizás hayas exportado con la opción\n--export-secret-subkeys\nAsegúrate de que exportas con\n--export-secret-keys\nen su lugar.
@@ -272,11 +249,11 @@
Los datos binarios directos sin un fichero existente en el sistema de ficheros no están soportados.¡Necesita Android 4.1 para usar la característica NFC Beam (haz NFC) de Android!¡NFC no está disponible en tu dispositivo!
- ¡Nada que importar!
+ ¡No se encontraron claves!Petición de búsqueda de clave demasiado cortaError irrecuperable buscando claves en el servidorLa petición de búsqueda de clave devolvió demasiados candidatos; por favor refine su petición
- El archivo está vacio
+ El Fichero/Portapapeles está vacíoHa ocurrido un error genérico, por favor, informa de este bug a OpenKeychainparte del archivo cargado es un objeto OpenPGP válido pero no una clave OpenPGP
@@ -327,10 +304,10 @@
verificando la integridad...borrando \'%s\' de forma segura…
- Buscar claves públicas
+ Identidad de Nombre/Correo/Clave...Buscar claves secretasCompartir la clave con...
- Buscar en Keybase.io
+ Nombre de usuario de Nombre/Keybase.io...512768
@@ -356,6 +333,10 @@
A cerca deVersión:
+ Servidor de claves
+ Fichero/Portapapeles
+ Código QR/NFC
+ Keybase.ioImportar las claves seleccionadasImportar desde el portapapeles
@@ -369,8 +350,30 @@
Escanea el código QR con \'Barcode Scanner\'Para recibir las claves a través de NFC, el dispositivo tiene que estar desbloqueado.Ayuda
+ Escaneando código QR...Tomar la clave desde el portapapelesObtener clave desde Keybase.io
+
+
+ Clave importada con éxito
+ %1$d claves importadas con éxito
+
+
+ y clave%2$s actualizada.
+ y %1$d claves%2$s actualizadas.
+
+
+ Clave%2$s importada con éxito.
+ %1$d claves%2$s importadas con éxito.
+
+
+ Clave%2$s importada con éxito.
+ %1$d claves%2$s importadas con éxito.
+
+ Ver registro (log)
+ No hay nada que importar.
+ ¡Error importando claves!
+ , con advertenciasDescifrar archivo con OpenKeychainImportar clave con OpenKeychain
@@ -434,7 +437,7 @@
Firmar y cifrarDescifrar y verificarImportar claves
- Aplicaciones registradas
+ AplicacionesAbrir el Navigation DrawerCerrar el Navigation DrawerEditar
@@ -455,6 +458,142 @@
¡falló!¡error!clave no disponible
+
+ Aplicando operación de inserción por lote.
+ Se intentó importar un juego de claves (keyring) secreto como público. Esto es un fallo, por favor ¡consigne un informe!
+ No se borró ninguna clave antigua (¿crear una nueva?)
+ Clave antigua borrada de la base de datos
+ La operación falló debido a un error de codificación
+ La operación falló debido a un error de E/S
+ La operación falló debido a un error de la base de datos
+ La operación falló debido a un error interno
+ Importando juego de claves públicas %s
+ Codificando datos del juego de claves (keyring)
+ Analizando claves
+ Preparando base de datos de operaciones
+ Procesando clave maestra %s
+ El juego de claves expiró el %s
+ El juego de claves expira el %s
+ Distintivos de clave maestra: certificar, cifrar, firmar
+ Distintivos de clave maestra: certificar, cifrar
+ Distintivos de clave maestra: certificar, firmar
+ Distintivos de clave maestra: cifrar, firmar
+ Distintivos de clave maestra: certificar
+ Distintivos de clave maestra: cifrar
+ Distintivos de clave maestra: firmar
+ Distintivos de clave maestra: ninguno
+ Procesando subclave %s
+ La subclave expiró el %s
+ La subclave expira el %s
+ Distintivos de subclave: certificar, cifrar, firmar
+ Distintivos de subclave: certificar, cifrar
+ Distintivos de subclave: certificar, firmar
+ Distintivos de subclave: cifrar, firmar
+ Distintivos de subclave: certificar
+ Distintivos de subclave: cifrar
+ Distintivos de subclave: firmar
+ Distintivos de subclave: ninguno
+ Juego de claves públicas importado con éxito
+ El juego de claves no contiene nuevos datos, no hay nada que hacer
+ Re-insertando clave secreta
+ ¡Se encontró un certificado defectuoso!
+ ¡Error procesando certificado!
+ La identificación de usuario está certificada por %1$s (%2$s)
+
+ Ignorando un certificado publicado por una clave pública desconocida
+ Ignorando %s certificados publicados por claves públicas desconocidas
+
+ Clasificando identidades de usuario (no hay claves de confianza disponibles)
+
+ Clasificando identidades de usuario (usando una clave de confianza)
+ Clasificando identidades de usuario (usando %s claves de confianza)
+
+ Re-ordenando identidades de usuario
+ Procesando identidad (id) de usuario %s
+ La identificación de usuario está revocada
+ Se intentó importar un juego de claves (keyring) público como secreto. Esto es un fallo, por favor ¡consigne un informe!
+
+ Importando clave secreta (privada) %s
+ ¡Error de base de datos!
+ Procesando subclaves secretas
+ Error codificando el juego de claves
+ Generando un juego de claves públicas desde el juego de claves secretas (privadas)
+ Subclave %s no disponible en la clave pública
+ Se marcó %s como no disponible
+ Se marcó %s como desnudo (de subclave)
+ El juego de claves no contiene nuevos datos, no hay nada que hacer
+ Juego de claves secretas (privadas) importado con éxito
+
+ Canonicalizando juego de claves público %s
+ Canonicalizando juego de claves secreto %s
+ Fallo en la canonicalización de juego de claves: El juego de claves no tiene identificaciones de usuario válidas
+ Procesando clave maestra
+ Eliminando certificado defectuoso de revocación de juego de claves
+ Eliminando certificado de revocación de juego de claves, con distintivo \"local\"
+ Eliminando certificado de revocación de juego de claves, con marca de tiempo futura
+ Eliminando certificado de clave maestra, de tipo desconocido (%s)
+ Eliminando certificado defectuoso de revocación de juego de claves
+ Eliminando certificado redundante de revocación de juego de claves
+ Procesando subclave %s
+ Eliminando certificado no válido de vinculación de subclave
+ Eliminando certificado defectuoso de vinculación de subclave
+ Eliminando certificado de vinculación de subclave, con distintivo \"local\"
+ La identidad del publicante de la vinculación de subclave no coincide
+ Eliminando certificado de vinculación de subclave, con marca de tiempo futura
+ Tipo de certificado de subclave desconocido: %s
+ Eliminando certificado redundante de vinculación de subclave
+ Eliminando certificado de vinculación de subclave debido a un certificado de vinculación primario no válido
+ Eliminando certificado de vinculación de subclave debido a un certificado de vinculación primario defectuoso
+ Eliminando certificado de vinculación de subclave debido a un certificado de vinculación primario ausente
+ No se encontró ningún certificado válido para %s, eliminándola del juego de claves
+ Eliminando certificado defectuoso de revocación de subclave
+ Eliminando certificado defectuoso de revocación de subclave
+ Eliminando certificado redundante de revocación de subclave
+ Canonicalización del juego de claves exitosa, no hay cambios
+
+ Canonicalización de juego de claves completada, se eliminó un certificado erróneo
+ Canonicalización de juego de claves completada, se eliminaron %d certificados erróneos
+
+ Canonicalización de juego de claves completada, eliminados %1$s certificados erróneos y %2$s redundantes
+
+ Canonicalización de juego de claves completada, se eliminó un certificado redundante
+ Canonicalización de juego de claves completada, se eliminaron %d certificados redundantes
+
+ Eliminando auto-certificado defectuoso para la identidad de usuario %s
+ Eliminando certificado de identidad de usuario, con distintivo \"local\"
+ Eliminando identidad de usuario con marca de tiempo futura
+ Eliminando certificado de identidad de usuario, de tipo desconocido (%s)
+ Eliminando auto-certificado defectuoso para la identidad de usuario \"%s\"
+ Eliminando auto-certificado desactualizado para el identificador de usuario \"%s\"
+ Eliminando certificado ajeno de identidad de usuario por %s
+ Eliminando certificado redundate de revocación para la identidad de usuario \"%s\"
+ Eliminando certificado desactualizado de revocación para la identidad de usuario \"%s\"
+ No se encontró ningún auto-certificado válido para la identificación de usuario %s, eliminándola del juego de claves.
+
+ Incorporándolas en el juego de claves públicas %s
+ Incorporándolas en el juego de claves secretas (privadas) %s
+ Error fatal codificando la firma
+ Se intentaron consolidar juegos de claves heterogéneos
+ Añadiendo nueva subclave %s
+ Se encontraron %s nuevos certificados en el juego de claves
+
+ Modificando el juego de claves %s
+ ¡Excepción en la codificación!
+ ¡Excepción interna de PGP!
+ ¡Excepción con la firma!
+ Cambiando frase contraseña
+ Modificando subclave %s
+ ¡Intentó operar sobre una subclave ausente %s!
+ Generando nueva subclave %2$s de %1$s bits
+ Nueva identidad de subclave: %s
+ ¡La fecha de expiración no puede ser del pasado!
+ Revocando subclave %s
+ Juego de claves modificado con éxito
+ Añadiendo identidad de usuario %s
+ Cambiando identidad de usuario (uid) primaria a %s
+ Revocando identidad de usuario %s
+ ¡Error desbloqueando juego de claves!
+ Desbloqueando juego de clavesCertificadorDetalles del certificado
@@ -473,5 +612,8 @@
Ver detalles del certificadodesconocidono puede firmarse
+ Error de codificación¡No hay subclave de cifrado disponible!
+ No cree Cuentas-OpenKeychain manualmente.\nPara más información, vea la Ayuda.
+ Mostrar clave (%s)
diff --git a/OpenKeychain/src/main/res/values-et/strings.xml b/OpenKeychain/src/main/res/values-et/strings.xml
index 3b18bd0df..51f30015a 100644
--- a/OpenKeychain/src/main/res/values-et/strings.xml
+++ b/OpenKeychain/src/main/res/values-et/strings.xml
@@ -9,7 +9,6 @@
Loo võtiMuuda võtitSeaded
- Registreeritud rakendusedVõtmeserveri seadedMäära salasõneImpordi võtmeid
@@ -94,6 +93,7 @@
+
@@ -102,5 +102,10 @@
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml
index 55a85fb9b..f3627e9eb 100644
--- a/OpenKeychain/src/main/res/values-fr/strings.xml
+++ b/OpenKeychain/src/main/res/values-fr/strings.xml
@@ -8,8 +8,9 @@
Phrase de passeCréer une clefModifier une clef
+ Bienvenue à OpenKeychainPréférences
- Applications enregistrées
+ ApplisPréférences du serveur de clefsModifier la phrase de passeDéfinir la phrase de passe
@@ -27,6 +28,7 @@
Certifier les identitésDétails sur la clefAide
+ JournalidentitésSous-clefs
@@ -70,16 +72,11 @@
ParamètresAide
- Importer depuis un fichier
- Importer depuis un code QR
- Importer avec la NFCExporter vers un fichierSupprimer la clefCréer une clefCréer une clef (expert)Rechercher
- Serveur de clefs
- Importer depuis Keybase.ioServeur de clefs...Mettre à jour depuis le serveur de clefsTéléverser vers le serveur de clefs
@@ -98,6 +95,7 @@
Tout sélectionnerAjouter des clefsExporter toutes les clefs
+ Afficher les infos avancéesSignerMessage
@@ -206,33 +204,12 @@
Vous avez ajouté une identité vide, êtes-vous certain de vouloir continuer ?Voulez-vous vraiment supprimer la clef publique %s ?\nCeci est irréversible !Exporter aussi les clefs secrètes ?
-
- %d clef ajoutée avec succès
- %d clefs ajoutées avec succès
-
-
- et %d clef mise à jour.
- et %d clefs mises à jour.
-
-
- %d clef ajoutée avec succès.
- %d clefs ajoutées avec succès.
-
-
- %d clef mise à jour avec succès.
- %d clefs mises à jour avec succès.
-
- Aucune clef ajoutée ou mise à jour.1 clef exportée avec succès.%d clefs exportées avec succès.Aucune clef exportée.Note : seules les sous-clefs prennent en charge ElGamal.Note : générer des clefs RSA d\'une longueur de 1024 bits ou moins est considéré non sécuritaire et est désactivé pour la génération de nouvelles clefs.Clef %08X introuvable.
-
- %d clef trouvée.
- %d clefs trouvées.
- %d mauvaise clef ignorée. Vous avez peut-être exporté avec l\'option\n --export-secret-subkeys\nAssurez-vous d\'exporter plutôt avec\n --export-secret-keys.%d mauvaises clefs ignorées. Vous avez peut-être exporté avec l\'option\n --export-secret-subkeys\nAssurez-vous d\'exporter plutôt avec\n --export-secret-keys.
@@ -272,11 +249,11 @@
Les données binaires directes sans fichier dans le système de fichiers ne sont pas prises en charge.Il vous faut Android 4.1 pour utiliser la fonction Beam NFC d\'Android !La NFC n\'est pas disponible sur votre appareil !
- Rien à importer !
+ Aucune clef trouvée !La requête de recherche de clef est trop courteErreur irrécupérable lors de la recherche de clef sur le serveurLa requête de recherche de clef a retourné trop de candidats. Veuillez raffiner la requête
- Le fichier n\'a pas de contenu
+ Le fichier/le presse-papiers est videUne erreur générique est survenue, veuillez créer un nouveau rapport de bogue pour OpenKeychain.une partie du fichier chargé est un objet OpenPGP valide mais pas une clef OpenPGP
@@ -327,10 +304,10 @@
vérification de l\'intégrité...suppression sûre de « %s »...
- Rechercher des clefs publiques
+ Nom/courriel/ ID clef...Rechercher des clefs secrètesPartager la clef avec...
- Rechercher dans Keybase.io
+ Nom/nom d\'utilisateur keybase.io...512768
@@ -356,6 +333,10 @@
À propos deVersion :
+ Serveur de clefs
+ Fichier/presse-papiers
+ Code QR/NFC
+ Keybase.ioImporter les clefs choisiesImporter à partir du presse-papiers
@@ -369,8 +350,18 @@
Numériser le code QR avec le lecteur de code-barresPour recevoir des clefs par la NFC, les appareils doivent être déverrouillés.Aide
+ Balayer le code QR...Obtenir la clef depuis le presse-papiersObtenir la clef depuis Keybase.io
+
+
+ Clef importée avec succès
+ %1$d clefs importées avec succès
+
+ Consulter le journal
+ Rien à importer.
+ Erreur lors de l\'importation des clefs !
+ , avec des avertissementsDéchiffrer le fichier avec OpenKeychainImporter la clef avec OpenKeychain
@@ -434,7 +425,7 @@
Signer et chiffrerDéchiffrer et vérifierImporter les clefs
- Applis enregistrées
+ ApplisOuvrir le tiroir de navigationFermer le tiroir de navigationModifier
@@ -455,6 +446,146 @@
échec!erreur!clef non disponible
+
+ Application de l\'opération d\'insertion par lot.
+ Tentative d\'importer le trousseau secret comme public. Ceci est un bogue, veuillez remplir un rapport !
+ Aucune ancienne clef de supprimée (création d\'une nouvelle ?)
+ L\'ancienne clef a été supprimée de la base de données
+ Échec de l\'opération causé par une erreur d\'encodage
+ Échec de l\'opération causé par une erreur d\'e/s
+ Échec de l\'opération causé par une erreur de base de données
+ Échec de l\'opération causé par une erreur interne
+ Importation du trousseau public %s
+ Encodage des données du trousseau
+ Analyse des clefs
+ Préparation des opérations sur la base de données
+ Traitement de la clef maîtresse %s
+ Trousseau expiré le %s
+ Le trousseau expire le %s
+ Drapeaux de la clef maîtresse : certifier, chiffrer, signer
+ Drapeaux de la clef maîtresse : certifier, chiffrer
+ Drapeaux de la clef maîtresse : certifier, signer
+ Drapeaux de la clef maîtresse : chiffrer, signer
+ Drapeaux de la clef maîtresse : certifier
+ Drapeaux de la clef maîtresse : chiffrer
+ Drapeaux de la clef maîtresse : signer
+ Drapeaux de la clef maîtresse : aucun
+ Traitement de la sous-clef %s
+ La sous-clef a expiré le %s
+ La sous-clef expire le %s
+ Drapeaux de sous-clef : certifier, chiffrer, signer
+ Drapeaux de sous-clef : certifier, chiffrer
+ Drapeaux de sous-clef : certifier, signer
+ Drapeaux de sous-clef : chiffrer, signer
+ Drapeaux de sous-clef : certifier
+ Drapeaux de sous-clef : chiffrer
+ Drapeaux de sous-clef : signer
+ Drapeaux de sous-clef : aucun
+ Importation du trousseau public réussie
+ Le trousseau ne contient pas de nouvelle donnée, rien à faire
+ Réinsertion de la clef secrète
+ Un mauvais certificat a été rencontré !
+ Erreur lors du traitement du certificat !
+ L\'ID utilisateur est certifié par %1$s (%2$s)
+
+ Un certificat ignoré provenant d\'une clef publique inconnue
+ %s certificats ignorés provenant de clefs publiques inconnues
+
+ Classification des ID utilisateurs (aucune clef de confiance disponible)
+
+ Classification des ID utilisateurs (en utilisant une clef de confiance)
+ Classification des ID utilisateurs (en utilisant %s clefs de confiance)
+
+ Réorganisation des ID utilisateurs
+ Traitement de l\'ID utilisateur %s
+ L\'ID utilisateur est révoqué
+ Tentative d\'importer le trousseau public comme secret. Ceci est un bogue, veuillez remplir un rapport !
+
+ Importation de la clef secrète %s
+ Erreur de base de données!
+ Traitement des sous-clefs secrètes
+ Erreur lors de l\'encodage du trousseau
+ Génération du trousseau public à partir du trousseau secret
+ La sous-clef %s n\'est pas disponible dans la clef publique
+ %s marqué comme disponible
+ %s marqué comme dépouillée
+ Le trousseau ne contient pas de nouvelle donnée, rien à faire
+ Importation du trousseau secret réussie
+
+ Canonicalisation du trousseau public %s
+ Canonicalisation du trousseau secret %s
+ La canonicalisation du trousseau a échoué : le trousseau n\'a pas d\'ID utilisateur valides
+ Traitement de la clef maîtresse
+ Suppression du mauvais certificat de révocation du trousseau
+ Suppression du certificat de révocation du trousseau ayant le drapeau « local »
+ Suppression du certificat de révocation du trousseau ayant une estampille temporelle dans le futur
+ Suppression du certificat de clef maîtresse de type inconnu (%s)
+ Suppression du mauvais certificat de révocation du trousseau
+ Suppression du certificat redondant de révocation du trousseau
+ Traitement de la sous-clef %s
+ Suppression du certificat invalide de liaison de la sous-clef
+ Suppression du mauvais certificat de liaison de la sous-clef
+ Suppression du certificat de liaison de la sous-clef ayant le drapeau « local »
+ L\'ID de l\'émetteur de la liaison de la sous-clef ne correspond pas
+ Suppression du certificat de liaison de la sous-clef ayant une estampille temporelle dans le futur
+ Type de certificat de sous-clef inconnu : %s
+ Suppression du certificat redondant de liaison de sous-clef
+ Suppression du certificat de liaison de la sous-clef à cause d\'un certificat de liaison primaire invalide
+ Suppression du certificat de liaison de la sous-clef due à un mauvais certificat de liaison
+ Suppression du certificat de liaison de la sous-clef due à un certificat de liaison primaire manquant
+ Aucun certificat valide trouvé pour %s, qui est maintenant enlevé du trousseau
+ Suppression du certificat de révocation de la mauvaise sous-clef
+ Suppression du certificat de révocation de la mauvaise sous-clef
+ Suppression du certificat de révocation de la sous-clef redondante
+ Canonicalisation du trousseau réussie, aucun changement
+
+ Canonicalisation du trousseau réussie, un certificat erroné supprimé
+ Canonicalisation du trousseau réussie, %d certificats erronés supprimés
+
+ Canonicalisation du trousseau réussie, %1$s certificats erronés et %2$s certificats redondants supprimés
+
+ Canonicalisation du trousseau réussie, un certificat redondant supprimé
+ Canonicalisation du trousseau réussie, %d certificats redondants supprimés
+
+ Suppression du mauvais auto-certificat pour l\'ID utilisateur %s
+ Suppression du certificat d\'ID utilisateur ayant le drapeau « local »
+ Suppression de l\'ID utilisateur ayant une estampille temporelle dans le futur
+ Suppression du certificat d\'ID utilisateur de type inconnu (%s)
+ Suppression du mauvais auto-certificat pour l\'ID utilisateur « %s »
+ Suppression de l\'auto-certificat périmé pour l\'ID utilisateur « %s »
+ Suppression du certificat étranger d\'ID utilisateur par %s
+ Suppression du certificat de révocation redondant pour l\'ID utilisateur « %s »
+ Suppression du certificat de révocation périmé pour l\'ID utilisateur « %s »
+ Aucun auto-certificat valide trouvé pour l\'ID utilisateur %s, qui est maintenant enlevé du trousseau
+
+ Fusion vers le trousseau public %s
+ Fusion vers le trousseau secret %s
+ Erreur fatale lors de l\'encodage de la signature
+ Il a été tenté de consolider les trousseaux hétérogènes
+ Ajout de la nouvelle sous-clef %s
+ %s nouveaux certificats trouvés dans le trousseau
+
+ Modification du trousseau %s
+ Exception d\'encodage !
+ L\'empreinte de clef effective ne correspond pas à celle attendue !
+ Aucune ID de clef. Ceci est une erreur de programmation, veuillez remplir un rapport de bogue !
+ Erreur interne, le contrôle d\'intégrité a échoué !
+ Les IDs d\'un utilisateur révoqué ne peuvent pas être primaires !
+ Exception interne PGP !
+ Exception de signature !
+ Changement de la phrase de passe
+ Modification de la sous-clef %s
+ Une action a été tentée sur la sous-clef manquante %s !
+ Génération d\'une nouvelle sous-clef %2$s de %1$s bit
+ ID de la nouvelle sous-clef : %s
+ La date d\'expiration ne peut pas être dans le passé !
+ Révocation de la sous-clef %s
+ Trousseau modifié avec succès
+ Ajout de l\'ID utilisateur %s
+ Changement de l\'UID primaire en %s
+ Révocation de l\'ID utilisateur %s
+ Erreur lors du déverrouillage du trousseau !
+ Déverrouillage du trousseauCertificateurDétails du certificat
@@ -473,5 +604,8 @@
Voir les détails du certificatinconnuimpossible de signer
+ Erreur d\'encodageAucune sous-clef de chiffrement n\'est disponible !
+ Ne pas créer de comptes-OpenKeychain manuellement.\nPour plus d\'informations, consultez l\'aide.
+ Montrer la clef (%s)
diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml
index 300627fa7..c8ec2614d 100644
--- a/OpenKeychain/src/main/res/values-it/strings.xml
+++ b/OpenKeychain/src/main/res/values-it/strings.xml
@@ -8,8 +8,9 @@
Frase di accessoCrea ChiaveModifica Chiave
+ Benvenuto in OpenKeychainPreferenze
- App Registrate
+ AppsPreferenze Server delle ChiaviCambia Frase Di AccessoImposta Frase di Accesso
@@ -27,6 +28,7 @@
Certifica identitàDettagli ChiaveAiuto
+ RegistroIdentitàSottochiavi
@@ -70,16 +72,11 @@
ImpostazioniAiuto
- Importa da file
- Importa da Codice QR
- Importa tramite NFCEsporta su un fileCancella chiaveCrea chiaveCrea chiave (avanzato)Cerca
- Server delle Chiavi
- Importa da Keybase.ioServer delle Chiavi...Aggiorna dal server delle chiaviCarica chiave nel server
@@ -98,6 +95,7 @@
Seleziona tuttoAggiungi chiaviEsporta tutte le chiavi
+ Mostra informazioni avanzateFirmaMessaggio
@@ -206,33 +204,12 @@
Hai aggiunto una identità vuota, sei sicuro di voler continuare?Vuoi veramente eliminare la chiave pubblica \'%s\'?\nNon potrai annullare!Esportare anche le chiavi segrete?
-
- %d chiave aggiunta correttamente
- %d chiavi aggiunte correttamente
-
-
- e %d chiave aggiornata.
- e %d chiavi aggiornate.
-
-
- %d chiave aggiunta correttamente.
- %d chiavi aggiunte correttamente.
-
-
- %d chiave aggiornata correttamente.
- %d chiavi aggiornate correttamente.
-
- Nessuna chiave aggiunta o aggiornata.1 chiave esportata correttamente.%d chiavi esportate correttamente.Nessuna chiave esportata.Nota: supporto sottochiavi solo per ElGamal.Nota: la generazione di chiavi RSA con lunghezza pari a 1024 bit o inferiore è considerata non sicura ed è disabilitata per la generazione di nuove chiavi.Impossibile trovare la chiave %08X.
-
- Trovata %d chiave.
- Trovate %d chiavi.
- %d chiave segreta non valida ignorata. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece.%d chiavi private non valide ignorate. Forse hai esportato con opzione\n--export-secret-subkeys\nAssicurati di esportare con\n--export-secret-keys\ninvece.
@@ -272,8 +249,11 @@
Flusso di dati diretto senza file corrispettivo nel filesystem non e\' supportato.Devi avere Android 4.1 per usare Android NFC Beam!NFC non disponibile nel tuo dispositivo!
- Niente da importare!
- Il File non ha contenuti
+ Nessuna chiave trovata!
+ Chiave della query di ricerca troppo corta
+ Errore irreversibile nella ricerca di chiavi sul server
+ Chiave della query di ricerca ha generato troppi candidati; Si prega di perfezionare la ricerca
+ File/Appunti vuotiSi è verificato un errore generico, si prega di creare una nuova segnalazione di errore per OpenKeychain.parte del file caricato e\' un oggetto OpenPGP valido, ma non una chave OpenPGP
@@ -324,10 +304,10 @@
verifica integrita\'...eliminazione sicura di \'%s\'...
- Ricerca Chiavi Pubbliche
+ Nome/Email/ID Chiave...Cerca Chiave PrivataCondividi chiave con...
- Cerca Keybase.io
+ Nome/Keybase.io nome utente...512768
@@ -353,6 +333,10 @@
InfoVersione:
+ Server delle chiavi
+ File/Appunti
+ Codice QR/NFC
+ Keybase.ioImporta chiavi selezionateImporta dagli appunti
@@ -366,8 +350,14 @@
Scansiona il Codice QR con \'Barcode Scanner\'Per ricevere le chiavi via NFC, il dispositivo deve essere sbloccato.Aiuto
+ Scansione Codice QROttieni chiave dagli appuntiOttieni chiave da Keybase.io
+
+ Mostra registro
+ Niente da importare
+ Errore di importazione chiavi!
+ , con avvisiDecodifica File con OpenKeychainImporta Chiave con OpenKeychain
@@ -431,7 +421,7 @@
Firma e CodificaDecodifica e VerificaImporta Chiavi
- App Registrate
+ AppsApri drawer di navigazioneChiudi drawer di navigazioneModifica
@@ -452,6 +442,125 @@
fallito!errore!chiave non disponibile
+
+ Applicazione inserimento operazioni in batch.
+ Ho cercato di importare portachiavi privato come pubblico. Questo è un bug, per cortesia inviateci un rapporto!
+ Nessuna vecchia chiave cancellata (stai creando una nuova?)
+ Cancellate vecchie chiavi dal database
+ Operazione fallita a causa di un errore di codifica
+ Operazione fallita a causa di un errore di i/o
+ Operazione fallita a causa di un errore della banca dati
+ Operazione fallita a causa di un errore interno
+ Importazione portachiavi pubblico %s
+ Codifica dati del portachiavi
+ Elaborazione chiavi
+ Preparazione operazioni banca dati
+ Elaborazione chiave principale %s
+ Portachiavi scaduto il %s
+ Il portachiavi scade il %s
+ Caratteristiche chiave principale: certifica, codifica, firma
+ Caratteristiche chiave principale: certifica, codifica
+ Caratteristiche chiave principale: certifica, firma
+ Caratteristiche chiave principale: codifica, firma
+ Caratteristiche chiave principale: certifica
+ Caratteristiche chiave principale: codifica
+ Caratteristiche chiave principale: firma
+ Caratteristiche chiave principale: nessuna
+ Elaborazione sottochiave %s
+ Sottochiave scaduta il %s
+ La sottochiave scade il %s
+ Caratteristiche sottochiave: certifica, codifica, firma
+ Caratteristiche sottochiave: certifica, codifica
+ Caratteristiche sottochiave: certifica, firma
+ Caratteristiche sottochiave: codifica, firma
+ Caratteristiche sottochiave: certifica
+ Caratteristiche sottochiave: codifica
+ Caratteristiche sottochiave: firma
+ Caratteristiche sottochiave: nessuna
+ Portachiavi pubblico importato con successo
+ Il portachiavi non contiene nuovi dati, nulla da eseguire
+ Reinserimento chiave segreta
+ Riscontrato certificato sbagliato!
+ Errore elaborazione certificato!
+ ID utente certificato da %1$s (%2$s)
+ Riordinamento ID utenti
+ Elaborazione ID utente %s
+ ID utente revocato
+ Ho cercato di importare portachiavi pubblico come privato. Questo è un bug, per cortesia inviateci un rapporto!
+
+ Importazione chiave segreta %s
+ Errore Banca Dati!
+ Elaborazione sottochiavi segrete
+ Errore codifica portachiavi
+ Generazione portachiavi pubblico da portachiavi privato
+ Sottochiave %s non disponibile nella chiave pubblica
+ %s marcate come disponibili
+ %s marcate come ripulite
+ Il portachiavi non contiene nuovi dati, nulla da eseguire
+ Portachiavi segreto importato con successo
+
+ Canonicalizzazione portachiavi pubblico %s
+ Canonicalizzazione portachiavi segreto %s
+ Canonicalizzazione portachiavi fallita: il portachiavi non ha ID utenti validi
+ Elaborazione chiave principale
+ Rimozione di certificato di revoca del portachiavi corrotto
+ Rimozione certificato di revoca del portachiavi con caratteristica \"locale\"
+ Rimozione certificato di revoca del portachiavi con marca temporale futura
+ Rimozione certificato della chiave principale di tipo sconosciuto (%s)
+ Rimozione certificato di revoca del portachiavi corrotto
+ Rimozione certificato di revoca del portachiavi ridondante
+ Elaborazione sottochiave %s
+ Rimozione certificato vincolante di sottochiave non valido
+ Rimozione certificato vincolante di sottochiave corrotto
+ Rimozione certificato di sottochiave con caratteristica \"locale\"
+ ID emittente vincolante della sottochiave non corrispondente
+ Rimozione certificato vincolante della sottochiave con marca temporale futura
+ Tipo di certificato della sottochiave sconosciuto: %s
+ Rimozione certificato vincolante di sottochiave ridondante
+ Rimozione certificato vincolante della sottochiave a causa di certificato vincolante primario non valido
+ Rimozione certificato vincolante della sottochiave a causa di certificato vincolante primario corrotto
+ Rimozione certificato vincolante della sottochiave a causa di certificato vincolante primario mancante
+ Certificato valido non trovato per %s, rimozione dal portachiavi
+ Rimozione certificato di revoca corrotto della sottochiave
+ Rimozione certificato di revoca corrotto della sottochiave
+ Rimozione certificato di revoca ridondante della sottochiave
+ Canonicalizzazione del portachiavi avvenuta con successo, nessuna modifica
+ Canonicalizzazione portachiavi con successo, rimossi %1$s certificati errati e %2$s certificati ridondanti
+ Rimozione autocertificazione corrotta per ID utente %s
+ Rimozione certificato ID utente con caratteristica \"locale\"
+ Rimozione ID utente con marca temporale futura
+ Rimozione certificato ID utente di tipo sconosciuto (%s)
+ Rimozione autocertificazione corrotta per ID utente \"%s\"
+ Rimozione autocertificazione scaduta per ID utente \"%s\"
+ Rimozione certificato ID utente estraneo di %s
+ Rimozione certificato di revoca ridondante per ID utente \"%s\"
+ Rimozione certificato di revoca scaduto per ID utente \"%s\"
+ Nessuna autocertificazione valida trovata per ID utente %s, rimozione dal portachiavi
+
+ Fusione nel portachiavi pubblico %s
+ Fusione nel portachiavi privato %s
+ Errore fatale nella codifica della firma
+ Tentativo di consolidare portachiavi eterogenei
+ Aggiunta nuova sottochiave %s
+ Trovati %s nuovi certificati nel portachiavi
+
+ Modifica del portachiavi %s
+ Eccezione di codifica!
+ Eccezione interna di PGP!
+ Eccezione di firma!
+ Cambio frase di accesso
+ Modifica sottochiave %s
+ Tentativo di operare su sottochiave mancante %s!
+ Generazione nuovi %1$s bit %2$s sottochiave
+ Nuovo ID sottochiave: %s
+ La data di scadenza non può essere passata!
+ Revoca sottochiave %s
+ Portachiavi modificato con successo
+ Aggiunta id utente %s
+ Cambio UID primario in %s
+ Revoca ID utente %s
+ Errore di apertura portachiavi!
+ Apertura portachiaviCertificatoreDettagli Certificato
@@ -470,5 +579,8 @@
Visualizza Dettagli Certificatisconosciutonon può firmare
+ Errore di codificaNessuna sottochiave di codifica disponibile!
+ Non creare account OpenKeychain manualmente\nPer ulteriori informazioni, vedere la Guida.
+ Mostra chiave (%s)
diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml
index 63fef2af2..13463df25 100644
--- a/OpenKeychain/src/main/res/values-ja/strings.xml
+++ b/OpenKeychain/src/main/res/values-ja/strings.xml
@@ -8,8 +8,9 @@
パスフレーズ鍵の生成鍵の編集
+ OpenKeychainへようこそ設定
- 登録済みのアプリケーション
+ アプリ鍵サーバ設定パスフレーズの変更パスフレーズの設定
@@ -27,6 +28,7 @@
ユーザID検証鍵の概要ヘルプ
+ ログユーザID副鍵
@@ -70,16 +72,11 @@
設定ヘルプ
- ファイルからインポート
- QRコードからインポート
- NFCからインポートファイルへのエクスポート鍵の削除鍵の生成鍵の生成(上級)検索
- 鍵サーバ
- Keybase.ioからのインポート鍵サーバ...鍵サーバからの更新鍵サーバへのアップロード
@@ -98,6 +95,7 @@
すべて選択鍵の追加すべての鍵のエクスポート
+ 詳細情報を表示署名メッセージ
@@ -203,28 +201,12 @@
あなたは空のユーザIDを追加しました、このまま続けますか?公開鍵\'%s\'を本当に削除してもよいですか?\nこれは元に戻せません!秘密鍵もエクスポートしますか?
-
- %d の鍵を追加しました
-
-
- そして %d の鍵をアップロードしました。
-
-
- %d の鍵を追加しました。
-
-
- %d の鍵をアップロードしました。
-
- 鍵の追加もしくは更新はありませんでした。1つの鍵をエクスポートしました。%d の鍵をエクスポートしました。鍵をエクスポートしていません。ノート: 副鍵はElGamalでのみサポートされます。付記: 長さ1024bitかそれ以下で生成されたRSA鍵は安全とはみなされず、新な鍵の生成は無効にされています。鍵 %08X は見付かりませんでした。
-
- %d の鍵を発見。
- %d の問題ある鍵を無視しました。 おそらく次のオプションでエクスポートしています\n --export-secret-subkeys\n代りに次のオプションでエクスポートしてください。\n --export-secret-keys
@@ -263,11 +245,11 @@
ファイルシステムに存在するファイルではないバイナリデータはサポートされません。Android NFC Beam機能を使うにはAndroid 4.1 が必要です!あなたのデバイスにはNFCが存在しません!
- インポートするものがありません!
+ 鍵が見当りません!鍵検索のクエリが短かすぎますサーバでの鍵の検索が回復不可能なエラーになりました鍵検索のクエリが沢山の候補を返しました; クエリを精密化してください
- ファイルに内容がありません
+ ファイル/クリップボードが空です一般エラーが発生しました、この新しいバグの情報をOpenKeychainプロジェクトに送ってください読み込んだファイルのOpenPGPオブジェクト部分は正しいですが、OpenPGPの鍵ではありません
@@ -315,10 +297,10 @@
完全性の検証中...\'%s\' を完全に削除中…
- 公開鍵の検索
+ 名前/メール/鍵ID...秘密鍵の検索...で鍵の共有
- Keybase.ioでの検索
+ 名前/Keybase.io名...512768
@@ -344,6 +326,10 @@
これについてバージョン:
+ 鍵サーバ
+ ファイル/クリップボード
+ QRコード/NFC
+ Keybase.io選択した鍵のインポートクリップボードからインポート
@@ -356,8 +342,26 @@
\'バーコードスキャナー\'でQRコードをスキャンするNFCで鍵を受信しました、デバイスのロックを解除する必要があります。ヘルプ
+ QCコードのスキャン...クリップボードから鍵を取得Keybase.ioから鍵を取得
+
+
+ %1$d の鍵のインポートに成功
+
+
+ そして%1$d の鍵%2$s をアップデート。
+
+
+ %1$d の鍵%2$sのインポートに成功。
+
+
+ %1$d の鍵%2$sのアップデートに成功。
+
+ ログを見る
+ インポートするものがありません。
+ 鍵のインポートのエラー!
+ 、とワーニングOpenKeychainでファイルを復号化OpenKeychainに鍵をインポート
@@ -420,7 +424,7 @@
署名と暗号化復号化と検証鍵のインポート
- 登録済みのアプリ
+ アプリナビゲーションドロワーを開くナビゲーションドロワーを閉める編集
@@ -441,6 +445,142 @@
失敗!エラー!鍵がありません
+
+ 連続挿入処理を適用する。
+ 秘密鍵の鍵輪を公開鍵としてインポートを試行しました。これはバグで、ファイルをレポートしてください!
+ 削除された古い鍵はありません (新しく作りますか?)
+ データベースから古い鍵を削除しました
+ エンコードエラーにより操作が失敗しました
+ I/Oエラーにより操作が失敗しました
+ データベースエラーにより操作が失敗しました
+ 内部エラーにより操作が失敗しました
+ 公開鍵の鍵輪 %s をインポート
+ 鍵輪データのエンコード中
+ 鍵の解析中
+ データベース操作の準備
+ 主鍵処理中 %s
+ %s が鍵輪の期限切れ
+ %s に鍵輪が期限切れ
+ 主鍵のフラグ: 検証、暗号化、署名
+ 主鍵のフラグ: 検証、暗号化
+ 主鍵のフラグ: 検証、署名
+ 主鍵のフラグ: 暗号化、署名
+ 主鍵のフラグ: 検証
+ 主鍵のフラグ: 暗号化
+ 主鍵のフラグ: 署名
+ 主鍵のフラグ: なし
+ 副鍵 %s の処理中
+ %s が副鍵の期限切れ
+ %s に副鍵が期限切れ
+ 副鍵のフラグ: 検証、暗号化、署名
+ 副鍵のフラグ: 検証、暗号化
+ 副鍵のフラグ: 検証、署名
+ 副鍵のフラグ: 暗号化、署名
+ 副鍵のフラグ: 検証
+ 副鍵のフラグ: 暗号化
+ 副鍵のフラグ: 署名
+ 副鍵のフラグ: なし
+ 公開鍵の鍵輪のインポートに成功
+ 鍵輪にデータがないため、なにもしません
+ 秘密鍵を再挿入中
+ 問題のある検証と遭遇しました!
+ 検証の処理中にエラーしました!
+ ユーザIDは %1$s (%2$s) によって検証されました
+
+ 不明な公開鍵から %s の検証を無視
+
+ ユーザIDを検証 (信頼された鍵がありません)
+
+ ユーザIDを検証 ( %s の信頼された鍵を使いました)
+
+ ユーザIDの並べ直し
+ ユーザID %s の処理中
+ ユーザIDは破棄されました
+ 公開鍵の鍵輪を秘密鍵としてインポートを試行しました。これはバグで、ファイルをレポートしてください\"
+
+ 秘密鍵 %s のインポート中
+ データベースエラー!
+ 秘密鍵の副鍵の処理中
+ 鍵輪のエンコードエラー
+ 秘密鍵の鍵輪から公開鍵の鍵輪を生成中
+ 公開鍵の中の副鍵 %s が利用不可能
+ %s を利用可能としてマーク
+ %s をストリップとしてマーク
+ 鍵輪にデータがないため、なにもしません
+ 秘密鍵の鍵輪のインポートに成功
+
+ 公開鍵の鍵輪 %s の正規化中
+ 秘密鍵の鍵輪 %s の正規化中
+ 鍵輪の正規化に失敗: 鍵輪が正しいユーザIDを含んでいませんでした
+ 主鍵処理中
+ 問題のある鍵輪の破棄証明を破棄中
+ 鍵輪のローカルフラグ付き破棄証明を破棄中
+ 鍵輪の未来にタイムスタンプがある破棄証明を破棄中
+ 問題のある主鍵の不明な型 (%s) の証明を破棄中
+ 問題のある鍵輪の破棄証明を破棄中
+ 重複している鍵輪の破棄証明を破棄中
+ 副鍵 %s の処理中
+ 証明が付随する不正な副鍵を破棄中
+ 証明が付随する問題のある副鍵を破棄中
+ ローカルフラグ付きの証明が付随する副鍵を破棄中
+ 副鍵の発行者のIDと付随するIDがミスマッチ
+ 未来にタイムスタンプがある証明が付随する副鍵を破棄中
+ 不明な検証のタイプ: %sの副鍵
+ 証明が付随する重複する副鍵を破棄中
+ 付随する主たる証明が正しくない証明が付随する副鍵を破棄中
+ 付随する主たる証明に問題がある証明が付随する副鍵を破棄中
+ 付随する主たる証明が失なわれている証明が付随する副鍵を破棄中
+ %s から正常な検証が見付かりません、鍵輪から除外します
+ 問題のある副鍵の破棄証明を破棄中
+ 問題のある副鍵の破棄証明を破棄中
+ 重複している副鍵の破棄証明を破棄中
+ 鍵輪の正規化に成功、変更なし
+
+ 鍵輪の認可に成功、 %d 個のエラーのある証明を除去
+
+ 鍵輪の認可に成功、 %1$s なエラーのある証明と %2$s の重複を除去
+
+ 鍵輪の認可に成功、 %d 個の重複を除去
+
+ ユーザID %s による問題のある自己検証を破棄中
+ ローカルフラグ付きのユーザID検証を破棄中
+ 未来にタイムスタンプがあるユーザIDを破棄中
+ 不明な型 (%s) でのユーザID検証を破棄中
+ ユーザID \"%s\" による問題のある自己検証を破棄中
+ 期限の切れたユーザID \"%s\" による自己検証を破棄中
+ %s によって検証されている外部ユーザIDを破棄中
+ ユーザID \"%s\" による重複した破棄証明を破棄中
+ ユーザID \"%s\" による期限切れ破棄証明を破棄中
+ ユーザID %s の正常な自己署名が見付かりませんでした、鍵輪から除去しました
+
+ 公開鍵の鍵輪 %s にマージ中
+ 秘密鍵の鍵輪 %s にマージ中
+ 署名のエンコードでの致命的なエラー
+ 種類の異なる鍵輪を統合しようとした
+ 新しい副鍵 %s を追加中
+ 鍵輪に新しい検証を %s 発見
+
+ 鍵輪 %s を変更中
+ エンコード例外!
+ 現実の鍵指紋が予想と合致しませんでした!
+ 鍵IDがない。 これはプログラミングのエラーで、バグレポートの提出をお願いします!
+ 内部エラー、完全性チェックが失敗!
+ 主ユーザIDの破棄はできません!
+ PGP内部例外!
+ 署名例外!
+ パスフレーズの変更中
+ 副鍵 %s を変更中
+ 遺失した副鍵 %s の操作をしようとした!
+ 新しい %1$s ビットの %2$s 副鍵の生成中
+ 新しい副鍵 ID: %s
+ 期限切れ日を過去にはできません!
+ 副鍵 %s を破棄中
+ 鍵輪の変更に成功
+ ユーザID %s を追加中
+ 主UIDを %s に変更中
+ ユーザID %s を破棄中
+ 鍵輪のロック解除エラー!
+ 鍵輪のロック解除中検証者証明の詳細
@@ -452,12 +592,15 @@
検証ステータス種別鍵が見当りません!
- 鍵処理のエラー!
+ 鍵処理中のエラー!副鍵がありませんスリム化秘密鍵は個別にしか削除できません!証明の詳細を見る不明署名不可
+ エンコードエラー暗号化の副鍵がありません!
+ OpenKeychainのアカウントを手動では生成できません.\nより詳細は、ヘルプを参照のこと。
+ 鍵 (%s) を表示
diff --git a/OpenKeychain/src/main/res/values-ko/strings.xml b/OpenKeychain/src/main/res/values-ko/strings.xml
index e3d3a6493..593fc2d11 100644
--- a/OpenKeychain/src/main/res/values-ko/strings.xml
+++ b/OpenKeychain/src/main/res/values-ko/strings.xml
@@ -19,6 +19,7 @@
+
@@ -27,5 +28,10 @@
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml
index f75d7a166..11b6c9673 100644
--- a/OpenKeychain/src/main/res/values-nl/strings.xml
+++ b/OpenKeychain/src/main/res/values-nl/strings.xml
@@ -9,7 +9,6 @@
Sleutel aanmakenSleutel bewerkenInstellingen
- Geregistreerde appsSleutelserver VoorkeurWachtwoord wijzigenWachtwoord instellen
@@ -70,16 +69,11 @@
InstellingenHelp
- Importeren uit bestand
- Importeren met QR-code
- Importeren met NFCExporteren naar bestandSleutel verwijderenSleutel aanmakenSleutel aanmaken (expert)Zoeken
- Sleutelserver
- Importeren uit Keybase.ioSleutelserver...Update van sleutelserverUpload naar sleutelserver
@@ -206,33 +200,12 @@
U heeft een lege identiteit toegevoegd, weet u zeker dat u wilt doorgaan?Wilt u echt de publieke sleutel \'%s\' verwijderen?\nDit kunt u niet ongedaan maken!Ook geheime sleutels exporteren?
-
- Succesvol %d sleutel toegevoegd
- Succesvol %d sleutels toegevoegd
-
-
- en %d sleutel bijgewerkt.
- en %d sleutels bijgewerkt.
-
-
- Succesvol %d sleutel toegevoegd.
- Succesvol %d sleutels toegevoegd.
-
-
- Succesvol %d sleutel bijgewerkt.
- Succesvol %d sleutels bijgewerkt.
-
- Geen sleutels toegevoegd of bijgewerkt.1 sleutel succesvol geëxporteerd.Succesvol %d sleutels geëxporteerd.Geen sleutels geëxporteerd.Opmerking: alleen subsleutels ondersteunen ElGamal.Opmerking: RSA sleutel met lengte 1024-bit en minder genereren wordt als onveilig beschouwd en is uitgeschakeld voor het genereren van nieuwe sleutels.Kan de sleutel %08X niet vinden.
-
- %d sleutel gevonden.
- %d sleutels gevonden.
- %d slechte geheime sleutel genegeerd. Misschien heeft u geëxporteerd met de optie\n --export-secret-subkeys\nZorg ervoor dat u in plaats daarvan met\n --export-secret-keys\nexporteert.%d slechte geheime sleutels genegeerd. Misschien heeft u geëxporteerd met de optie\n --export-secret-subkeys\nZorg ervoor dat u in plaats daarvan met\n --export-secret-keys\nexporteert.
@@ -272,8 +245,6 @@
Directe binaire data zonder eigenlijke bestand in bestandssysteem wordt niet ondersteund.U heeft minstens Android 4.1 nodig om Androids NFC Beam eigenschap te gebruiken!Uw apparaat biedt geen ondersteuning voor NFC
- Niets te importeren
- Bestand heeft geen inhoudEen algemene fout is opgetreden, maak alstublieft een nieuwe bug report voor OpenKeychain.Deel van het geladen bestand is geldig OpenPGP object maar niet een OpenPGP sleutel
@@ -324,10 +295,8 @@
integriteit verifiëren...\'%s\' veilig verwijderen...
- Publieke sleutels zoekenPrivésleutels zoekenSleutel delen met...
- Doorzoek Keybase.io512768
@@ -368,6 +337,7 @@
HelpVerkrijg sleutel uit klembordVerkrijg sleutel uit Keybase.io
+
Decodeer bestand met OpenKeychainImporteer Sleutel met OpenKeychain
@@ -431,7 +401,6 @@
Ondertekenen en VersleutelenDecoderen en VerifiërenImporteer Sleutels
- Geregistreerde appsOpen navigatiemenuSluit navigatiemenuBewerken
@@ -452,6 +421,11 @@
mislukt!fout!sleutel onbeschikbaar
+
+
+
+
+
CertificeerCertificaat Details
diff --git a/OpenKeychain/src/main/res/values-pl/strings.xml b/OpenKeychain/src/main/res/values-pl/strings.xml
index 851e77c3a..9e41373f4 100644
--- a/OpenKeychain/src/main/res/values-pl/strings.xml
+++ b/OpenKeychain/src/main/res/values-pl/strings.xml
@@ -9,7 +9,6 @@
Utwórz KluczEdytuj KluczWłaściwości
- Zarejestrowane AplikacjeWłaściwości serwera kluczyZmień hasłoUstaw hasło
@@ -55,15 +54,11 @@
UstawieniaPomoc
- Zaimportuj z pliku
- Zaimportuj z kodu QR
- Zaimportuj przy użyciu NFCEksportuj do plikuUsuń kluczStwórz kluczStwórz klucz (tryb zaawansowany)Znajdź
- Serwer kluczySerwer kluczy...Aktualizuj z serwera kluczyWyślij do serwera kluczy
@@ -191,38 +186,12 @@
Zostały dokonane zmiany w pęku kluczy, czy chcesz je zachować?Czy na pewno chcesz usunąć klucz publiczny \'%s\'?\nNie można cofnąć tej operacji!Czy wyeksportować również klucze prywatne?
-
- Pomyślnie dodano %d klucz
- Pomyślnie dodano %d kluczy
- Pomyślnie dodano %d kluczy
-
-
- i zaktualizowano %d klucz.
- i zaktualizowano %d kluczy.
- i zaktualizowano %d kluczy.
-
-
- Pomyślnie dodano %d klucz.
- Pomyślnie dodano %d kluczy.
- Pomyślnie dodano %d kluczy.
-
-
- Pomyślnie zaktualizowano %d klucz.
- Pomyślnie zaktualizowano %d kluczy.
- Pomyślnie zaktualizowano %d kluczy.
-
- Nie dodano ani zaktualizowano żadnych kluczy.Pomyślnie wyeksportowano 1 klucz.Pomyślnie wyeksportowano %d kluczy.Nie wyeksportowano żadnych kluczy.Informacja: tylko podklucze mogą być tworzone przy użyciu algorytmu ElGamal.Uwaga: generowanie klucza RSA o długości 1024 bity i mniejszej jest uważane za niebezpieczne i wyłączone dla tworzenia nowych kluczy.Nie można znaleźć klucza %08X.
-
- Znaleziono %d klucz.
- Znaleziono %d kluczy.
- Znaleziono %d kluczy.
- Zignorowano %d niepoprawny klucz prywatny. Prawdopodobnie został wyeksportowany przy uzyciu opcji\n --export-secret-subkeys\nUpewnij się że eksportujesz go z opcją\n --export-secret-keys\nktóra jest poprawna.Zignorowano %d niepoprawnych kluczy prywatnych. Prawdopodobnie zostały wyeksportowane przy uzyciu opcji\n --export-secret-subkeys\nUpewnij się że eksportujesz je z opcją\n --export-secret-keys\nktóra jest poprawna.
@@ -258,8 +227,6 @@
Dane binarne pozbawione pliku nie są obsługiwane.Potrzebujesz Androida 4.1 aby korzystać z Android NFC BeamNCF jest niedostępne na twoim urządzeniu
- Nie ma nic do zaimportowania!
- Plik jest pustyWystąpił błąd ogólny, proszę zgłoś go autorom OpenKeychain.Część wczytanego pliku jest poprawnym obiektem OpenPGP, ale nie jest kluczem OpenPGP
@@ -313,7 +280,6 @@
weryfikacja spójności...usuwanie \'%s\' bezpiecznie…
- Wyszukaj klucze publiczneWyszukaj klucze prywatneUdostępnij klucz...
@@ -356,6 +322,7 @@
Aby odbierać klucze przez NFC, urządzenie musi być odblokowane.PomocOdczytaj klucz ze schowka
+
Deszyfruj plik korzystając z OpenKeychainImportuj klucz korzystając z OpenKeychain
@@ -408,7 +375,6 @@
Podpisz i zaszyfrujDeszyfruj i weryfikujImportuj klucze
- Zarejestrowane aplikacjeOtwórz panel nawigacjiZamknij panel nawigacjiEdytuj
@@ -428,6 +394,11 @@
niepowodzenie!błąd!klucz niedostępny
+
+
+
+
+
Szczegóły certyfikatu<nieznany>
diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml
index b108324d1..539a431b5 100644
--- a/OpenKeychain/src/main/res/values-ru/strings.xml
+++ b/OpenKeychain/src/main/res/values-ru/strings.xml
@@ -8,8 +8,9 @@
ПарольСоздать ключИзменить ключ
+ Добро пожаловать в OpenKeychainНастройки
- Связанные приложения
+ ПриложенияНастройки сервера ключейИзменить парольЗадать пароль
@@ -27,6 +28,7 @@
СертифицироватьСведения о ключеПомощь
+ ЖурналИдентификаторыДоп. ключи
@@ -70,16 +72,11 @@
НастройкиПомощь
- Импорт из файла
- Импорт из QR кода
- Импорт из NFCЭкспорт в файлУдалить ключСоздать ключСоздать ключ (эксперт)Поиск
- Сервер ключей
- Импорт с сервера Keybase.ioСервер ключей...Обновить с сервера ключейЗагрузить на сервер ключей
@@ -98,6 +95,7 @@
Выбрать всеДобавить ключиЭкспорт всех ключей
+ Подробные данныеПодписатьСообщение
@@ -122,7 +120,7 @@
Серверы ключейID ключаСоздан
- Годен до...
+ Годен доПрименениеРазмер ключаОсновной идентификатор
@@ -143,6 +141,8 @@
<нет ключа>шифрованиеподпись
+ сертификация
+ не для сертификациипросроченотозван
@@ -178,9 +178,10 @@
ОшибкаОшибка: %s
- Сертифицировать
- Подписать
- Зашифровать
+ Сертификация
+ Подписание
+ Шифрование
+ АутентификацияНеправ. парольСначала задайте пароль
@@ -206,38 +207,12 @@
Вы добавили пустой идентификатор. Вы уверены, что хотите продолжить?Вы правда хотите удалить публичный ключ \'%s\'?\nЭто действие нельзя отменить!Экспортировать секретные ключи?
-
- Успешно добавлено %d ключ
- Успешно добавлено %d ключей
- Успешно добавлено %d ключей
-
-
- и обновлен %d ключ.
- и обновлено %d ключей.
- и обновлено %d ключей.
-
-
- Добавлен %d ключ
- Добавлено %d ключей
- Добавлено %d ключей
-
-
- Обновлен %d ключ.
- Обновлено %d ключей.
- Обновлено %d ключей.
-
- Нет обновленных или добавленных ключейУспешный экспорт 1 ключа.Экспортировано %d ключей.Ключи не были экспортированы.Прим.: только вторичные ключи поддерживают ElGamal.Внимание: создание ключей RSA длиной 1024 бита и менее признано небезопасным. Данная возможность отключена.Не удается найти ключ %08X.
-
- Найден %d ключ.
- Найдено %d ключей.
- Найдено %d ключей.
- %d плохой секретный ключ проигнорирован. Возможно, вы экспортируете с параметром\n--export-secret-subkeys\nВместо этого используйте\n--export-secret-keys%d плохих секретных ключей проигнорировано. Возможно, вы экспортируете с параметром\n--export-secret-subkeys\nВместо этого используйте\n--export-secret-keys\n
@@ -278,11 +253,11 @@
Прямая передача данных без использования файла в памяти устройства не поддерживается.Для использования NFC Beam требуется Android 4.1+ !Ваше устройство не поддерживает NFC!
- Нет данных для импорта!
+ Ключи не найдены!Запрос слишком короткийОшибка поиска ключей на сервереПоиск ключа вернул слишком много вариантов; Пожалуйста, уточните запрос
- Файл пуст
+ Файл/Буфер пустВыявлена ошибка. Пожалуйста, сообщите о ней разработчику.часть загруженного файла содержит данные OpenPGP, но это не ключ
@@ -336,10 +311,9 @@
проверка целостности...безопасное удаление \'%s\'...
- Найти публичные ключи
+ Имя/Email/ID ключа…Найти секретные ключиОтправить...
- Поиск на сервере Keybase.io512768
@@ -365,6 +339,10 @@
О программеВерсия:
+ Сервер ключей
+ Файл/Буфер
+ QR код/NFC
+ Keybase.ioИмпорт выбранных ключейИмпорт из буфера обмена
@@ -379,8 +357,24 @@
Сканировать QR код с \'Barcode Scanner\'Разблокируйте устройство, что бы получить ключ через NFC.Помощь
+ Сканировать QR код...Получить ключ из буфераПолучить ключ с сервера Keybase.io
+
+
+ Ключ успешно импортирован
+ Успешно добавлено %1$d ключей
+ Успешно добавлено %1$d ключей
+
+
+ и обновлен ключ%2$s.
+ и обновлено %1$d ключей%2$s.
+ и обновлено %1$d ключей%2$s.
+
+ Смотреть журнал
+ Нет данных для импорта.
+ Ошибка импорта ключей!
+ , с предупреждениямиOpenKeychain: Расшифровать файлOpenKeychain: Импортировать ключ
@@ -445,7 +439,7 @@
Подписать и зашифроватьРасшифровать и проверитьИмпорт ключей
- Связанные приложения
+ ПриложенияОткрыть панель навигацииЗакрыть панель навигацииИзменить
@@ -464,6 +458,46 @@
сбой!ошибка!ключ не доступен
+
+ Выполнение пакетной вставки.
+ Попытка импорта секретной связки как публичной. Это ошибка, пожалуйста, сообщите об этом.
+ Старый ключ не удален (создать новый?)
+ Старый ключ удален из базы
+ Действие прервано из-за ошибки кодировки
+ Действие прервано из-за ошибки ввода/вывода
+ Действие прервано из-за внутренней ошибки
+ Импорт связки публичных ключей %s
+ Подготовка операций
+ Успешно внесена связка публичных ключей
+ Повторное внесение секретного ключа
+ Плохой сертификат!
+ Ошибка обработки сертификата!
+ Обработка id %s
+ id аннулирован
+ Попытка импорта публичной связки как секретной. Это ошибка, пожалуйста, сообщите об этом.
+
+ Импорт секретного ключа %s
+ Ошибка базы данных!
+ Обработка секретных ключей
+ Успешно добавлена связка секретных ключей
+
+ Подготовка основного ключа
+
+
+ Ошибка кодирования!
+ Нет ID ключа. Это программная ошибка. Пожалуйста, сообщите об этом!
+ Внутренняя ошибка, сбой проверки целостности!
+ Аннулированные идентификаторы не могут быть основными!
+ Внутренняя ошибка PGP!
+ Ошибка подписи!
+ Изменение пароля
+ Срок годности не может быть в прошлом!
+ Связка успешно изменена
+ Добавление id %s
+ Изменение основного uid на %s
+ Аннулирование id %s
+ Ошибка разблокирования связки!
+ Разблокирование связкиКем подписанДетали сертификации
@@ -480,5 +514,9 @@
Секретные ключи можно удалять только по одному!Просмотреть детали сертификациинеизв.
+ не для подписания
+ Ошибка кодировкиНет доп. ключа для шифрования!
+ Не создавать аккаунт OpenKeychain вручную.\nДля подробной информации, смотрите раздел Помощь.
+ Показать ключ (%s)
diff --git a/OpenKeychain/src/main/res/values-sk/strings.xml b/OpenKeychain/src/main/res/values-sk/strings.xml
new file mode 100644
index 000000000..593fc2d11
--- /dev/null
+++ b/OpenKeychain/src/main/res/values-sk/strings.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values-sl/strings.xml b/OpenKeychain/src/main/res/values-sl/strings.xml
index 0fe44725b..61fe6ed86 100644
--- a/OpenKeychain/src/main/res/values-sl/strings.xml
+++ b/OpenKeychain/src/main/res/values-sl/strings.xml
@@ -9,7 +9,6 @@
Ustvari klučUredi ključNastavitve
- Prijavljene aplikacijeNastavitve strežnikovSpremeni gesloDoloči geslo
@@ -70,16 +69,11 @@
NastavitvePomoč
- Uvozi iz datoteke
- Uvozi iz kode QR
- Uvozi preko NFCIzvozi v datotekoIzbriši ključUstvari ključUstvari ključ (napredno)Išči
- Strežnik
- Uvozi iz Keybase.ioStrežnik...Posodobi s strežnikaNaloži na strežnik
@@ -98,6 +92,7 @@
Izberi vseDodaj ključeIzvozi vse ključe
+ Prikaži dodatne informacijePodpišiSporočilo
@@ -208,47 +203,16 @@
Določite datoteko, kamor želite izvoziti vsebino.\nPOZOR: če datoteka že obstaja, bo prepisana.Ali res želite izbrisati vse izbrane javne ključe?\nTega koraka ne boste mogli preklicati!Ali res želite izbrisati ZASEBNI ključ \'%s\'?\nTega koraka ne boste mogli preklicati!
- Vnesli ste spremembe v vaš \'keyring\'. Jih želite shraniti?
+ Vnesli ste spremembe v zbirko ključev. Jih želite shraniti?Dodali ste prazno identiteto, ali res želite nadaljevati?Ali res želite izbrisati javni ključ \'%s\'?\nTega koraka ne boste mogli preklicati!Želite izvoziti tudi zasebne ključe?
-
- Uspešno dodan %d ključ
- Uspešno dodana %d ključa
- Uspešno dodani %d ključi
- Uspešno dodanih %d ključev
-
-
- in posodbljen %d.
- in posodobljena %d.
- in posodobljeni %d.
- in posodobljenih %d.
-
-
- Uspešno dodan %d ključ.
- Uspešno dodana %d ključa.
- Uspešno dodani %d ključi.
- Uspešno dodanih %d ključev.
-
-
- Uspešno posodobljen %d ključ.
- Uspešno posodobljena %d ključa.
- Uspešno posodobljeni %d ključi.
- Uspešno posodobljenih %d ključev.
-
- Noben ključ ni bil dodan ali posodobljen.Uspešno izvožen 1 ključ.Uspešno izvoženih ključev: %dNoben ključ ni bil izvožen.Pozor: ELGamal podpirajo samo podključi.Pozor: ključi RSA dolžine 1024 bitov ali manj ne veljajo več za varne, zato je njihovo ustvarjanje onemogočeno.Ne najdem ključa %08X.
-
- Najden %d ključ.
- Najdena %d ključa.
- Najdeni %d ključi.
- Najdeno %d ključev.
- Neupoštevan %d slab zasebni ključ. Morda je bil izvožen na način\n --export-secret-subkeys\nPoskrbite, da bo izvožen z\n --export-secret-keysNeupoštevana %d slaba zasebna ključa. Morda sta bila izvožena na način\n --export-secret-subkeys\nPoskrbite, da bosta izvožena z\n --export-secret-keys
@@ -290,8 +254,9 @@
Neposredni binarni podatki brez dejanske datoteke v datotečnem sistemu niso podprti.Za uporabo storitve NFC Beam potrebujete najmanj Android 4.1!NFC ni na voljo na vaši napravi!
- Ni česa uvoziti!
- Datoteka nima vsebine
+ Iskalni pojem je prekratek
+ Nepremostljiva napaka pri iskanju ključev na strežniku
+ Iskanje ključev je vrnilo preveč zadetkov; prosimo redefinirajte iskalni pojemPripetila se je splošna napaka, prosimo ustvarite poročilo o \'hrošču\'.Del naložene datoteke je veljavnen objekt OpenPGP a ni ključ.
@@ -299,7 +264,7 @@
Deli naložene datoteke so veljavni objekti OpenPGP a niso ključi.Deli naložene datoteke so veljavni objekti OpenPGP a niso ključi.
- V \'keyring\' morate vnesti spremembe, šele nato ga lahko shranite
+ V zbirko ključev morate najprej vnesti spremembe, šele nato jo lahko shraniteNeveljaven podpis!Neznan javni ključ
@@ -348,10 +313,8 @@
preverjam neokrnjenost...varno brišem \'%s\'…
- Iskanje javnih ključevIskanje zasebnih ključevDeli ključ z...
- Išči v Keybase.io512768
@@ -394,6 +357,7 @@
PomočPridobi ključ iz odložiščaPridobi ključ iz Keybase.io
+
Dešifriraj datoteko z OpenKeychainUvozi ključ z OpenKeychain
@@ -459,7 +423,6 @@
Podpiši in šifrirajDešifriraj in preveriUvozi ključe
- Prijavljene aplikacijeOdprite navigacijski poteznikZaprite navigacijski poteznikUredi
@@ -480,6 +443,27 @@
neuspešno!napaka!ključ ni na voljo
+
+ Uveljavljam serijsko dodajanje.
+ Poskus uvoza zasebne zbirke ključev kot javne. Prosimo prijavite dogodek kot \"hrošč\" (napako).
+ Noben star ključ ni bil izbrisan (ustvarim novega?)
+ Star ključ je bil izbrisan iz baze
+ Operacija ni uspela zaradi napake
+ Operacija ni uspela zaradi napake pri branju/pisanju
+ Operacija ni uspela zaradi notranje napake
+ Ponovno vnašam zasebni ključ
+ Naleteli ste na slab certifikat!
+ Napaka pri obdelavi certifikata!
+ Procesiram uporabniško identiteto %s
+ Poskus uvoza javne zbirke ključev kot zasebne. Prosimo prijavite dogodek kot \'hrošč\' (napako).
+
+ Procesiram zasebne podključe
+ Podključ %s ni na voljo v javnem ključu
+ %s označen kot razpoložljiv
+ %s označen kot slečen
+
+
+
OveroviteljPodrobnosti potrdil
@@ -498,5 +482,8 @@
Preglej podrobosti certifikataneznanne more podpisati
+ Napaka pri šifriranjuNi nobenega podključa za šifriranje!
+ Ne ustvari računov OpenKeychain ročno.\nZa več informacij poglej poglavje Pomoč.
+ Prikaži ključ (%s)
diff --git a/OpenKeychain/src/main/res/values-tr/strings.xml b/OpenKeychain/src/main/res/values-tr/strings.xml
index 1205095aa..bae2b55ad 100644
--- a/OpenKeychain/src/main/res/values-tr/strings.xml
+++ b/OpenKeychain/src/main/res/values-tr/strings.xml
@@ -32,15 +32,11 @@
AyarlarYardım
- Dosyadan al
- QR Kodundan al
- NFCden alDosyaya verAnahtar silAnahtar oluşturAnahtar oluştur (uzman)Ara
- Anahtar SunucusuPaylaş...QR Kod ileNFC ile
@@ -105,7 +101,6 @@
anahtar uzunluğu en az 512bit olmalıeposta bulunamadı
- Dosyanın içeriği boşGeçersiz imza!
@@ -148,6 +143,7 @@
Seçili anahtarları alYardım
+
Anahtar seçilmedi
@@ -179,6 +175,11 @@
başarısız!hata!anahtar mevcut değil
+
+
+
+
+
imzalanamadı
diff --git a/OpenKeychain/src/main/res/values-uk/strings.xml b/OpenKeychain/src/main/res/values-uk/strings.xml
index 2951d13f8..6f5cc7cf1 100644
--- a/OpenKeychain/src/main/res/values-uk/strings.xml
+++ b/OpenKeychain/src/main/res/values-uk/strings.xml
@@ -9,7 +9,6 @@
Створити ключРедагувати ключНалаштування
- Зареєстровані програмиНалаштування сервера ключівЗмінити парольну фразуЗадати парольну фразу
@@ -27,6 +26,7 @@
Сертифікувати сутностіПодробиці про ключДовідка
+ ЖурналСутностіПідключі
@@ -70,16 +70,11 @@
ПараметриДовідка
- Імпорт з файлу
- Імпорт з штрих-коду
- Імпорт з NFCЕкспорт до файлуВилучити ключСтворити ключСтворити ключ (експерт)Пошук
- Сервер ключів
- Імпорт із Keybase.ioСервер ключів…Оновити з сервера ключівЗавантажити на сервер ключів
@@ -98,6 +93,7 @@
Вибрати усеДодати ключіЕкспортувати усі ключі
+ Показати додаткову інформаціюПідписПовідомлення
@@ -209,38 +205,12 @@
Ви вже додали порожню сутність. Ви справді хочете продовжити?Ви справді хочете вилучити відкритий ключ \'%s\'?\nВи не зможете це відмінити!Також експортувати секретні ключі?
-
- Успішно додано %d ключ
- Успішно додано %d ключі
- Успішно додано %d ключів
-
-
- і оновлено %d ключ.
- і оновлено %d ключі.
- і оновлено %d ключів.
-
-
- Успішно додано %d ключ.
- Успішно додано %d ключі.
- Успішно додано %d ключів.
-
-
- Успішно оновлено %d ключ.
- Успішно оновлено %d ключі.
- Успішно оновлено %d ключів.
-
- Жодного ключа не додано та не оновлено.Успішно експортовано 1 ключ.Успішно експортовано %d ключів.Жодного ключа не експортовано.Примітка: лише підключі підтримують ElGamal.Примітка: генерація ключа RSA з довжиною 1024 біти і менше вважається небезпечною і вона вимкнена для генерації нових ключів.Не можливо знайти ключ %08X.
-
- Знайдено %d ключ.
- Знайдено %d ключі.
- Знайдено %d ключів.
- %d поганий секретний ключ проігнорований. Можливо ви експортували з параметром\n --export-secret-subkeys\nЗробіть ваш експорт з \n --export-secret-keys\nнатомість.%d погані секретні ключі проігноровані. Можливо ви експортували з параметром\n --export-secret-subkeys\nЗробіть ваш експорт з \n --export-secret-keys\nнатомість.
@@ -281,11 +251,10 @@
Пряма передача даних без використання файлу в пам\'яті пристрою не підтримується.Вам потрібний Android 4.1 для використання функції Androids NFC промінь!NFC недоступний на вашому пристрої!
- Нема що імпортувати!
+ Ключ не знайдено!Запит пошуку ключа надто короткийНевиправна помилка пошуку ключів в серверіЗапит пошуку ключа видав надто багато варіантів. Уточніть пошуковий запит
- Файл не має вмістуТрапилася загальна помилка, будь ласка, створіть новий звіт про помилку для OpenKeychain.частина завантаженого файлу є вірним об\'єктом OpenPGP, але не ключем OpenPGP
@@ -339,10 +308,8 @@
перевірка цілісності…вилучення безпечно \'%s\'…
- Пошук публічних ключівПошук секретних ключівПоділитися ключем з…
- Пошук Keybase.io512768
@@ -384,6 +351,10 @@
ДовідкаОтримати ключ з буфера обмінуОтримати ключ із Keybase.io
+
+ Переглянути журнал
+ Нема що імпортувати.
+ Помилка імпорту ключів!Розшифрувати файл з OpenKeychainІмпортувати ключ з OpenKeychain
@@ -448,7 +419,6 @@
Підписати і зашифруватиРозшифрувати і ПеревіритиІмпортувати ключі
- Зареєстровані програмиВідкрити панель навігаціїЗакрити панель навігаціїРедагувати
@@ -469,6 +439,26 @@
Невдача!Помилка!Недоступний ключ
+
+ Застосовується пакетна операція вставки.
+ Нема вилученого старого ключа (створюється новий?)
+ Вилучений старий ключ з бази даних
+ Операція не вдалася через помилку кодування
+ Операція не вдалася через помилку вводу/виводу
+ Операція не вдалася через внутрішню помилку
+ Підготовка операцій з базою даних
+ Опрацьовується підключ %s
+ Повторне вставлення секретного ключа
+ Виявлено поганий сертифікат!
+ Помилка опрацювання сертифікату!
+ Обробляється ІД користувача %s
+
+ Опрацьовуються секретні підключі
+ Підключ %s недоступний у публічному ключі
+ Позначено %s як доступно
+
+
+
Ким підписанийДані сертифікату
@@ -482,9 +472,13 @@
Ключ не знайдено!Помилка опрацювання ключа!підключ недоступний
+ голийСекретні ключі можна вилучити лише окремо!Переглянути дані сертифікатуневідомийне можна підписати
+ Помилка шифруванняЖодний підключ шифрування недоступний!
+ Вручну не створюються профілі OpenKeychain.\nЗа подробицями дивіться Довідку.
+ Показати ключ (%s)
diff --git a/OpenKeychain/src/main/res/values-zh/strings.xml b/OpenKeychain/src/main/res/values-zh/strings.xml
index 8dfb6b2ca..f661ca058 100644
--- a/OpenKeychain/src/main/res/values-zh/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh/strings.xml
@@ -9,7 +9,6 @@
创建密钥编辑密钥参数
- 已注册应用密钥服务器偏好设置密码短语加密至文件
@@ -134,6 +133,7 @@
从剪贴板导入二维码扫描完成!帮助
+
显示高级设置
@@ -156,5 +156,10 @@
导入密钥
+
+
+
+
+
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 9284e63e3..3c88dd0af 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -226,7 +226,6 @@
Successfully exported %d keys.No keys exported.Note: only subkeys support ElGamal.
- Note: generating RSA key with length 1024-bit and less is considered unsafe and it\'s disabled for generating new keys.Couldn\'t find key %08X.
@@ -419,7 +418,7 @@
Decrypt with OpenKeychain
- No registered applications!\n\nA list of supported third-party applications can be found in \'Help\'!
+ No registered apps!\n\nA list of supported third-party applications can be found in \'Help\'!Show advanced informationHide advanced informationShow advanced settings
@@ -435,9 +434,9 @@
Package NameSHA-256 of Package SignatureAccounts
- No accounts attached to this application.
- The application requests the creation of a new account. Please select an existing private key or create a new one.\nApplications are restricted to the usage of keys you select here!
- The displayed application requests access to OpenKeychain.\nAllow access?\n\nWARNING: If you do not know why this screen appeared, disallow access! You can revoke access later using the \'Registered Applications\' screen.
+ No accounts attached to this app.
+ The app requests the creation of a new account. Please select an existing private key or create a new one.\nApps are restricted to the usage of keys you select here!
+ The displayed app wants to encrypt/decrypt messages and sign them in your name.\nAllow access?\n\nWARNING: If you do not know why this screen appeared, disallow access! You can revoke access later using the \'Apps\' screen.Allow accessDisallow accessPlease select a key!
@@ -476,6 +475,16 @@
SubkeysCertificates
+
+ Change Passphrase
+ Add Identity
+ Add Subkey
+ Select an action!
+
+ Change to Primary Identity
+ Revoke Identity
+
+
KeysSign and Encrypt
@@ -550,8 +559,8 @@
Ignoring one certificate issued by an unknown public keyIgnoring %s certificates issued by unknown public keys
+ Classifying user ids (no trusted keys available)
- Classifying user ids (no trusted keys available)Classifying user ids (using one trusted key)Classifying user ids (using %s trusted keys)
@@ -630,13 +639,17 @@
Modifying keyring %sEncoding exception!
+ Actual key fingerprint does not match the expected one!
+ No key ID. This is an internal error, please file a bug report!
+ Internal error, integrity check failed!
+ Revoked user ids cannot be primary!PGP internal exception!Signature exception!Changing passphraseModifying subkey %sTried to operate on missing subkey %s!Generating new %1$s bit %2$s subkey
- New subkey id: %s
+ New subkey ID: %sExpiry date cannot be in the past!Revoking subkey %sKeyring successfully modified
diff --git a/OpenKeychain/src/test/java/tests/PgpDecryptVerifyTest.java b/OpenKeychain/src/test/java/tests/PgpDecryptVerifyTest.java
index 346a1f9df..d759bce05 100644
--- a/OpenKeychain/src/test/java/tests/PgpDecryptVerifyTest.java
+++ b/OpenKeychain/src/test/java/tests/PgpDecryptVerifyTest.java
@@ -22,7 +22,6 @@ public class PgpDecryptVerifyTest {
Assert.assertEquals(expectedSignatureResult, status);
}
-
@Test
public void testVerifyFailure() throws Exception {
diff --git a/Resources/gnupg-infographic/README b/Resources/gnupg-infographic/README
new file mode 100644
index 000000000..f29c0a84a
--- /dev/null
+++ b/Resources/gnupg-infographic/README
@@ -0,0 +1,13 @@
+Source files for GnuPG infographic
+==================================
+
+These are the source graphics for the Email Self-Defense infographic from the
+Free Software Foundation, available at .
+
+License
+-------
+
+Copyright (c) 2014 Free Software Foundation, Inc.
+
+Licensed under the Creative Commons Attribution license (CC-BY). See full
+source and attribution text at the above site.
diff --git a/Resources/gnupg-infographic/gnupg-infographic.png b/Resources/gnupg-infographic/gnupg-infographic.png
new file mode 100644
index 000000000..52b8f21ac
Binary files /dev/null and b/Resources/gnupg-infographic/gnupg-infographic.png differ
diff --git a/Resources/gnupg-infographic/gnupg-infographic.svg b/Resources/gnupg-infographic/gnupg-infographic.svg
new file mode 100644
index 000000000..9a17421e2
--- /dev/null
+++ b/Resources/gnupg-infographic/gnupg-infographic.svg
@@ -0,0 +1,8145 @@
+
+
+
+
diff --git a/extern/spongycastle b/extern/spongycastle
index 09d85b7d7..968405ee5 160000
--- a/extern/spongycastle
+++ b/extern/spongycastle
@@ -1 +1 @@
-Subproject commit 09d85b7d7a64b3003210d065c4210ff7fb7a8c6d
+Subproject commit 968405ee5d4272330cffdf75f7eee4cd9f5c8646