aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java40
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java237
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java338
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java60
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java190
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java88
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java38
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java16
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java70
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java82
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java34
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java2
18 files changed, 770 insertions, 480 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java
index d64587578..f04d84315 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/OtherHelper.java
@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.helper;
+import android.content.Context;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -67,4 +68,12 @@ public class OtherHelper {
return sb;
}
+ public static int dpToPx(Context context, int dp) {
+ return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5);
+ }
+
+ public static int pxToDp(Context context, int px) {
+ return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5);
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
index 3681d62d8..9b070175c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpImportExport.java
@@ -149,7 +149,8 @@ public class PgpImportExport {
SaveKeyringResult result;
if (key.isSecret()) {
- result = mProviderHelper.saveSecretKeyRing(key);
+ result = mProviderHelper.saveSecretKeyRing(key,
+ new ProgressScaler(mProgressable, position, (position+1)*progSteps, 100));
} else {
result = mProviderHelper.savePublicKeyRing(key,
new ProgressScaler(mProgressable, position, (position+1)*progSteps, 100));
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 bbdbfffd2..c590200ee 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -174,7 +174,7 @@ public class PgpKeyOperation {
} catch(InvalidAlgorithmParameterException e) {
throw new RuntimeException(e);
} catch(PGPException e) {
- throw new PgpGeneralMsgIdException(R.string.msg_mr_error_pgp, e);
+ throw new PgpGeneralMsgIdException(R.string.msg_mf_error_pgp, e);
}
}
@@ -203,7 +203,7 @@ public class PgpKeyOperation {
* 6. If requested, change passphrase
*/
- log.add(LogLevel.START, LogType.MSG_MR, indent);
+ log.add(LogLevel.START, LogType.MSG_MF, indent);
indent += 1;
updateProgress(R.string.progress_building_key, 0, 100);
@@ -213,14 +213,14 @@ public class PgpKeyOperation {
PGPSecretKey masterSecretKey = sKR.getSecretKey();
// 1. Unlock private key
- log.add(LogLevel.DEBUG, LogType.MSG_MR_UNLOCK, indent);
+ log.add(LogLevel.DEBUG, LogType.MSG_MF_UNLOCK, indent);
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_MR_UNLOCK_ERROR, indent+1);
+ log.add(LogLevel.ERROR, LogType.MSG_MF_UNLOCK_ERROR, indent+1);
return null;
}
}
@@ -237,7 +237,7 @@ public class PgpKeyOperation {
// 2a. Add certificates for new user ids
for (String userId : saveParcel.addUserIds) {
- log.add(LogLevel.INFO, LogType.MSG_MR_UID_ADD, indent);
+ log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent);
PGPSignature cert = generateUserIdSignature(masterPrivateKey,
masterPublicKey, userId, false);
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
@@ -245,7 +245,7 @@ public class PgpKeyOperation {
// 2b. Add revocations for revoked user ids
for (String userId : saveParcel.revokeUserIds) {
- log.add(LogLevel.INFO, LogType.MSG_MR_UID_REVOKE, indent);
+ log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent);
PGPSignature cert = generateRevocationSignature(masterPrivateKey,
masterPublicKey, userId);
modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert);
@@ -253,7 +253,7 @@ 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_MR_UID_PRIMARY, indent);
+ log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent);
// todo
}
@@ -267,18 +267,18 @@ public class PgpKeyOperation {
// 4a. For each subkey change, generate new subkey binding certificate
for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) {
- log.add(LogLevel.INFO, LogType.MSG_MR_SUBKEY_CHANGE,
+ log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE,
new String[]{PgpKeyHelper.convertKeyIdToHex(change.mKeyId)}, indent);
PGPSecretKey sKey = sKR.getSecretKey(change.mKeyId);
if (sKey == null) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_SUBKEY_MISSING,
+ log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING,
new String[]{PgpKeyHelper.convertKeyIdToHex(change.mKeyId)}, indent + 1);
return null;
}
PGPPublicKey pKey = sKey.getPublicKey();
if (change.mExpiry != null && new Date(change.mExpiry).before(new Date())) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_SUBKEY_PAST_EXPIRY,
+ log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_PAST_EXPIRY,
new String[]{PgpKeyHelper.convertKeyIdToHex(change.mKeyId)}, indent + 1);
return null;
}
@@ -292,11 +292,11 @@ public class PgpKeyOperation {
// 4b. For each subkey revocation, generate new subkey revocation certificate
for (long revocation : saveParcel.revokeSubKeys) {
- log.add(LogLevel.INFO, LogType.MSG_MR_SUBKEY_REVOKE,
+ log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_REVOKE,
new String[] { PgpKeyHelper.convertKeyIdToHex(revocation) }, indent);
PGPSecretKey sKey = sKR.getSecretKey(revocation);
if (sKey == null) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_SUBKEY_MISSING,
+ log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_MISSING,
new String[] { PgpKeyHelper.convertKeyIdToHex(revocation) }, indent+1);
return null;
}
@@ -314,13 +314,13 @@ public class PgpKeyOperation {
try {
if (add.mExpiry != null && new Date(add.mExpiry).before(new Date())) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_SUBKEY_PAST_EXPIRY, indent +1);
+ log.add(LogLevel.ERROR, LogType.MSG_MF_SUBKEY_PAST_EXPIRY, indent +1);
return null;
}
- log.add(LogLevel.INFO, LogType.MSG_MR_SUBKEY_NEW, indent);
+ log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent);
PGPSecretKey sKey = createKey(add.mAlgorithm, add.mKeysize, passphrase, false);
- log.add(LogLevel.DEBUG, LogType.MSG_MR_SUBKEY_NEW_ID,
+ log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID,
new String[] { PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID()) }, indent+1);
PGPPublicKey pKey = sKey.getPublicKey();
@@ -336,7 +336,7 @@ public class PgpKeyOperation {
// 6. If requested, change passphrase
if (saveParcel.newPassphrase != null) {
- log.add(LogLevel.INFO, LogType.MSG_MR_PASSPHRASE, indent);
+ log.add(LogLevel.INFO, LogType.MSG_MF_PASSPHRASE, indent);
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build()
.get(HashAlgorithmTags.SHA1);
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
@@ -352,17 +352,17 @@ public class PgpKeyOperation {
// This one must only be thrown by
} catch (IOException e) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_ERROR_ENCODE, indent+1);
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_ENCODE, indent+1);
return null;
} catch (PGPException e) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_ERROR_PGP, indent+1);
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_PGP, indent+1);
return null;
} catch (SignatureException e) {
- log.add(LogLevel.ERROR, LogType.MSG_MR_ERROR_SIG, indent+1);
+ log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_SIG, indent+1);
return null;
}
- log.add(LogLevel.OK, LogType.MSG_MR_SUCCESS, indent);
+ log.add(LogLevel.OK, LogType.MSG_MF_SUCCESS, indent);
return new UncachedKeyRing(sKR);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
index f22ea7697..e1ce62bdf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
@@ -27,10 +27,14 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.Vector;
/** Wrapper around PGPKeyRing class, to be constructed from bytes.
@@ -50,24 +54,27 @@ import java.util.Vector;
* @see org.sufficientlysecure.keychain.pgp.UncachedSecretKey
*
*/
+@SuppressWarnings("unchecked")
public class UncachedKeyRing {
final PGPKeyRing mRing;
final boolean mIsSecret;
+ final boolean mIsCanonicalized;
UncachedKeyRing(PGPKeyRing ring) {
mRing = ring;
mIsSecret = ring instanceof PGPSecretKeyRing;
+ mIsCanonicalized = false;
}
- public long getMasterKeyId() {
- return mRing.getPublicKey().getKeyID();
+ private UncachedKeyRing(PGPKeyRing ring, boolean canonicalized) {
+ mRing = ring;
+ mIsSecret = ring instanceof PGPSecretKeyRing;
+ mIsCanonicalized = canonicalized;
}
- /* TODO don't use this */
- @Deprecated
- public PGPKeyRing getRing() {
- return mRing;
+ public long getMasterKeyId() {
+ return mRing.getPublicKey().getKeyID();
}
public UncachedPublicKey getPublicKey() {
@@ -94,6 +101,10 @@ public class UncachedKeyRing {
return mIsSecret;
}
+ public boolean isCanonicalized() {
+ return mIsCanonicalized;
+ }
+
public byte[] getEncoded() throws IOException {
return mRing.getEncoded();
}
@@ -102,15 +113,6 @@ public class UncachedKeyRing {
return mRing.getPublicKey().getFingerprint();
}
- public static UncachedKeyRing decodePublicFromData(byte[] data)
- throws PgpGeneralException, IOException {
- UncachedKeyRing ring = decodeFromData(data);
- if(ring.isSecret()) {
- throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!");
- }
- return ring;
- }
-
public static UncachedKeyRing decodeFromData(byte[] data)
throws PgpGeneralException, IOException {
BufferedInputStream bufferedInput =
@@ -178,7 +180,7 @@ public class UncachedKeyRing {
return result;
}
- /** "Canonicalizes" a key, removing inconsistencies in the process. This operation can be
+ /** "Canonicalizes" a public key, removing inconsistencies in the process. This variant can be
* applied to public keyrings only.
*
* More specifically:
@@ -193,19 +195,18 @@ public class UncachedKeyRing {
* - certifications and certification revocations for user ids
* - If a subkey retains no valid subkey binding certificate, remove it
* - If a user id retains no valid self certificate, remove it
+ * - If the key is a secret key, remove all certificates by foreign keys
+ * - If no valid user id remains, log an error and return null
*
* This operation writes an OperationLog which can be used as part of a OperationResultParcel.
*
- * @return A canonicalized key
+ * @return A canonicalized key, or null on fatal error
*
*/
+ @SuppressWarnings("ConstantConditions")
public UncachedKeyRing canonicalize(OperationLog log, int indent) {
- if (isSecret()) {
- throw new RuntimeException("Tried to canonicalize non-secret keyring. " +
- "This is a programming error and should never happen!");
- }
- log.add(LogLevel.START, LogType.MSG_KC,
+ log.add(LogLevel.START, isSecret() ? LogType.MSG_KC_SECRET : LogType.MSG_KC_PUBLIC,
new String[]{PgpKeyHelper.convertKeyIdToHex(getMasterKeyId())}, indent);
indent += 1;
@@ -213,7 +214,7 @@ public class UncachedKeyRing {
int redundantCerts = 0, badCerts = 0;
- PGPPublicKeyRing ring = (PGPPublicKeyRing) mRing;
+ PGPKeyRing ring = mRing;
PGPPublicKey masterKey = mRing.getPublicKey();
final long masterKeyId = masterKey.getKeyID();
@@ -334,8 +335,15 @@ public class UncachedKeyRing {
continue;
}
- // If this is a foreign signature, never mind any further
+ // If this is a foreign signature, ...
if (certId != masterKeyId) {
+ // never mind any further for public keys, but remove them from secret ones
+ if (isSecret()) {
+ log.add(LogLevel.WARN, LogType.MSG_KC_UID_FOREIGN,
+ new String[] { PgpKeyHelper.convertKeyIdToHex(certId) }, indent);
+ modified = PGPPublicKey.removeCertification(modified, userId, zert);
+ badCerts += 1;
+ }
continue;
}
@@ -433,7 +441,7 @@ public class UncachedKeyRing {
}
// Replace modified key in the keyring
- ring = PGPPublicKeyRing.insertPublicKey(ring, modified);
+ ring = replacePublicKey(ring, modified);
indent -= 1;
}
@@ -578,7 +586,7 @@ public class UncachedKeyRing {
// it is not properly bound? error!
if (selfCert == null) {
- ring = PGPPublicKeyRing.removePublicKey(ring, modified);
+ ring = replacePublicKey(ring, modified);
log.add(LogLevel.ERROR, LogType.MSG_KC_SUB_NO_CERT,
new String[]{ PgpKeyHelper.convertKeyIdToHex(key.getKeyID()) }, indent);
@@ -593,7 +601,7 @@ public class UncachedKeyRing {
modified = PGPPublicKey.addCertification(modified, revocation);
}
// replace pubkey in keyring
- ring = PGPPublicKeyRing.insertPublicKey(ring, modified);
+ ring = replacePublicKey(ring, modified);
indent -= 1;
}
@@ -611,8 +619,181 @@ public class UncachedKeyRing {
log.add(LogLevel.OK, LogType.MSG_KC_SUCCESS, null, indent);
}
- return new UncachedKeyRing(ring);
+ return new UncachedKeyRing(ring, true);
+ }
+
+ /** This operation merges information from a different keyring, returning a combined
+ * UncachedKeyRing.
+ *
+ * The combined keyring contains the subkeys and user ids of both input keyrings, but it does
+ * not necessarily have the canonicalized property.
+ *
+ * @param other The UncachedKeyRing to merge. Must not be empty, and of the same masterKeyId
+ * @return A consolidated UncachedKeyRing with the data of both input keyrings. Same type as
+ * this object, or null on error.
+ *
+ */
+ public UncachedKeyRing merge(UncachedKeyRing other, OperationLog log, int indent) {
+
+ log.add(LogLevel.DEBUG, isSecret() ? LogType.MSG_MG_SECRET : LogType.MSG_MG_PUBLIC,
+ new String[]{ PgpKeyHelper.convertKeyIdToHex(getMasterKeyId()) }, indent);
+ indent += 1;
+
+ long masterKeyId = other.getMasterKeyId();
+
+ if (getMasterKeyId() != masterKeyId) {
+ log.add(LogLevel.ERROR, LogType.MSG_MG_HETEROGENEOUS, null, indent);
+ return null;
+ }
+
+ // remember which certs we already added. this is cheaper than semantic deduplication
+ Set<byte[]> certs = new TreeSet<byte[]>(new Comparator<byte[]>() {
+ public int compare(byte[] left, byte[] right) {
+ // check for length equality
+ if (left.length != right.length) {
+ return left.length - right.length;
+ }
+ // compare byte-by-byte
+ for (int i = 0; i < left.length && i < right.length; i++) {
+ if (left[i] != right[i]) {
+ return (left[i] & 0xff) - (right[i] & 0xff);
+ }
+ }
+ // ok they're the same
+ return 0;
+ }});
+
+ try {
+ PGPKeyRing result = mRing;
+ PGPKeyRing candidate = other.mRing;
+
+ // Pre-load all existing certificates
+ for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(result.getPublicKeys())) {
+ for (PGPSignature cert : new IterableIterator<PGPSignature>(key.getSignatures())) {
+ certs.add(cert.getEncoded());
+ }
+ }
+
+ // keep track of the number of new certs we add
+ int newCerts = 0;
+
+ for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(candidate.getPublicKeys())) {
+
+ final PGPPublicKey resultKey = result.getPublicKey(key.getKeyID());
+ if (resultKey == null) {
+ log.add(LogLevel.DEBUG, LogType.MSG_MG_NEW_SUBKEY, null, indent);
+ result = replacePublicKey(result, key);
+ continue;
+ }
+
+ // Modifiable version of the old key, which we merge stuff into (keep old for comparison)
+ PGPPublicKey modified = resultKey;
+
+ // Iterate certifications
+ for (PGPSignature cert : new IterableIterator<PGPSignature>(key.getSignatures())) {
+ int type = cert.getSignatureType();
+ // Disregard certifications on user ids, we will deal with those later
+ if (type == PGPSignature.NO_CERTIFICATION
+ || type == PGPSignature.DEFAULT_CERTIFICATION
+ || type == PGPSignature.CASUAL_CERTIFICATION
+ || type == PGPSignature.POSITIVE_CERTIFICATION
+ || type == PGPSignature.CERTIFICATION_REVOCATION) {
+ continue;
+ }
+
+ // Don't merge foreign stuff into secret keys
+ if (cert.getKeyID() != masterKeyId && isSecret()) {
+ continue;
+ }
+
+ byte[] encoded = cert.getEncoded();
+ // Known cert, skip it
+ if (certs.contains(encoded)) {
+ continue;
+ }
+ certs.add(encoded);
+ modified = PGPPublicKey.addCertification(modified, cert);
+ newCerts += 1;
+ }
+
+ // If this is a subkey, merge it in and stop here
+ if (!key.isMasterKey()) {
+ if (modified != resultKey) {
+ result = replacePublicKey(result, modified);
+ }
+ continue;
+ }
+
+ // Copy over all user id certificates
+ for (String userId : new IterableIterator<String>(key.getUserIDs())) {
+ for (PGPSignature cert : new IterableIterator<PGPSignature>(key.getSignaturesForID(userId))) {
+ // Don't merge foreign stuff into secret keys
+ if (cert.getKeyID() != masterKeyId && isSecret()) {
+ continue;
+ }
+ byte[] encoded = cert.getEncoded();
+ // Known cert, skip it
+ if (certs.contains(encoded)) {
+ continue;
+ }
+ newCerts += 1;
+ certs.add(encoded);
+ modified = PGPPublicKey.addCertification(modified, userId, cert);
+ }
+ }
+ // If anything changed, save the updated (sub)key
+ if (modified != resultKey) {
+ result = replacePublicKey(result, modified);
+ }
+
+ }
+
+ log.add(LogLevel.DEBUG, LogType.MSG_MG_FOUND_NEW,
+ new String[] { Integer.toString(newCerts) }, indent);
+
+ return new UncachedKeyRing(result);
+
+ } catch (IOException e) {
+ log.add(LogLevel.ERROR, LogType.MSG_MG_FATAL_ENCODE, null, indent);
+ return null;
+ }
+
+ }
+
+ public UncachedKeyRing extractPublicKeyRing() {
+ if(!isSecret()) {
+ throw new RuntimeException("Tried to extract public keyring from non-secret keyring. " +
+ "This is a programming error and should never happen!");
+ }
+
+ ArrayList<PGPPublicKey> keys = new ArrayList();
+ Iterator<PGPPublicKey> it = mRing.getPublicKeys();
+ while (it.hasNext()) {
+ keys.add(it.next());
+ }
+
+ return new UncachedKeyRing(new PGPPublicKeyRing(keys));
}
+ /** This method replaces a public key in a keyring.
+ *
+ * This method essentially wraps PGP*KeyRing.insertPublicKey, where the keyring may be of either
+ * the secret or public subclass.
+ *
+ * @return the resulting PGPKeyRing of the same type as the input
+ */
+ private static PGPKeyRing replacePublicKey(PGPKeyRing ring, PGPPublicKey key) {
+ if (ring instanceof PGPPublicKeyRing) {
+ return PGPPublicKeyRing.insertPublicKey((PGPPublicKeyRing) ring, key);
+ }
+ PGPSecretKeyRing secRing = (PGPSecretKeyRing) ring;
+ PGPSecretKey sKey = secRing.getSecretKey(key.getKeyID());
+ // TODO generate secret key with S2K dummy, if none exists! for now, just die.
+ if (sKey == null) {
+ throw new RuntimeException("dummy secret key generation not yet implemented");
+ }
+ sKey = PGPSecretKey.replacePublicKey(sKey, key);
+ return PGPSecretKeyRing.insertSecretKey(secRing, sKey);
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java
index 71d237c05..6f3068261 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedKeyRing.java
@@ -91,8 +91,18 @@ public abstract class WrappedKeyRing extends KeyRing {
getRing().encode(stream);
}
+ /** Returns an UncachedKeyRing which wraps the same data as this ring. This method should
+ * only be used */
+ public UncachedKeyRing getUncachedKeyRing() {
+ return new UncachedKeyRing(getRing());
+ }
+
abstract PGPKeyRing getRing();
abstract public IterableIterator<WrappedPublicKey> publicKeyIterator();
+ public UncachedKeyRing getUncached() {
+ return new UncachedKeyRing(getRing());
+ }
+
}
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 9591cf8bc..d7148f710 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java
@@ -154,8 +154,4 @@ public class WrappedSecretKeyRing extends WrappedKeyRing {
});
}
- public UncachedKeyRing getUncached() {
- return new UncachedKeyRing(mRing);
- }
-
}
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 8688ecb6c..955fb90ba 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -68,7 +69,7 @@ import java.util.Set;
* name, it is not only a helper but actually the main interface for all
* synchronous database operations.
*
- * Operations in this class write logs (TODO). These can be obtained from the
+ * Operations in this class write logs. These can be obtained from the
* OperationResultParcel return values directly, but are also accumulated over
* the lifetime of the executing ProviderHelper object unless the resetLog()
* method is called to start a new one specifically.
@@ -187,9 +188,9 @@ public class ProviderHelper {
KeyRings.PUBKEY_DATA
}, KeyRings.HAS_ANY_SECRET + " = 1", null, null);
- LongSparseArray<WrappedPublicKey> result =
- new LongSparseArray<WrappedPublicKey>(cursor.getCount());
try {
+ LongSparseArray<WrappedPublicKey> result = new LongSparseArray<WrappedPublicKey>();
+
if (cursor != null && cursor.moveToFirst()) do {
long masterKeyId = cursor.getLong(0);
boolean hasAnySecret = cursor.getInt(1) > 0;
@@ -200,13 +201,15 @@ public class ProviderHelper {
new WrappedPublicKeyRing(blob, hasAnySecret, verified).getSubkey());
}
} while (cursor.moveToNext());
+
+ return result;
+
} finally {
if (cursor != null) {
cursor.close();
}
}
- return result;
}
public CachedPublicKeyRing getCachedPublicKeyRing(Uri queryUri) {
@@ -260,60 +263,30 @@ public class ProviderHelper {
}
}
- public SaveKeyringResult savePublicKeyRing(UncachedKeyRing keyRing) {
- return savePublicKeyRing(keyRing, new Progressable() {
- @Override
- public void setProgress(String message, int current, int total) {
- return;
- }
-
- @Override
- public void setProgress(int resourceId, int current, int total) {
- return;
- }
-
- @Override
- public void setProgress(int current, int total) {
- return;
- }
- });
- }
- /**
- * Saves PGPPublicKeyRing with its keys and userIds in DB
+ /** Saves an UncachedKeyRing of the public variant into the db.
+ *
+ * This method will not delete all previous data for this masterKeyId from the database prior
+ * to inserting. All public data is effectively re-inserted, secret keyrings are left deleted
+ * and need to be saved externally to be preserved past the operation.
*/
@SuppressWarnings("unchecked")
- public SaveKeyringResult savePublicKeyRing(UncachedKeyRing keyRing, Progressable progress) {
+ private int internalSavePublicKeyRing(UncachedKeyRing keyRing,
+ Progressable progress, boolean selfCertsAreTrusted) {
if (keyRing.isSecret()) {
log(LogLevel.ERROR, LogType.MSG_IP_BAD_TYPE_SECRET);
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ return SaveKeyringResult.RESULT_ERROR;
+ }
+ if (!keyRing.isCanonicalized()) {
+ log(LogLevel.ERROR, LogType.MSG_IP_BAD_TYPE_SECRET);
+ return SaveKeyringResult.RESULT_ERROR;
}
// start with ok result
int result = SaveKeyringResult.SAVED_PUBLIC;
long masterKeyId = keyRing.getMasterKeyId();
- log(LogLevel.START, LogType.MSG_IP,
- new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) });
- mIndent += 1;
-
- // Canonicalize this key, to assert a number of assumptions made about it.
- keyRing = keyRing.canonicalize(mLog, mIndent);
- if (keyRing == null) {
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
- }
-
UncachedPublicKey masterKey = keyRing.getPublicKey();
- // IF there is a secret key, preserve it!
- UncachedKeyRing secretRing;
- try {
- secretRing = getWrappedSecretKeyRing(masterKeyId).getUncached();
- log(LogLevel.DEBUG, LogType.MSG_IP_PRESERVING_SECRET);
- progress.setProgress(LogType.MSG_IP_PRESERVING_SECRET.getMsgId(), 30, 100);
- } catch (NotFoundException e) {
- secretRing = null;
- }
-
ArrayList<ContentProviderOperation> operations;
try {
@@ -331,7 +304,7 @@ public class ProviderHelper {
values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
} catch (IOException e) {
log(LogLevel.ERROR, LogType.MSG_IP_ENCODE_FAIL);
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ return SaveKeyringResult.RESULT_ERROR;
}
Uri uri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId));
@@ -463,6 +436,7 @@ public class ProviderHelper {
item.isRevoked = true;
log(LogLevel.INFO, LogType.MSG_IP_UID_REVOKED);
}
+ continue;
}
@@ -500,7 +474,7 @@ public class ProviderHelper {
}
mIndent -= 1;
- progress.setProgress(LogType.MSG_IP_UID_REORDER.getMsgId(), 80, 100);
+ progress.setProgress(LogType.MSG_IP_UID_REORDER.getMsgId(), 65, 100);
log(LogLevel.DEBUG, LogType.MSG_IP_UID_REORDER);
// primary before regular before revoked (see UserIdItem.compareTo)
// this is a stable sort, so the order of keys is otherwise preserved.
@@ -511,7 +485,7 @@ public class ProviderHelper {
operations.add(buildUserIdOperations(masterKeyId, item, userIdRank));
if (item.selfCert != null) {
operations.add(buildCertOperations(masterKeyId, userIdRank, item.selfCert,
- secretRing != null ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF));
+ selfCertsAreTrusted ? Certs.VERIFIED_SECRET : Certs.VERIFIED_SELF));
}
// don't bother with trusted certs if the uid is revoked, anyways
if (item.isRevoked) {
@@ -529,7 +503,7 @@ public class ProviderHelper {
log(LogLevel.ERROR, LogType.MSG_IP_FAIL_IO_EXC);
Log.e(Constants.TAG, "IOException during import", e);
mIndent -= 1;
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ return SaveKeyringResult.RESULT_ERROR;
}
try {
@@ -544,33 +518,24 @@ public class ProviderHelper {
}
log(LogLevel.DEBUG, LogType.MSG_IP_APPLY_BATCH);
- progress.setProgress(LogType.MSG_IP_APPLY_BATCH.getMsgId(), 90, 100);
+ progress.setProgress(LogType.MSG_IP_APPLY_BATCH.getMsgId(), 75, 100);
mContentResolver.applyBatch(KeychainContract.CONTENT_AUTHORITY, operations);
- // Save the saved keyring (if any)
- if (secretRing != null) {
- log(LogLevel.DEBUG, LogType.MSG_IP_REINSERT_SECRET);
- mIndent += 1;
- saveSecretKeyRing(secretRing);
- result |= SaveKeyringResult.SAVED_SECRET;
- mIndent -= 1;
- }
-
- mIndent -= 1;
log(LogLevel.OK, LogType.MSG_IP_SUCCESS);
- progress.setProgress(LogType.MSG_IP_SUCCESS.getMsgId(), 100, 100);
- return new SaveKeyringResult(result, mLog);
+ mIndent -= 1;
+ progress.setProgress(LogType.MSG_IP_SUCCESS.getMsgId(), 90, 100);
+ return result;
} catch (RemoteException e) {
log(LogLevel.ERROR, LogType.MSG_IP_FAIL_REMOTE_EX);
Log.e(Constants.TAG, "RemoteException during import", e);
mIndent -= 1;
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ return SaveKeyringResult.RESULT_ERROR;
} catch (OperationApplicationException e) {
- log(LogLevel.ERROR, LogType.MSG_IP_FAIL_OP_EX);
+ log(LogLevel.ERROR, LogType.MSG_IP_FAIL_OP_EXC);
Log.e(Constants.TAG, "OperationApplicationException during import", e);
mIndent -= 1;
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ return SaveKeyringResult.RESULT_ERROR;
}
}
@@ -596,17 +561,19 @@ public class ProviderHelper {
}
}
- /**
- * Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring
- * is already in the database!
- *
- * TODO allow adding secret keys where no public key exists (ie, consolidate keys)
+ /** Saves an UncachedKeyRing of the secret variant into the db.
+ * This method will fail if no corresponding public keyring is in the database!
*/
- public SaveKeyringResult saveSecretKeyRing(UncachedKeyRing keyRing) {
+ private int internalSaveSecretKeyRing(UncachedKeyRing keyRing) {
if (!keyRing.isSecret()) {
log(LogLevel.ERROR, LogType.MSG_IS_BAD_TYPE_PUBLIC);
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ return SaveKeyringResult.RESULT_ERROR;
+ }
+
+ if (!keyRing.isCanonicalized()) {
+ log(LogLevel.ERROR, LogType.MSG_IS_BAD_TYPE_PUBLIC);
+ return SaveKeyringResult.RESULT_ERROR;
}
long masterKeyId = keyRing.getMasterKeyId();
@@ -614,6 +581,12 @@ public class ProviderHelper {
new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) });
mIndent += 1;
+ // Canonicalize this key, to assert a number of assumptions made about it.
+ keyRing = keyRing.canonicalize(mLog, mIndent);
+ if (keyRing == null) {
+ return SaveKeyringResult.RESULT_ERROR;
+ }
+
// IF this is successful, it's a secret key
int result = SaveKeyringResult.SAVED_SECRET;
@@ -624,11 +597,14 @@ public class ProviderHelper {
values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded());
// insert new version of this keyRing
Uri uri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
- mContentResolver.insert(uri, values);
+ if (mContentResolver.insert(uri, values) == null) {
+ log(LogLevel.ERROR, LogType.MSG_IS_DB_EXCEPTION);
+ return SaveKeyringResult.RESULT_ERROR;
+ }
} catch (IOException e) {
Log.e(Constants.TAG, "Failed to encode key!", e);
- log(LogLevel.ERROR, LogType.MSG_IS_IO_EXCPTION);
- return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ log(LogLevel.ERROR, LogType.MSG_IS_FAIL_IO_EXC);
+ return SaveKeyringResult.RESULT_ERROR;
}
{
@@ -672,22 +648,219 @@ public class ProviderHelper {
}
log(LogLevel.OK, LogType.MSG_IS_SUCCESS);
- return new SaveKeyringResult(result, mLog);
+ return result;
+
+ }
+
+
+ @Deprecated
+ public SaveKeyringResult savePublicKeyRing(UncachedKeyRing keyRing) {
+ return savePublicKeyRing(keyRing, new Progressable() {
+ @Override
+ public void setProgress(String message, int current, int total) {
+ }
+
+ @Override
+ public void setProgress(int resourceId, int current, int total) {
+ }
+
+ @Override
+ public void setProgress(int current, int total) {
+ }
+ });
+ }
+
+ /** Save a public keyring into the database.
+ *
+ * This is a high level method, which takes care of merging all new information into the old and
+ * keep public and secret keyrings in sync.
+ */
+ public SaveKeyringResult savePublicKeyRing(UncachedKeyRing publicRing, Progressable progress) {
+
+ try {
+ long masterKeyId = publicRing.getMasterKeyId();
+ log(LogLevel.START, LogType.MSG_IP,
+ new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) });
+ mIndent += 1;
+
+ // If there is an old keyring, merge it
+ try {
+ UncachedKeyRing oldPublicRing = getWrappedPublicKeyRing(masterKeyId).getUncached();
+
+ // Merge data from new public ring into the old one
+ publicRing = oldPublicRing.merge(publicRing, mLog, mIndent);
+
+ // If this is null, there is an error in the log so we can just return
+ if (publicRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ // Canonicalize this keyring, to assert a number of assumptions made about it.
+ publicRing = publicRing.canonicalize(mLog, mIndent);
+ if (publicRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ // Early breakout if nothing changed
+ if (Arrays.hashCode(publicRing.getEncoded())
+ == Arrays.hashCode(oldPublicRing.getEncoded())) {
+ log(LogLevel.OK, LogType.MSG_IP_SUCCESS_IDENTICAL, null);
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_OK, mLog);
+ }
+ } catch (NotFoundException e) {
+ // Not an issue, just means we are dealing with a new keyring.
+
+ // Canonicalize this keyring, to assert a number of assumptions made about it.
+ publicRing = publicRing.canonicalize(mLog, mIndent);
+ if (publicRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ }
+
+ // If there is a secret key, merge new data (if any) and save the key for later
+ UncachedKeyRing secretRing;
+ try {
+ secretRing = getWrappedSecretKeyRing(publicRing.getMasterKeyId()).getUncached();
+
+ // Merge data from new public ring into secret one
+ secretRing = secretRing.merge(publicRing, mLog, mIndent);
+ if (secretRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+ secretRing = secretRing.canonicalize(mLog, mIndent);
+ if (secretRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ } catch (NotFoundException e) {
+ // No secret key available (this is what happens most of the time)
+ secretRing = null;
+ }
+
+ int result = internalSavePublicKeyRing(publicRing, progress, secretRing != null);
+
+ // Save the saved keyring (if any)
+ if (secretRing != null) {
+ progress.setProgress(LogType.MSG_IP_REINSERT_SECRET.getMsgId(), 90, 100);
+ int secretResult = internalSaveSecretKeyRing(secretRing);
+ if ((secretResult & SaveKeyringResult.RESULT_ERROR) != SaveKeyringResult.RESULT_ERROR) {
+ result |= SaveKeyringResult.SAVED_SECRET;
+ }
+ }
+
+ mIndent -= 1;
+ return new SaveKeyringResult(result, mLog);
+
+ } catch (IOException e) {
+ log(LogLevel.ERROR, LogType.MSG_IP_FAIL_IO_EXC);
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ }
+
+ public SaveKeyringResult saveSecretKeyRing(UncachedKeyRing secretRing, Progressable progress) {
+
+ try {
+ long masterKeyId = secretRing.getMasterKeyId();
+ log(LogLevel.START, LogType.MSG_IS,
+ new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) });
+ mIndent += 1;
+
+ // If there is an old secret key, merge it.
+ try {
+ UncachedKeyRing oldSecretRing = getWrappedSecretKeyRing(masterKeyId).getUncached();
+
+ // Merge data from new secret ring into old one
+ secretRing = oldSecretRing.merge(secretRing, mLog, mIndent);
+
+ // If this is null, there is an error in the log so we can just return
+ if (secretRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ // Canonicalize this keyring, to assert a number of assumptions made about it.
+ secretRing = secretRing.canonicalize(mLog, mIndent);
+ if (secretRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ // Early breakout if nothing changed
+ if (Arrays.hashCode(secretRing.getEncoded())
+ == Arrays.hashCode(oldSecretRing.getEncoded())) {
+ log(LogLevel.OK, LogType.MSG_IS_SUCCESS_IDENTICAL,
+ new String[]{ PgpKeyHelper.convertKeyIdToHex(masterKeyId) });
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_OK, mLog);
+ }
+ } catch (NotFoundException e) {
+ // Not an issue, just means we are dealing with a new keyring
+
+ // Canonicalize this keyring, to assert a number of assumptions made about it.
+ secretRing = secretRing.canonicalize(mLog, mIndent);
+ if (secretRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ }
+
+ // Merge new data into public keyring as well, if there is any
+ UncachedKeyRing publicRing;
+ try {
+ UncachedKeyRing oldPublicRing = getWrappedPublicKeyRing(masterKeyId).getUncached();
+
+ // Merge data from new public ring into secret one
+ publicRing = oldPublicRing.merge(secretRing, mLog, mIndent);
+ if (publicRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ // If nothing changed, never mind
+ if (Arrays.hashCode(publicRing.getEncoded())
+ == Arrays.hashCode(oldPublicRing.getEncoded())) {
+ publicRing = null;
+ }
+
+ } catch (NotFoundException e) {
+ log(LogLevel.DEBUG, LogType.MSG_IS_PUBRING_GENERATE, null);
+ publicRing = secretRing.extractPublicKeyRing();
+ }
+
+ if (publicRing != null) {
+ publicRing = publicRing.canonicalize(mLog, mIndent);
+ if (publicRing == null) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+
+ int result = internalSavePublicKeyRing(publicRing, progress, true);
+ if ((result & SaveKeyringResult.RESULT_ERROR) == SaveKeyringResult.RESULT_ERROR) {
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
+ }
+
+ progress.setProgress(LogType.MSG_IP_REINSERT_SECRET.getMsgId(), 90, 100);
+ int result = internalSaveSecretKeyRing(secretRing);
+ return new SaveKeyringResult(result, mLog);
+
+ } catch (IOException e) {
+ log(LogLevel.ERROR, LogType.MSG_IS_FAIL_IO_EXC, null);
+ return new SaveKeyringResult(SaveKeyringResult.RESULT_ERROR, mLog);
+ }
}
/**
* Saves (or updates) a pair of public and secret KeyRings in the database
*/
- public void saveKeyRing(UncachedKeyRing pubRing, UncachedKeyRing secRing) throws IOException {
- long masterKeyId = pubRing.getPublicKey().getKeyId();
+ @Deprecated // scheduled for deletion after merge with new-edit branch
+ public void savePairedKeyRing(UncachedKeyRing pubRing, UncachedKeyRing secRing) throws IOException {
+ long masterKeyId = pubRing.getMasterKeyId();
// delete secret keyring (so it isn't unnecessarily saved by public-savePublicKeyRing below)
mContentResolver.delete(KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)), null, null);
// save public keyring
- savePublicKeyRing(pubRing);
- saveSecretKeyRing(secRing);
+ internalSavePublicKeyRing(pubRing, null, true);
+ internalSaveSecretKeyRing(secRing);
}
/**
@@ -803,9 +976,6 @@ public class ProviderHelper {
/**
* Must be an uri pointing to an account
- *
- * @param uri
- * @return
*/
public AppSettings getApiAppSettings(Uri uri) {
AppSettings settings = null;
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 73f552c92..6e49baf92 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
@@ -3,8 +3,10 @@ package org.sufficientlysecure.keychain.service;
import android.os.Parcel;
import android.os.Parcelable;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.IterableIterator;
+import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
@@ -129,12 +131,11 @@ public class OperationResultParcel implements Parcelable {
MSG_IP_DELETE_OLD_OK (R.string.msg_ip_delete_old_ok),
MSG_IP_ENCODE_FAIL (R.string.msg_ip_encode_fail),
MSG_IP_FAIL_IO_EXC (R.string.msg_ip_fail_io_exc),
- MSG_IP_FAIL_OP_EX (R.string.msg_ip_fail_op_ex),
+ MSG_IP_FAIL_OP_EXC (R.string.msg_ip_fail_op_exc),
MSG_IP_FAIL_REMOTE_EX (R.string.msg_ip_fail_remote_ex),
MSG_IP_INSERT_KEYRING (R.string.msg_ip_insert_keyring),
MSG_IP_INSERT_SUBKEYS (R.string.msg_ip_insert_keys),
MSG_IP_PREPARE (R.string.msg_ip_prepare),
- MSG_IP_PRESERVING_SECRET (R.string.msg_ip_preserving_secret),
MSG_IP_REINSERT_SECRET (R.string.msg_ip_reinsert_secret),
MSG_IP_MASTER (R.string.msg_ip_master),
MSG_IP_MASTER_EXPIRED (R.string.msg_ip_master_expired),
@@ -159,6 +160,7 @@ public class OperationResultParcel implements Parcelable {
MSG_IP_SUBKEY_FLAGS_XXS (R.string.msg_ip_subkey_flags_xxs),
MSG_IP_SUBKEY_FLAGS_XXX (R.string.msg_ip_subkey_flags_xxx),
MSG_IP_SUCCESS (R.string.msg_ip_success),
+ MSG_IP_SUCCESS_IDENTICAL (R.string.msg_ip_success_identical),
MSG_IP_UID_CERT_BAD (R.string.msg_ip_uid_cert_bad),
MSG_IP_UID_CERT_ERROR (R.string.msg_ip_uid_cert_error),
MSG_IP_UID_CERT_GOOD (R.string.msg_ip_uid_cert_good),
@@ -171,15 +173,19 @@ public class OperationResultParcel implements Parcelable {
// import secret
MSG_IS(R.string.msg_is),
MSG_IS_BAD_TYPE_PUBLIC (R.string.msg_is_bad_type_public),
+ MSG_IS_DB_EXCEPTION (R.string.msg_is_db_exception),
+ MSG_IS_FAIL_IO_EXC (R.string.msg_is_io_exc),
MSG_IS_IMPORTING_SUBKEYS (R.string.msg_is_importing_subkeys),
- MSG_IS_IO_EXCPTION (R.string.msg_is_io_excption),
+ MSG_IS_PUBRING_GENERATE (R.string.msg_is_pubring_generate),
MSG_IS_SUBKEY_NONEXISTENT (R.string.msg_is_subkey_nonexistent),
MSG_IS_SUBKEY_OK (R.string.msg_is_subkey_ok),
MSG_IS_SUBKEY_STRIPPED (R.string.msg_is_subkey_stripped),
+ MSG_IS_SUCCESS_IDENTICAL (R.string.msg_is_success_identical),
MSG_IS_SUCCESS (R.string.msg_is_success),
// keyring canonicalization
- MSG_KC (R.string.msg_kc),
+ MSG_KC_PUBLIC (R.string.msg_kc_public),
+ MSG_KC_SECRET (R.string.msg_kc_secret),
MSG_KC_FATAL_NO_UID (R.string.msg_kc_fatal_no_uid),
MSG_KC_MASTER (R.string.msg_kc_master),
MSG_KC_REVOKE_BAD_ERR (R.string.msg_kc_revoke_bad_err),
@@ -212,27 +218,38 @@ public class OperationResultParcel implements Parcelable {
MSG_KC_UID_BAD_TYPE (R.string.msg_kc_uid_bad_type),
MSG_KC_UID_BAD (R.string.msg_kc_uid_bad),
MSG_KC_UID_DUP (R.string.msg_kc_uid_dup),
+ MSG_KC_UID_FOREIGN (R.string.msg_kc_uid_foreign),
MSG_KC_UID_NO_CERT (R.string.msg_kc_uid_no_cert),
MSG_KC_UID_REVOKE_DUP (R.string.msg_kc_uid_revoke_dup),
MSG_KC_UID_REVOKE_OLD (R.string.msg_kc_uid_revoke_old),
- MSG_MR (R.string.msg_mr),
- MSG_MR_ERROR_ENCODE (R.string.msg_mr_error_encode),
- MSG_MR_ERROR_PGP (R.string.msg_mr_error_pgp),
- MSG_MR_ERROR_SIG (R.string.msg_mr_error_sig),
- MSG_MR_PASSPHRASE (R.string.msg_mr_passphrase),
- MSG_MR_SUBKEY_CHANGE (R.string.msg_mr_subkey_change),
- MSG_MR_SUBKEY_MISSING (R.string.msg_mr_subkey_missing),
- MSG_MR_SUBKEY_NEW_ID (R.string.msg_mr_subkey_new_id),
- MSG_MR_SUBKEY_NEW (R.string.msg_mr_subkey_new),
- MSG_MR_SUBKEY_PAST_EXPIRY (R.string.msg_mr_subkey_past_expiry),
- MSG_MR_SUBKEY_REVOKE (R.string.msg_mr_subkey_revoke),
- MSG_MR_SUCCESS (R.string.msg_mr_success),
- MSG_MR_UID_ADD (R.string.msg_mr_uid_add),
- MSG_MR_UID_PRIMARY (R.string.msg_mr_uid_primary),
- MSG_MR_UID_REVOKE (R.string.msg_mr_uid_revoke),
- MSG_MR_UNLOCK_ERROR (R.string.msg_mr_unlock_error),
- MSG_MR_UNLOCK (R.string.msg_mr_unlock),
+
+ // keyring consolidation
+ MSG_MG_PUBLIC (R.string.msg_mg_public),
+ MSG_MG_SECRET (R.string.msg_mg_secret),
+ MSG_MG_FATAL_ENCODE (R.string.msg_mg_fatal_encode),
+ MSG_MG_HETEROGENEOUS (R.string.msg_mg_heterogeneous),
+ MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey),
+ MSG_MG_FOUND_NEW (R.string.msg_mg_found_new),
+
+ // secret key modify
+ MSG_MF (R.string.msg_mr),
+ MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode),
+ 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),
+ MSG_MF_SUBKEY_CHANGE (R.string.msg_mf_subkey_change),
+ MSG_MF_SUBKEY_MISSING (R.string.msg_mf_subkey_missing),
+ MSG_MF_SUBKEY_NEW_ID (R.string.msg_mf_subkey_new_id),
+ MSG_MF_SUBKEY_NEW (R.string.msg_mf_subkey_new),
+ MSG_MF_SUBKEY_PAST_EXPIRY (R.string.msg_mf_subkey_past_expiry),
+ MSG_MF_SUBKEY_REVOKE (R.string.msg_mf_subkey_revoke),
+ MSG_MF_SUCCESS (R.string.msg_mf_success),
+ MSG_MF_UID_ADD (R.string.msg_mf_uid_add),
+ MSG_MF_UID_PRIMARY (R.string.msg_mf_uid_primary),
+ MSG_MF_UID_REVOKE (R.string.msg_mf_uid_revoke),
+ MSG_MF_UNLOCK_ERROR (R.string.msg_mf_unlock_error),
+ MSG_MF_UNLOCK (R.string.msg_mf_unlock),
;
private final int mMsgId;
@@ -279,6 +296,7 @@ public class OperationResultParcel implements Parcelable {
/// Simple convenience method
public void add(LogLevel level, LogType type, String[] parameters, int indent) {
+ Log.d(Constants.TAG, type.toString());
add(new OperationResultParcel.LogEntryParcel(level, type, parameters, indent));
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index f389726ff..54186e380 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -32,10 +32,14 @@ import android.os.Messenger;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
+import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.github.johnpersano.supertoasts.SuperCardToast;
@@ -45,18 +49,22 @@ import com.github.johnpersano.supertoasts.util.Style;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
+import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.OperationResults.ImportResult;
+import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
+import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
import java.util.Locale;
-public class ImportKeysActivity extends ActionBarActivity implements ActionBar.OnNavigationListener {
+public class ImportKeysActivity extends ActionBarActivity {
public static final String ACTION_IMPORT_KEY = Constants.INTENT_PREFIX + "IMPORT_KEY";
public static final String ACTION_IMPORT_KEY_FROM_QR_CODE = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_QR_CODE";
@@ -90,23 +98,18 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
private String[] mNavigationStrings;
private Fragment mCurrentFragment;
private View mImportButton;
+ private ViewPager mViewPager;
+ private SlidingTabLayout mSlidingTabLayout;
+ private PagerTabStripAdapter mTabsAdapter;
+
+ public static final int VIEW_PAGER_HEIGHT = 64; // dp
- private static final Class[] NAVIGATION_CLASSES = new Class[]{
- ImportKeysServerFragment.class,
- ImportKeysFileFragment.class,
- ImportKeysQrCodeFragment.class,
- ImportKeysClipboardFragment.class,
- ImportKeysNFCFragment.class,
- ImportKeysKeybaseFragment.class
- };
private static final int NAV_SERVER = 0;
- private static final int NAV_FILE = 1;
- private static final int NAV_QR_CODE = 2;
- private static final int NAV_CLIPBOARD = 3;
- private static final int NAV_NFC = 4;
- private static final int NAV_KEYBASE = 5;
+ private static final int NAV_QR_CODE = 1;
+ private static final int NAV_FILE = 2;
+ private static final int NAV_KEYBASE = 3;
- private int mCurrentNavPosition = -1;
+ private int mSwitchToTab = NAV_SERVER;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -114,6 +117,9 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
setContentView(R.layout.import_keys_activity);
+ mViewPager = (ViewPager) findViewById(R.id.import_pager);
+ mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.import_sliding_tab_layout);
+
mImportButton = findViewById(R.id.import_import);
mImportButton.setOnClickListener(new OnClickListener() {
@Override
@@ -127,18 +133,55 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) {
setTitle(R.string.nav_import);
} else {
- getSupportActionBar().setDisplayShowTitleEnabled(false);
-
- // set drop down navigation
- Context context = getSupportActionBar().getThemedContext();
- ArrayAdapter<CharSequence> navigationAdapter = ArrayAdapter.createFromResource(context,
- R.array.import_action_list, android.R.layout.simple_spinner_dropdown_item);
- getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- getSupportActionBar().setListNavigationCallbacks(navigationAdapter, this);
+ initTabs();
}
handleActions(savedInstanceState, getIntent());
+ }
+
+ private void initTabs() {
+ mTabsAdapter = new PagerTabStripAdapter(this);
+ mViewPager.setAdapter(mTabsAdapter);
+ mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ // resize view pager back to 64 if keyserver settings have been collapsed
+ if (getViewPagerHeight() > VIEW_PAGER_HEIGHT) {
+ resizeViewPager(VIEW_PAGER_HEIGHT);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+ });
+
+ Bundle serverBundle = new Bundle();
+// serverBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ImportKeysServerFragment.class,
+ serverBundle, getString(R.string.import_tab_keyserver));
+
+ Bundle qrCodeBundle = new Bundle();
+// importBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ImportKeysQrCodeFragment.class,
+ qrCodeBundle, getString(R.string.import_tab_qr_code));
+
+ Bundle fileBundle = new Bundle();
+// importBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ImportKeysFileFragment.class,
+ fileBundle, getString(R.string.import_tab_direct));
+ Bundle keybaseBundle = new Bundle();
+// keybaseBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
+ mTabsAdapter.addTab(ImportKeysKeybaseFragment.class,
+ keybaseBundle, getString(R.string.import_tab_keybase));
+
+ // update layout after operations
+ mSlidingTabLayout.setViewPager(mViewPager);
}
protected void handleActions(Bundle savedInstanceState, Intent intent) {
@@ -164,7 +207,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
/* Keychain's own Actions */
// display file fragment
- loadNavFragment(NAV_FILE, null);
+ mViewPager.setCurrentItem(NAV_FILE);
if (dataUri != null) {
// action: directly load data
@@ -199,7 +242,9 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
// display keyserver fragment with query
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
- loadNavFragment(NAV_SERVER, args);
+// loadNavFragment(NAV_SERVER, args);
+ //TODO: load afterwards!
+ mSwitchToTab = NAV_SERVER;
// action: search immediately
startListFragment(savedInstanceState, null, null, query);
@@ -223,9 +268,8 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
return;
}
} else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) {
-
// NOTE: this only displays the appropriate fragment, no actions are taken
- loadNavFragment(NAV_FILE, null);
+ mSwitchToTab = NAV_FILE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
@@ -233,26 +277,28 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
// also exposed in AndroidManifest
// NOTE: this only displays the appropriate fragment, no actions are taken
- loadNavFragment(NAV_QR_CODE, null);
+ mSwitchToTab = NAV_QR_CODE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
} else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) {
// NOTE: this only displays the appropriate fragment, no actions are taken
- loadNavFragment(NAV_NFC, null);
+ mSwitchToTab = NAV_QR_CODE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
} else if (ACTION_IMPORT_KEY_FROM_KEYBASE.equals(action)) {
// NOTE: this only displays the appropriate fragment, no actions are taken
- loadNavFragment(NAV_KEYBASE, null);
+ mSwitchToTab = NAV_KEYBASE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
} else {
startListFragment(savedInstanceState, null, null, null);
}
+
+ mViewPager.setCurrentItem(mSwitchToTab);
}
private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri, String serverQuery) {
@@ -275,54 +321,16 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
getSupportFragmentManager().executePendingTransactions();
}
- /**
- * "Basically, when using a list navigation, onNavigationItemSelected() is automatically
- * called when your activity is created/re-created, whether you like it or not. To prevent
- * your Fragment's onCreateView() from being called twice, this initial automatic call to
- * onNavigationItemSelected() should check whether the Fragment is already in existence
- * inside your Activity."
- * <p/>
- * from http://stackoverflow.com/a/14295474
- * <p/>
- * In our case, if we start ImportKeysActivity with parameters to directly search using a fingerprint,
- * the fragment would be loaded twice resulting in the query being empty after the second load.
- * <p/>
- * Our solution:
- * To prevent that a fragment will be loaded again even if it was already loaded loadNavFragment
- * checks against mCurrentNavPosition.
- *
- * @param itemPosition
- * @param itemId
- * @return
- */
- @Override
- public boolean onNavigationItemSelected(int itemPosition, long itemId) {
- Log.d(Constants.TAG, "onNavigationItemSelected");
-
- loadNavFragment(itemPosition, null);
-
- return true;
- }
-
- private void loadNavFragment(int itemPosition, Bundle args) {
- if (mCurrentNavPosition != itemPosition) {
- if (ActionBar.NAVIGATION_MODE_LIST == getSupportActionBar().getNavigationMode()) {
- getSupportActionBar().setSelectedNavigationItem(itemPosition);
- }
- loadFragment(NAVIGATION_CLASSES[itemPosition], args, mNavigationStrings[itemPosition]);
- mCurrentNavPosition = itemPosition;
- }
+ public void resizeViewPager(int dp) {
+ ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
+ params.height = OtherHelper.dpToPx(this, dp);
+ // update layout after operations
+ mSlidingTabLayout.setViewPager(mViewPager);
}
- private void loadFragment(Class<?> clss, Bundle args, String tag) {
- mCurrentFragment = Fragment.instantiate(this, clss.getName(), args);
-
- FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
- // Replace whatever is in the fragment container with this fragment
- // and give the fragment a tag name equal to the string at the position selected
- ft.replace(R.id.import_navigation_fragment, mCurrentFragment, tag);
- // Apply changes
- ft.commit();
+ public int getViewPagerHeight() {
+ ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
+ return OtherHelper.pxToDp(this, params.height);
}
public void loadFromFingerprintUri(Bundle savedInstanceState, Uri dataUri) {
@@ -349,7 +357,9 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
args.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true);
- loadNavFragment(NAV_SERVER, args);
+// loadNavFragment(NAV_SERVER, args);
+
+ //TODO
// action: search directly
startListFragment(savedInstanceState, null, null, query);
@@ -437,15 +447,16 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
toast.setButtonTextColor(getResources().getColor(R.color.black));
toast.setTextColor(getResources().getColor(R.color.black));
toast.setOnClickWrapper(new OnClickWrapper("supercardtoast",
- new SuperToast.OnClickListener() {
- @Override
- public void onClick(View view, Parcelable token) {
- Intent intent = new Intent(
- ImportKeysActivity.this, LogDisplayActivity.class);
- intent.putExtra(LogDisplayFragment.EXTRA_RESULT, result);
- startActivity(intent);
+ new SuperToast.OnClickListener() {
+ @Override
+ public void onClick(View view, Parcelable token) {
+ Intent intent = new Intent(
+ ImportKeysActivity.this, LogDisplayActivity.class);
+ intent.putExtra(LogDisplayFragment.EXTRA_RESULT, result);
+ startActivity(intent);
+ }
}
- }));
+ ));
toast.show();
/*
@@ -560,9 +571,12 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
super.onResume();
// Check to see if the Activity started due to an Android Beam
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
- && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
- handleActionNdefDiscovered(getIntent());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
+ handleActionNdefDiscovered(getIntent());
+ } else {
+ Log.d(Constants.TAG, "NFC: No NDEF discovered!");
+ }
} else {
Log.e(Constants.TAG, "Android Beam not supported by Android < 4.1");
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java
deleted file mode 100644
index f331358fa..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-
-import com.beardedhen.androidbootstrap.BootstrapButton;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
-
-import java.util.Locale;
-
-public class ImportKeysClipboardFragment extends Fragment {
-
- private ImportKeysActivity mImportActivity;
- private BootstrapButton mButton;
-
- /**
- * Creates new instance of this fragment
- */
- public static ImportKeysClipboardFragment newInstance() {
- ImportKeysClipboardFragment frag = new ImportKeysClipboardFragment();
-
- Bundle args = new Bundle();
- frag.setArguments(args);
-
- return frag;
- }
-
- /**
- * Inflate the layout for this fragment
- */
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.import_keys_clipboard_fragment, container, false);
-
- mButton = (BootstrapButton) view.findViewById(R.id.import_clipboard_button);
- mButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
- String sendText = "";
- if (clipboardText != null) {
- sendText = clipboardText.toString();
- if (sendText.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
- mImportActivity.loadFromFingerprintUri(null, Uri.parse(sendText));
- return;
- }
- }
- mImportActivity.loadCallback(sendText.getBytes(), null, null, null, null);
- }
- });
-
- return view;
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- mImportActivity = (ImportKeysActivity) getActivity();
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
index 51f961aab..060e9bab2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
@@ -19,21 +19,24 @@ package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.beardedhen.androidbootstrap.BootstrapButton;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.FileHelper;
+import java.util.Locale;
+
public class ImportKeysFileFragment extends Fragment {
private ImportKeysActivity mImportActivity;
- private BootstrapButton mBrowse;
+ private View mBrowse;
+ private View mClipboardButton;
public static final int REQUEST_CODE_FILE = 0x00007003;
@@ -56,26 +59,45 @@ public class ImportKeysFileFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_file_fragment, container, false);
- mBrowse = (BootstrapButton) view.findViewById(R.id.import_keys_file_browse);
+ mBrowse = view.findViewById(R.id.import_keys_file_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// open .asc or .gpg files
- // setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
+ // setting it to text/plain prevents Cyanogenmod's file manager from selecting asc
// or gpg types!
FileHelper.openFile(ImportKeysFileFragment.this, Constants.Path.APP_DIR + "/",
"*/*", REQUEST_CODE_FILE);
}
});
+ mClipboardButton = view.findViewById(R.id.import_clipboard_button);
+ mClipboardButton.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
+ String sendText = "";
+ if (clipboardText != null) {
+ sendText = clipboardText.toString();
+ if (sendText.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
+ mImportActivity.loadFromFingerprintUri(null, Uri.parse(sendText));
+ return;
+ }
+ }
+ mImportActivity.loadCallback(sendText.getBytes(), null, null, null, null);
+ }
+ });
+
+
return view;
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
- mImportActivity = (ImportKeysActivity) getActivity();
+ mImportActivity = (ImportKeysActivity) activity;
}
@Override
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java
index a639fe0e0..9264829ea 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysKeybaseFragment.java
@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -29,8 +30,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
-import com.beardedhen.androidbootstrap.BootstrapButton;
-
import org.sufficientlysecure.keychain.R;
/**
@@ -40,7 +39,7 @@ import org.sufficientlysecure.keychain.R;
public class ImportKeysKeybaseFragment extends Fragment {
private ImportKeysActivity mImportActivity;
- private BootstrapButton mSearchButton;
+ private View mSearchButton;
private EditText mQueryEditText;
public static final String ARG_QUERY = "query";
@@ -66,7 +65,7 @@ public class ImportKeysKeybaseFragment extends Fragment {
mQueryEditText = (EditText) view.findViewById(R.id.import_keybase_query);
- mSearchButton = (BootstrapButton) view.findViewById(R.id.import_keybase_search);
+ mSearchButton = view.findViewById(R.id.import_keybase_search);
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -101,8 +100,6 @@ public class ImportKeysKeybaseFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- mImportActivity = (ImportKeysActivity) getActivity();
-
// set displayed values
if (getArguments() != null) {
if (getArguments().containsKey(ARG_QUERY)) {
@@ -112,6 +109,13 @@ public class ImportKeysKeybaseFragment extends Fragment {
}
}
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ mImportActivity = (ImportKeysActivity) activity;
+ }
+
private void search(String query) {
mImportActivity.loadCallback(null, null, null, null, query);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
index d91c55da3..7d8dc4a6c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java
@@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Notify;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
@@ -97,7 +98,7 @@ public class ImportKeysListFragment extends ListFragment implements
public ArrayList<ParcelableKeyRing> getSelectedData() {
ArrayList<ParcelableKeyRing> result = new ArrayList<ParcelableKeyRing>();
- for(ImportKeysListEntry entry : getSelectedEntries()) {
+ for (ImportKeysListEntry entry : getSelectedEntries()) {
result.add(mCachedKeyData.get(entry.getKeyId()));
}
return result;
@@ -273,17 +274,15 @@ public class ImportKeysListFragment extends ListFragment implements
// No error
mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings();
} else if (error instanceof ImportKeysListLoader.FileHasNoContent) {
- AppMsg.makeText(getActivity(), R.string.error_import_file_no_content,
- AppMsg.STYLE_ALERT).show();
+ Notify.showNotify(getActivity(), R.string.error_import_file_no_content, Notify.Style.ERROR);
} else if (error instanceof ImportKeysListLoader.NonPgpPart) {
- AppMsg.makeText(getActivity(),
+ Notify.showNotify(getActivity(),
((ImportKeysListLoader.NonPgpPart) error).getCount() + " " + getResources().
getQuantityString(R.plurals.error_import_non_pgp_part,
((ImportKeysListLoader.NonPgpPart) error).getCount()),
- new AppMsg.Style(AppMsg.LENGTH_LONG, R.color.confirm)).show();
+ Notify.Style.OK);
} else {
- AppMsg.makeText(getActivity(), R.string.error_generic_report_bug,
- new AppMsg.Style(AppMsg.LENGTH_LONG, R.color.alert)).show();
+ Notify.showNotify(getActivity(), R.string.error_generic_report_bug, Notify.Style.ERROR);
}
break;
@@ -292,23 +291,17 @@ public class ImportKeysListFragment extends ListFragment implements
// TODO: possibly fine-tune message building for these two cases
if (error == null) {
- AppMsg.makeText(
- getActivity(), getResources().getQuantityString(R.plurals.keys_found,
- mAdapter.getCount(), mAdapter.getCount()),
- AppMsg.STYLE_INFO
- ).show();
+ // No error
} else if (error instanceof Keyserver.QueryTooShortException) {
- AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query,
- AppMsg.STYLE_ALERT).show();
+ Notify.showNotify(getActivity(), R.string.error_keyserver_insufficient_query, Notify.Style.ERROR);
} else if (error instanceof Keyserver.TooManyResponsesException) {
- AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses,
- AppMsg.STYLE_ALERT).show();
+ Notify.showNotify(getActivity(), R.string.error_keyserver_too_many_responses, Notify.Style.ERROR);
} else if (error instanceof Keyserver.QueryFailedException) {
Log.d(Constants.TAG,
"Unrecoverable keyserver query error: " + error.getLocalizedMessage());
String alert = getActivity().getString(R.string.error_searching_keys);
alert = alert + " (" + error.getLocalizedMessage() + ")";
- AppMsg.makeText(getActivity(), alert, AppMsg.STYLE_ALERT).show();
+ Notify.showNotify(getActivity(), alert, Notify.Style.ERROR);
}
break;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java
deleted file mode 100644
index 45f464b1c..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-
-import com.beardedhen.androidbootstrap.BootstrapButton;
-
-import org.sufficientlysecure.keychain.R;
-
-public class ImportKeysNFCFragment extends Fragment {
-
- private BootstrapButton mButton;
-
- /**
- * Creates new instance of this fragment
- */
- public static ImportKeysNFCFragment newInstance() {
- ImportKeysNFCFragment frag = new ImportKeysNFCFragment();
-
- Bundle args = new Bundle();
- frag.setArguments(args);
-
- return frag;
- }
-
- /**
- * Inflate the layout for this fragment
- */
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.import_keys_nfc_fragment, container, false);
-
- mButton = (BootstrapButton) view.findViewById(R.id.import_nfc_button);
- mButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- // show nfc help
- Intent intent = new Intent(getActivity(), HelpActivity.class);
- intent.putExtra(HelpActivity.EXTRA_SELECTED_TAB, HelpActivity.TAB_NFC);
- startActivityForResult(intent, 0);
- }
- });
-
- return view;
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java
index 22b56e1ab..0cbb51c77 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java
@@ -17,47 +17,47 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.beardedhen.androidbootstrap.BootstrapButton;
-import com.devspark.appmsg.AppMsg;
import com.google.zxing.integration.android.IntentResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Notify;
import java.util.ArrayList;
import java.util.Locale;
public class ImportKeysQrCodeFragment extends Fragment {
-
private ImportKeysActivity mImportActivity;
- private BootstrapButton mButton;
- private TextView mText;
- private ProgressBar mProgress;
+ private View mNfcButton;
+
+ private View mQrCodeButton;
+ private TextView mQrCodeText;
+ private ProgressBar mQrCodeProgress;
- private String[] mScannedContent;
+ private String[] mQrCodeContent;
/**
* Creates new instance of this fragment
*/
- public static ImportKeysQrCodeFragment newInstance() {
- ImportKeysQrCodeFragment frag = new ImportKeysQrCodeFragment();
+ public static ImportKeysFileFragment newInstance() {
+ ImportKeysFileFragment frag = new ImportKeysFileFragment();
Bundle args = new Bundle();
- frag.setArguments(args);
+ frag.setArguments(args);
return frag;
}
@@ -68,11 +68,23 @@ public class ImportKeysQrCodeFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_qr_code_fragment, container, false);
- mButton = (BootstrapButton) view.findViewById(R.id.import_qrcode_button);
- mText = (TextView) view.findViewById(R.id.import_qrcode_text);
- mProgress = (ProgressBar) view.findViewById(R.id.import_qrcode_progress);
+ mNfcButton = view.findViewById(R.id.import_nfc_button);
+ mNfcButton.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ // show nfc help
+ Intent intent = new Intent(getActivity(), HelpActivity.class);
+ intent.putExtra(HelpActivity.EXTRA_SELECTED_TAB, HelpActivity.TAB_NFC);
+ startActivityForResult(intent, 0);
+ }
+ });
+
+ mQrCodeButton = view.findViewById(R.id.import_qrcode_button);
+ mQrCodeText = (TextView) view.findViewById(R.id.import_qrcode_text);
+ mQrCodeProgress = (ProgressBar) view.findViewById(R.id.import_qrcode_progress);
- mButton.setOnClickListener(new OnClickListener() {
+ mQrCodeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -85,10 +97,10 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
- mImportActivity = (ImportKeysActivity) getActivity();
+ mImportActivity = (ImportKeysActivity) activity;
}
@Override
@@ -122,8 +134,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
// fail...
- AppMsg.makeText(getActivity(), R.string.import_qr_code_wrong, AppMsg.STYLE_ALERT)
- .show();
+ Notify.showNotify(getActivity(), R.string.import_qr_code_wrong, Notify.Style.ERROR);
}
break;
@@ -136,6 +147,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
}
+
public void importFingerprint(Uri dataUri) {
mImportActivity.loadFromFingerprintUri(null, dataUri);
}
@@ -151,32 +163,31 @@ public class ImportKeysQrCodeFragment extends Fragment {
// first qr code -> setup
if (counter == 0) {
- mScannedContent = new String[size];
- mProgress.setMax(size);
- mProgress.setVisibility(View.VISIBLE);
- mText.setVisibility(View.VISIBLE);
+ mQrCodeContent = new String[size];
+ mQrCodeProgress.setMax(size);
+ mQrCodeProgress.setVisibility(View.VISIBLE);
+ mQrCodeText.setVisibility(View.VISIBLE);
}
- if (mScannedContent == null || counter > mScannedContent.length) {
- AppMsg.makeText(getActivity(), R.string.import_qr_code_start_with_one, AppMsg.STYLE_ALERT)
- .show();
+ if (mQrCodeContent == null || counter > mQrCodeContent.length) {
+ Notify.showNotify(getActivity(), R.string.import_qr_code_start_with_one, Notify.Style.ERROR);
return;
}
// save scanned content
- mScannedContent[counter] = content;
+ mQrCodeContent[counter] = content;
// get missing numbers
ArrayList<Integer> missing = new ArrayList<Integer>();
- for (int i = 0; i < mScannedContent.length; i++) {
- if (mScannedContent[i] == null) {
+ for (int i = 0; i < mQrCodeContent.length; i++) {
+ if (mQrCodeContent[i] == null) {
missing.add(i);
}
}
// update progress and text
- int alreadyScanned = mScannedContent.length - missing.size();
- mProgress.setProgress(alreadyScanned);
+ int alreadyScanned = mQrCodeContent.length - missing.size();
+ mQrCodeProgress.setProgress(alreadyScanned);
String missingString = "";
for (int m : missing) {
@@ -188,17 +199,16 @@ public class ImportKeysQrCodeFragment extends Fragment {
String missingText = getResources().getQuantityString(R.plurals.import_qr_code_missing,
missing.size(), missingString);
- mText.setText(missingText);
+ mQrCodeText.setText(missingText);
// finished!
if (missing.size() == 0) {
- mText.setText(R.string.import_qr_code_finished);
+ mQrCodeText.setText(R.string.import_qr_code_finished);
String result = "";
- for (String in : mScannedContent) {
+ for (String in : mQrCodeContent) {
result += in;
}
mImportActivity.loadCallback(result.getBytes(), null, null, null, null);
}
}
-
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java
index 9e3d88ff5..eabc8348c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java
@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui;
+import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -32,8 +33,6 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
-import com.beardedhen.androidbootstrap.BootstrapButton;
-
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
@@ -46,8 +45,10 @@ public class ImportKeysServerFragment extends Fragment {
private ImportKeysActivity mImportActivity;
- private BootstrapButton mSearchButton;
+ private View mSearchButton;
private EditText mQueryEditText;
+ private View mConfigButton;
+ private View mConfigLayout;
private Spinner mServerSpinner;
private ArrayAdapter<String> mServerAdapter;
@@ -73,14 +74,17 @@ public class ImportKeysServerFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_server_fragment, container, false);
- mSearchButton = (BootstrapButton) view.findViewById(R.id.import_server_search);
+ mSearchButton = view.findViewById(R.id.import_server_search);
mQueryEditText = (EditText) view.findViewById(R.id.import_server_query);
+ mConfigButton = view.findViewById(R.id.import_server_config_button);
+ mConfigLayout = view.findViewById(R.id.import_server_config);
mServerSpinner = (Spinner) view.findViewById(R.id.import_server_spinner);
// add keyservers to spinner
mServerAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item, Preferences.getPreferences(getActivity())
- .getKeyServers());
+ .getKeyServers()
+ );
mServerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mServerSpinner.setAdapter(mServerAdapter);
if (mServerAdapter.getCount() > 0) {
@@ -118,6 +122,17 @@ public class ImportKeysServerFragment extends Fragment {
}
});
+ mConfigButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mImportActivity.getViewPagerHeight() > ImportKeysActivity.VIEW_PAGER_HEIGHT) {
+ mImportActivity.resizeViewPager(ImportKeysActivity.VIEW_PAGER_HEIGHT);
+ } else {
+ mImportActivity.resizeViewPager(ImportKeysActivity.VIEW_PAGER_HEIGHT + 41);
+ }
+ }
+ });
+
return view;
}
@@ -125,8 +140,6 @@ public class ImportKeysServerFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- mImportActivity = (ImportKeysActivity) getActivity();
-
// set displayed values
if (getArguments() != null) {
if (getArguments().containsKey(ARG_QUERY)) {
@@ -150,6 +163,13 @@ public class ImportKeysServerFragment extends Fragment {
}
}
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ mImportActivity = (ImportKeysActivity) activity;
+ }
+
private void search(String query, String keyServer) {
mImportActivity.loadCallback(null, null, query, keyServer, null);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 13e9d22ab..1912b6e7d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -171,7 +171,7 @@ public class ViewKeyActivity extends ActionBarActivity implements
Bundle shareBundle = new Bundle();
shareBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ViewKeyShareFragment.class,
- mainBundle, getString(R.string.key_view_tab_share));
+ shareBundle, getString(R.string.key_view_tab_share));
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
index 03a82696d..c2712e89e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java
@@ -133,7 +133,7 @@ public class ImportKeysListLoader
// read all available blocks... (asc files can contain many blocks with BEGIN END)
while (bufferedInput.available() > 0) {
- // todo deal with non-keyring objects?
+ // TODO: deal with non-keyring objects?
List<UncachedKeyRing> rings = UncachedKeyRing.fromStream(bufferedInput);
for(UncachedKeyRing key : rings) {
ImportKeysListEntry item = new ImportKeysListEntry(getContext(), key);