diff options
Diffstat (limited to 'OpenKeychain')
21 files changed, 232 insertions, 210 deletions
diff --git a/OpenKeychain/.gitignore b/OpenKeychain/.gitignore index aa8bb5760..a44cc0f0f 100644 --- a/OpenKeychain/.gitignore +++ b/OpenKeychain/.gitignore @@ -27,3 +27,7 @@ pom.xml.* #IntelliJ IDEA .idea *.iml + +#Lint output +lint-report.html +lint-report_files/*
\ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 7b022b694..2bf75a4a0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.pgp; import android.content.Context; +import android.net.Uri; import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.bcpg.ArmoredInputStream; @@ -382,52 +383,44 @@ public class PgpDecryptVerify { currentProgress += 10; } - long signatureKeyId = 0; if (dataChunk instanceof PGPOnePassSignatureList) { updateProgress(R.string.progress_processing_signature, currentProgress, 100); signatureResult = new OpenPgpSignatureResult(); PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk; + Long masterKeyId = null; for (int i = 0; i < sigList.size(); ++i) { - signature = sigList.get(i); - - // TODO: rework this code, seems wonky! try { - signatureKey = ProviderHelper - .getPGPPublicKeyRingWithKeyId(mContext, signature.getKeyID()).getPublicKey(); + Uri uri = KeyRings.buildUnifiedKeyRingsFindBySubkeyUri( + Long.toString(sigList.get(i).getKeyID())); + masterKeyId = ProviderHelper.getMasterKeyId(mContext, uri); + signatureIndex = i; } catch (ProviderHelper.NotFoundException e) { Log.d(Constants.TAG, "key not found!"); } - if (signatureKeyId == 0) { - signatureKeyId = signature.getKeyID(); - } - if (signatureKey == null) { - signature = null; - } else { - signatureIndex = i; - signatureKeyId = signature.getKeyID(); - String userId = null; - try { - PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingWithKeyId( - mContext, signatureKeyId); - userId = PgpKeyHelper.getMainUserId(signKeyRing.getPublicKey()); - } catch (ProviderHelper.NotFoundException e) { - Log.d(Constants.TAG, "key not found!"); - } - signatureResult.setUserId(userId); - break; - } } - signatureResult.setKeyId(signatureKeyId); + if(masterKeyId == null) { + try { + signatureKey = ProviderHelper + .getPGPPublicKeyRing(mContext, masterKeyId).getPublicKey(); + } catch (ProviderHelper.NotFoundException e) { + // can't happen + } - if (signature != null) { + signature = sigList.get(signatureIndex); + signatureResult.setUserId(PgpKeyHelper.getMainUserId(signatureKey)); + signatureResult.setKeyId(signature.getKeyID()); JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); - signature.init(contentVerifierBuilderProvider, signatureKey); + } else { + if(!sigList.isEmpty()) { + signatureResult.setKeyId(sigList.get(0).getKeyID()); + } + Log.d(Constants.TAG, "SIGNATURE_UNKNOWN_PUB_KEY"); signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY); } @@ -500,7 +493,7 @@ public class PgpDecryptVerify { boolean validSignature = signature.verify(messageSignature); // TODO: implement CERTIFIED! - if (validKeyBinding & validSignature) { + if (validKeyBinding && validSignature) { Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED"); signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED); } else { @@ -654,7 +647,7 @@ public class PgpDecryptVerify { boolean validKeyBinding = verifyKeyBinding(mContext, signature, signatureKey); boolean validSignature = signature.verify(); - if (validKeyBinding & validSignature) { + if (validKeyBinding && validSignature) { Log.d(Constants.TAG, "SIGNATURE_SUCCESS_UNCERTIFIED"); signatureResult.setStatus(OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED); } else { 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 b52f106f1..d66332820 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -18,8 +18,6 @@ package org.sufficientlysecure.keychain.pgp; -import android.util.Pair; - import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.HashAlgorithmTags; import org.spongycastle.bcpg.SymmetricKeyAlgorithmTags; @@ -220,29 +218,26 @@ public class PgpKeyOperation { } - private Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildNewSecretKey( - ArrayList<String> userIds, ArrayList<PGPSecretKey> keys, - ArrayList<GregorianCalendar> keysExpiryDates, - ArrayList<Integer> keysUsages, - String newPassphrase, String oldPassphrase) + public Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildNewSecretKey( + SaveKeyringParcel saveParcel) throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException { - int usageId = keysUsages.get(0); + int usageId = saveParcel.keysUsages.get(0); boolean canSign; - String mainUserId = userIds.get(0); + String mainUserId = saveParcel.userIds.get(0); - PGPSecretKey masterKey = keys.get(0); + PGPSecretKey masterKey = saveParcel.keys.get(0); // this removes all userIds and certifications previously attached to the masterPublicKey PGPPublicKey masterPublicKey = masterKey.getPublicKey(); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()); + Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(saveParcel.oldPassphrase.toCharArray()); PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor); updateProgress(R.string.progress_certifying_master_key, 20, 100); - for (String userId : userIds) { + for (String userId : saveParcel.userIds) { PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); @@ -265,10 +260,10 @@ public class PgpKeyOperation { hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS); hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); - if (keysExpiryDates.get(0) != null) { + if (saveParcel.keysExpiryDates.get(0) != null) { GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC")); creationDate.setTime(masterPublicKey.getCreationTime()); - GregorianCalendar expiryDate = keysExpiryDates.get(0); + GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(0); //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c //here we purposefully ignore partial days in each date - long type has no fractional part! long numDays = (expiryDate.getTimeInMillis() / 86400000) - @@ -295,7 +290,7 @@ public class PgpKeyOperation { PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( PGPEncryptedData.CAST5, sha1Calc) .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - newPassphrase.toCharArray()); + saveParcel.newPassphrase.toCharArray()); PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(), @@ -303,15 +298,15 @@ public class PgpKeyOperation { updateProgress(R.string.progress_adding_sub_keys, 40, 100); - for (int i = 1; i < keys.size(); ++i) { - updateProgress(40 + 40 * (i - 1) / (keys.size() - 1), 100); + for (int i = 1; i < saveParcel.keys.size(); ++i) { + updateProgress(40 + 40 * (i - 1) / (saveParcel.keys.size() - 1), 100); - PGPSecretKey subKey = keys.get(i); + PGPSecretKey subKey = saveParcel.keys.get(i); PGPPublicKey subPublicKey = subKey.getPublicKey(); PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder() .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - oldPassphrase.toCharArray()); + saveParcel.oldPassphrase.toCharArray()); PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2); // TODO: now used without algorithm and creation time?! (APG 1) @@ -320,7 +315,7 @@ public class PgpKeyOperation { hashedPacketsGen = new PGPSignatureSubpacketGenerator(); unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); - usageId = keysUsages.get(i); + usageId = saveParcel.keysUsages.get(i); canSign = (usageId & KeyFlags.SIGN_DATA) > 0; //todo - separate function for this if (canSign) { Date todayDate = new Date(); //both sig times the same @@ -340,10 +335,10 @@ public class PgpKeyOperation { } hashedPacketsGen.setKeyFlags(false, usageId); - if (keysExpiryDates.get(i) != null) { + if (saveParcel.keysExpiryDates.get(i) != null) { GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC")); creationDate.setTime(subPublicKey.getCreationTime()); - GregorianCalendar expiryDate = keysExpiryDates.get(i); + GregorianCalendar expiryDate = saveParcel.keysExpiryDates.get(i); //note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c //here we purposefully ignore partial days in each date - long type has no fractional part! long numDays = (expiryDate.getTimeInMillis() / 86400000) - @@ -383,11 +378,6 @@ public class PgpKeyOperation { saveParcel.newPassphrase = ""; } - if (mKR == null) { - return buildNewSecretKey(saveParcel.userIDs, saveParcel.keys, saveParcel.keysExpiryDates, - saveParcel.keysUsages, saveParcel.newPassphrase, saveParcel.oldPassphrase); //new Keyring - } - /* IDs - NB This might not need to happen later, if we change the way the primary ID is chosen remove deleted ids @@ -421,7 +411,7 @@ public class PgpKeyOperation { int usageId = saveParcel.keysUsages.get(0); boolean canSign; - String mainUserId = saveParcel.userIDs.get(0); + String mainUserId = saveParcel.userIds.get(0); PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(saveParcel.oldPassphrase.toCharArray()); @@ -465,10 +455,10 @@ public class PgpKeyOperation { } if (saveParcel.primaryIDChanged || - !saveParcel.originalIDs.get(0).equals(saveParcel.userIDs.get(0))) { + !saveParcel.originalIDs.get(0).equals(saveParcel.userIds.get(0))) { anyIDChanged = true; ArrayList<Pair<String, PGPSignature>> sigList = new ArrayList<Pair<String, PGPSignature>>(); - for (String userId : saveParcel.userIDs) { + for (String userId : saveParcel.userIds) { String origID = saveParcel.originalIDs.get(userIDIndex); if (origID.equals(userId) && !saveParcel.newIDs[userIDIndex] && !userId.equals(saveParcel.originalPrimaryID) && userIDIndex != 0) { @@ -502,7 +492,7 @@ public class PgpKeyOperation { PGPPublicKey.addCertification(masterPublicKey, toAdd.first, toAdd.second); } } else { - for (String userId : saveParcel.userIDs) { + for (String userId : saveParcel.userIds) { String origID = saveParcel.originalIDs.get(userIDIndex); if (!origID.equals(userId) || saveParcel.newIDs[userIDIndex]) { anyIDChanged = true; @@ -530,7 +520,7 @@ public class PgpKeyOperation { ArrayList<Pair<String, PGPSignature>> sigList = new ArrayList<Pair<String, PGPSignature>>(); if (saveParcel.moddedKeys[0]) { userIDIndex = 0; - for (String userId : saveParcel.userIDs) { + for (String userId : saveParcel.userIds) { String origID = saveParcel.originalIDs.get(userIDIndex); if (!(origID.equals(saveParcel.originalPrimaryID) && !saveParcel.primaryIDChanged)) { Iterator<PGPSignature> sigs = masterPublicKey.getSignaturesForID(userId); 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 28376096d..3e0520c2a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -124,13 +124,13 @@ public class ProviderHelper { */ public static long getMasterKeyId(Context context, Uri queryUri) throws NotFoundException { // try extracting from the uri first - String firstSegment = queryUri.getPathSegments().get(1); - if(!firstSegment.equals("find")) try { - return Long.parseLong(firstSegment); - } catch(NumberFormatException e) { - // didn't work? oh well. - Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying..."); - } +// String firstSegment = queryUri.getPathSegments().get(1); +// if(!firstSegment.equals("find")) try { +// return Long.parseLong(firstSegment); +// } catch(NumberFormatException e) { +// // didn't work? oh well. +// Log.d(Constants.TAG, "Couldn't get masterKeyId from URI, querying..."); +// } Object data = getGenericData(context, queryUri, KeyRings.MASTER_KEY_ID, FIELD_TYPE_INTEGER); if(data != null) { return (Long) data; 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 a663e6a12..0fb28ed1c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -480,9 +480,9 @@ public class KeychainIntentService extends IntentService } else if (ACTION_SAVE_KEYRING.equals(action)) { try { /* Input */ - SaveKeyringParcel saveParams = data.getParcelable(SAVE_KEYRING_PARCEL); - String oldPassphrase = saveParams.oldPassphrase; - String newPassphrase = saveParams.newPassphrase; + SaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL); + String oldPassphrase = saveParcel.oldPassphrase; + String newPassphrase = saveParcel.newPassphrase; boolean canSign = true; if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) { @@ -493,7 +493,7 @@ public class KeychainIntentService extends IntentService newPassphrase = oldPassphrase; } - long masterKeyId = saveParams.keys.get(0).getKeyID(); + long masterKeyId = saveParcel.keys.get(0).getKeyID(); /* Operation */ if (!canSign) { @@ -506,10 +506,16 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); } else { PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100)); - PGPSecretKeyRing privkey = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); - PGPPublicKeyRing pubkey = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId); - PgpKeyOperation.Pair<PGPSecretKeyRing,PGPPublicKeyRing> pair = - keyOperations.buildSecretKey(privkey, pubkey, saveParams); + PgpKeyOperation.Pair<PGPSecretKeyRing, PGPPublicKeyRing> pair; + try { + PGPSecretKeyRing privkey = ProviderHelper.getPGPSecretKeyRing(this, masterKeyId); + PGPPublicKeyRing pubkey = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId); + + pair = keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing + } catch (ProviderHelper.NotFoundException e) { + pair = keyOperations.buildNewSecretKey(saveParcel); //new Keyring + } + setProgress(R.string.progress_saving_key_ring, 90, 100); // save the pair ProviderHelper.saveKeyRing(this, pair.second, pair.first); @@ -654,16 +660,16 @@ public class KeychainIntentService extends IntentService ArrayList<Long> secretMasterKeyIds = new ArrayList<Long>(); String selection = null; - if(!exportAll) { + if (!exportAll) { selection = KeychainDatabase.Tables.KEYS + "." + KeyRings.MASTER_KEY_ID + " IN( "; - for(long l : masterKeyIds) { + for (long l : masterKeyIds) { selection += Long.toString(l) + ","; } - selection = selection.substring(0, selection.length()-1) + " )"; + selection = selection.substring(0, selection.length() - 1) + " )"; } Cursor cursor = getContentResolver().query(KeyRings.buildUnifiedKeyRingsUri(), - new String[]{ KeyRings.MASTER_KEY_ID, KeyRings.HAS_SECRET }, + new String[]{KeyRings.MASTER_KEY_ID, KeyRings.HAS_SECRET}, selection, null, null); try { cursor.moveToFirst(); @@ -671,9 +677,9 @@ public class KeychainIntentService extends IntentService // export public either way publicMasterKeyIds.add(cursor.getLong(0)); // add secret if available (and requested) - if(exportSecret && cursor.getInt(1) != 0) + if (exportSecret && cursor.getInt(1) != 0) secretMasterKeyIds.add(cursor.getLong(0)); - } while(cursor.moveToNext()); + } while (cursor.moveToNext()); } finally { cursor.close(); } @@ -757,13 +763,13 @@ public class KeychainIntentService extends IntentService // verify downloaded key by comparing fingerprints if (entry.getFingerPrintHex() != null) { String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex( - downloadedKey.getPublicKey().getFingerprint()); + downloadedKey.getPublicKey().getFingerprint()); if (downloadedKeyFp.equals(entry.getFingerPrintHex())) { Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " + "the requested fingerprint!"); } else { throw new PgpGeneralException("fingerprint of downloaded key is " + - "NOT the same as the requested fingerprint!"); + "NOT the same as the requested fingerprint!"); } } 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 7c2dcf2c1..11b1ec978 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -29,7 +29,7 @@ import java.util.GregorianCalendar; public class SaveKeyringParcel implements Parcelable { - public ArrayList<String> userIDs; + public ArrayList<String> userIds; public ArrayList<String> originalIDs; public ArrayList<String> deletedIDs; public boolean[] newIDs; @@ -47,7 +47,7 @@ public class SaveKeyringParcel implements Parcelable { public SaveKeyringParcel() {} private SaveKeyringParcel(Parcel source) { - userIDs = (ArrayList<String>) source.readSerializable(); + userIds = (ArrayList<String>) source.readSerializable(); originalIDs = (ArrayList<String>) source.readSerializable(); deletedIDs = (ArrayList<String>) source.readSerializable(); newIDs = source.createBooleanArray(); @@ -70,7 +70,7 @@ public class SaveKeyringParcel implements Parcelable { @Override public void writeToParcel(Parcel destination, int flags) { - destination.writeSerializable(userIDs); //might not be the best method to store. + destination.writeSerializable(userIds); //might not be the best method to store. destination.writeSerializable(originalIDs); destination.writeSerializable(deletedIDs); destination.writeBooleanArray(newIDs); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index e2e09f052..910365394 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -193,7 +193,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements if (data.moveToFirst()) { // TODO: put findViewById in onCreate! mPubKeyId = data.getLong(INDEX_MASTER_KEY_ID); - String keyIdStr = PgpKeyHelper.convertKeyIdToHexShort(mPubKeyId); + String keyIdStr = PgpKeyHelper.convertKeyIdToHex(mPubKeyId); ((TextView) findViewById(R.id.key_id)).setText(keyIdStr); String mainUserId = data.getString(INDEX_USER_ID); 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 4e21b172e..84f0c41cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -568,7 +568,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); SaveKeyringParcel saveParams = new SaveKeyringParcel(); - saveParams.userIDs = getUserIds(mUserIdsView); + saveParams.userIds = getUserIds(mUserIdsView); saveParams.originalIDs = mUserIdsView.getOriginalIDs(); saveParams.deletedIDs = mUserIdsView.getDeletedIDs(); saveParams.newIDs = toPrimitiveArray(mUserIdsView.getNewIDFlags()); 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 6ea79473a..46da6257a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -93,6 +93,11 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O ImportKeysClipboardFragment.class, ImportKeysNFCFragment.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 int mCurrentNavPosition = -1; @@ -152,7 +157,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O /* Keychain's own Actions */ // display file fragment - loadNavFragment(1, null); + loadNavFragment(NAV_FILE, null); if (dataUri != null) { // action: directly load data @@ -187,7 +192,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O // display keyserver fragment with query Bundle args = new Bundle(); args.putString(ImportKeysServerFragment.ARG_QUERY, query); - loadNavFragment(0, args); + loadNavFragment(NAV_SERVER, args); // action: search immediately startListFragment(savedInstanceState, null, null, query); @@ -212,7 +217,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { // NOTE: this only displays the appropriate fragment, no actions are taken - loadNavFragment(1, null); + loadNavFragment(NAV_FILE, null); // no immediate actions! startListFragment(savedInstanceState, null, null, null); @@ -220,14 +225,14 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O // also exposed in AndroidManifest // NOTE: this only displays the appropriate fragment, no actions are taken - loadNavFragment(2, null); + loadNavFragment(NAV_QR_CODE, null); // 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(3, null); + loadNavFragment(NAV_NFC, null); // no immediate actions! startListFragment(savedInstanceState, null, null, null); @@ -327,7 +332,7 @@ 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(0, args); + loadNavFragment(NAV_SERVER, args); // action: search directly startListFragment(savedInstanceState, null, null, query); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index 0dc36a792..0ec652aad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -155,8 +155,8 @@ public class ViewCertActivity extends ActionBarActivity try { sig.init(new JcaPGPContentVerifierBuilderProvider().setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME), signeeRing.getPublicKey()); - if (sig.verifyCertification(signeeUid, signerRing.getPublicKey())) { + Constants.BOUNCY_CASTLE_PROVIDER_NAME), signerRing.getPublicKey()); + if (sig.verifyCertification(signeeUid, signeeRing.getPublicKey())) { mStatus.setText("ok"); mStatus.setTextColor(getResources().getColor(R.color.bbutton_success)); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java index 2b57b2bf0..d535195f0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivityJB.java @@ -18,12 +18,14 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; +import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.NfcAdapter.CreateNdefMessageCallback; import android.nfc.NfcAdapter.OnNdefPushCompleteCallback; import android.nfc.NfcEvent; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -33,6 +35,7 @@ import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; @@ -62,11 +65,38 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess // Check for available NFC Adapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this); if (mNfcAdapter != null) { - // init nfc - // Register callback to set NDEF message - mNfcAdapter.setNdefPushMessageCallback(this, this); - // Register callback to listen for message-sent success - mNfcAdapter.setOnNdefPushCompleteCallback(this, this); + /* + * Retrieve mSharedKeyringBytes here asynchronously (to not block the UI) + * and init nfc adapter afterwards. + * mSharedKeyringBytes can not be retrieved in createNdefMessage, because this process + * has no permissions to query the Uri. + */ + AsyncTask<NfcAdapter, Void, Void> initTask = + new AsyncTask<NfcAdapter, Void, Void>() { + protected Void doInBackground(NfcAdapter... adapter) { + try { + Uri dataUri = KeychainContract.KeyRingData.buildPublicKeyRingUri(mDataUri); + mSharedKeyringBytes = ProviderHelper.getPGPKeyRing( + ViewKeyActivityJB.this, dataUri).getEncoded(); + } catch (IOException e) { + Log.e(Constants.TAG, "Error parsing keyring", e); + } catch (ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, "key not found!", e); + } + return null; + } + + protected void onPostExecute(Void result) { + // Register callback to set NDEF message + mNfcAdapter.setNdefPushMessageCallback(ViewKeyActivityJB.this + , ViewKeyActivityJB.this); + // Register callback to listen for message-sent success + mNfcAdapter.setOnNdefPushCompleteCallback(ViewKeyActivityJB.this, + ViewKeyActivityJB.this); + } + }; + + initTask.execute(); } } } @@ -82,20 +112,9 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess * guarantee that this activity starts when receiving a beamed message. For now, this code * uses the tag dispatch system. */ - try { - // get public keyring as byte array - mSharedKeyringBytes = ProviderHelper.getPGPKeyRing(this, mDataUri).getEncoded(); - - NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME, - mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME)); - return msg; - } catch(IOException e) { - Log.e(Constants.TAG, "Error parsing keyring", e); - return null; - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - return null; - } + NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME, + mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME)); + return msg; } /** 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 3d4002696..a7543d194 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -39,6 +39,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; @@ -204,8 +205,9 @@ public class ViewKeyMainFragment extends Fragment implements * because the notification triggers faster than the activity closes. */ // Avoid NullPointerExceptions... - if(data.getCount() == 0) + if(data.getCount() == 0) { return; + } // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) switch (loader.getId()) { @@ -232,7 +234,8 @@ public class ViewKeyMainFragment extends Fragment implements mActionEdit.setOnClickListener(new View.OnClickListener() { public void onClick(View view) { Intent editIntent = new Intent(getActivity(), EditKeyActivity.class); - editIntent.setData(mDataUri); + editIntent.setData( + KeyRingData.buildSecretKeyRingUri(mDataUri)); editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); startActivityForResult(editIntent, 0); } @@ -292,6 +295,7 @@ public class ViewKeyMainFragment extends Fragment implements case LOADER_ID_KEYS: // hide encrypt button if no encryption key is available + // TODO: do with subquery! boolean canEncrypt = false; data.moveToFirst(); do { @@ -329,7 +333,8 @@ public class ViewKeyMainFragment extends Fragment implements private void encryptToContact(Uri dataUri) { // TODO preselect from uri? should be feasible without trivial query try { - long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); + long keyId = ProviderHelper.getMasterKeyId(getActivity(), + KeyRingData.buildPublicKeyRingUri(dataUri)); long[] encryptionKeyIds = new long[]{ keyId }; Intent intent = new Intent(getActivity(), EncryptActivity.class); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java index 64b735bfa..ed274c025 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java @@ -95,7 +95,7 @@ public class ViewKeyKeysAdapter extends CursorAdapter { ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey); ImageView revokedKeyIcon = (ImageView) view.findViewById(R.id.ic_revokedKey); - String keyIdStr = PgpKeyHelper.convertKeyIdToHexShort(cursor.getLong(mIndexKeyId)); + String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId)); String algorithmStr = PgpKeyHelper.getAlgorithmInfo(cursor.getInt(mIndexAlgorithm), cursor.getInt(mIndexKeySize)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java index 09137f745..82c311f59 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java @@ -28,7 +28,9 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.TextView; + import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; @@ -43,7 +45,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView. private final ArrayList<Boolean> mCheckStates; - public static final String[] USER_IDS_PROJECTION = new String[] { + public static final String[] USER_IDS_PROJECTION = new String[]{ UserIds._ID, UserIds.USER_ID, UserIds.RANK, UserIds.VERIFIED, UserIds.IS_PRIMARY, UserIds.IS_REVOKED }; @@ -57,6 +59,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView. initIndex(c); } + public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags) { this(context, c, flags, false); } @@ -70,7 +73,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView. int count = newCursor.getCount(); mCheckStates.ensureCapacity(count); // initialize to true (use case knowledge: we usually want to sign all uids) - for(int i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { newCursor.moveToPosition(i); int verified = newCursor.getInt(mVerifiedId); mCheckStates.add(verified != Certs.VERIFIED_SECRET); @@ -105,7 +108,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView. TextView vAddress = (TextView) view.findViewById(R.id.address); ImageView vVerified = (ImageView) view.findViewById(R.id.certified); - if(cursor.getInt(mIsPrimary) > 0) { + if (cursor.getInt(mIsPrimary) > 0) { vRank.setText("+"); } else { vRank.setText(Integer.toString(cursor.getInt(mIndexRank))); @@ -119,18 +122,28 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView. } vAddress.setText(userId[1]); - if(cursor.getInt(mIsRevoked) > 0) { + if (cursor.getInt(mIsRevoked) > 0) { vRank.setText(" "); vVerified.setImageResource(android.R.drawable.presence_away); + + // disable and strike through text for revoked user ids + vUserId.setEnabled(false); + vAddress.setEnabled(false); + vUserId.setText(OtherHelper.strikeOutText(vUserId.getText())); + vAddress.setText(OtherHelper.strikeOutText(vAddress.getText())); } else { + vUserId.setEnabled(true); + vAddress.setEnabled(true); + int verified = cursor.getInt(mVerifiedId); // TODO introduce own resources for this :) - if(verified == Certs.VERIFIED_SECRET) + if (verified == Certs.VERIFIED_SECRET) { vVerified.setImageResource(android.R.drawable.presence_online); - else if(verified == Certs.VERIFIED_SELF) + } else if (verified == Certs.VERIFIED_SELF) { vVerified.setImageResource(android.R.drawable.presence_invisible); - else + } else { vVerified.setImageResource(android.R.drawable.presence_busy); + } } // don't care further if checkboxes aren't shown @@ -154,7 +167,7 @@ public class ViewKeyUserIdsAdapter extends CursorAdapter implements AdapterView. public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { CheckBox box = ((CheckBox) view.findViewById(R.id.checkBox)); - if(box != null) { + if (box != null) { box.toggle(); } } diff --git a/OpenKeychain/src/main/res/layout/certify_key_activity.xml b/OpenKeychain/src/main/res/layout/certify_key_activity.xml index 3fa0468de..0ae46a261 100644 --- a/OpenKeychain/src/main/res/layout/certify_key_activity.xml +++ b/OpenKeychain/src/main/res/layout/certify_key_activity.xml @@ -3,14 +3,14 @@ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" - android:layout_height="match_parent" > + android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="16dp" android:paddingRight="16dp" - android:orientation="vertical" > + android:orientation="vertical"> <TextView style="@style/SectionHeader" @@ -77,8 +77,7 @@ <TextView android:id="@+id/main_user_id" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:typeface="monospace" /> + android:layout_height="wrap_content" /> </TableRow> diff --git a/OpenKeychain/src/main/res/layout/key_list_fragment.xml b/OpenKeychain/src/main/res/layout/key_list_fragment.xml index f2430f213..951f8d729 100644 --- a/OpenKeychain/src/main/res/layout/key_list_fragment.xml +++ b/OpenKeychain/src/main/res/layout/key_list_fragment.xml @@ -105,5 +105,4 @@ </FrameLayout> - </FrameLayout> diff --git a/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml b/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml index 408c0c54e..8c3b61cda 100644 --- a/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml +++ b/OpenKeychain/src/main/res/layout/select_secret_key_layout_fragment.xml @@ -52,8 +52,7 @@ android:layout_marginRight="5dip" android:text="" android:visibility="gone" - android:textAppearance="?android:attr/textAppearanceSmall" - android:paddingLeft="10dp" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView android:id="@+id/select_secret_key_master_key_hex" diff --git a/OpenKeychain/src/main/res/layout/view_cert_activity.xml b/OpenKeychain/src/main/res/layout/view_cert_activity.xml index 95b8ffc8d..adb673d1f 100644 --- a/OpenKeychain/src/main/res/layout/view_cert_activity.xml +++ b/OpenKeychain/src/main/res/layout/view_cert_activity.xml @@ -61,7 +61,8 @@ android:id="@+id/signee_key" android:layout_width="0dp" android:layout_height="wrap_content" - android:paddingRight="5dip" /> + android:paddingRight="5dip" + android:typeface="monospace" /> </TableRow> <TableRow> diff --git a/OpenKeychain/src/main/res/layout/view_key_certs_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_certs_fragment.xml index 33042c541..08738ce40 100644 --- a/OpenKeychain/src/main/res/layout/view_key_certs_fragment.xml +++ b/OpenKeychain/src/main/res/layout/view_key_certs_fragment.xml @@ -1,34 +1,25 @@ -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent" - android:fillViewport="true"> + android:layout_height="match_parent"> - <RelativeLayout + <se.emilsjolander.stickylistheaders.StickyListHeadersListView android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <view - android:layout_width="match_parent" - android:layout_height="match_parent" - class="se.emilsjolander.stickylistheaders.StickyListHeadersListView" - android:id="@+id/list" - android:paddingRight="32dp" - android:paddingLeft="16dp" - android:layout_alignParentStart="false" - android:layout_alignParentEnd="false" - android:layout_below="@+id/list" /> + android:layout_height="match_parent" + android:id="@+id/list" + android:fastScrollEnabled="true" + android:paddingBottom="16dp" + android:paddingLeft="16dp" + android:paddingRight="32dp" + android:scrollbarStyle="outsideOverlay" /> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/empty_certs" - android:id="@+id/empty" - android:visibility="gone" - android:layout_centerInParent="true" - android:paddingBottom="32dp" /> - - </RelativeLayout> + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:text="@string/empty_certs" + android:id="@+id/empty" + android:visibility="gone" + android:gravity="center" + android:paddingBottom="32dp" /> -</ScrollView> +</FrameLayout> diff --git a/OpenKeychain/src/main/res/layout/view_key_keys_item.xml b/OpenKeychain/src/main/res/layout/view_key_keys_item.xml index aecedc39b..66cd4d7b5 100644 --- a/OpenKeychain/src/main/res/layout/view_key_keys_item.xml +++ b/OpenKeychain/src/main/res/layout/view_key_keys_item.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingLeft="8dip" - android:paddingRight="3dip" > + android:paddingRight="3dip"> <ImageView android:id="@+id/ic_masterKey" @@ -12,56 +12,34 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:paddingRight="6dip" + android:layout_alignParentLeft="true" android:src="@drawable/key_small" /> - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical" - android:paddingBottom="2dip" - android:paddingTop="2dip" > - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="horizontal"> - <TextView - android:id="@+id/keyId" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingRight="2dip" - android:text="@string/label_key_id" - android:textAppearance="?android:attr/textAppearanceMedium" - android:typeface="monospace" /> - - <TextView - android:id="@+id/keyDetails" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingRight="5dip" - android:text="(RSA, 1024bit)" - android:textAppearance="?android:attr/textAppearanceSmall" /> - </LinearLayout> - <TextView - android:id="@+id/keyExpiry" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="right" - android:text="@string/label_expiry" - android:textAppearance="?android:attr/textAppearanceSmall" /> - </LinearLayout> + <TextView + android:id="@+id/keyId" + android:layout_toRightOf="@+id/ic_masterKey" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingRight="2dip" + android:text="@string/label_key_id" + android:textAppearance="?android:attr/textAppearanceSmall" + android:typeface="monospace" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" - android:gravity="right" + android:layout_alignParentEnd="true" android:paddingBottom="2dip" - android:paddingTop="2dip" > + android:paddingTop="2dip" + android:id="@+id/linearLayout"> - <ImageView android:id="@+id/ic_revokedKey" + <ImageView + android:id="@+id/ic_revokedKey" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:src="@drawable/revoked_key_small"/> + android:src="@drawable/revoked_key_small" /> + <ImageView android:id="@+id/ic_certifyKey" android:layout_width="wrap_content" @@ -81,4 +59,25 @@ android:src="@drawable/signed_small" /> </LinearLayout> -</LinearLayout> + <TextView + android:id="@+id/keyDetails" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingRight="5dip" + android:text="(RSA, 1024bit)" + android:textAppearance="?android:attr/textAppearanceSmall" + android:layout_below="@+id/ic_masterKey" + android:layout_toRightOf="@+id/ic_masterKey" /> + + <TextView + android:id="@+id/keyExpiry" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="right" + android:text="@string/label_expiry" + android:textAppearance="?android:attr/textAppearanceSmall" + android:layout_alignTop="@+id/keyDetails" + android:layout_alignRight="@+id/linearLayout" + android:layout_alignEnd="@+id/linearLayout" /> + +</RelativeLayout> diff --git a/OpenKeychain/src/main/res/layout/view_key_userids_item.xml b/OpenKeychain/src/main/res/layout/view_key_userids_item.xml index e47f591cb..e76902512 100644 --- a/OpenKeychain/src/main/res/layout/view_key_userids_item.xml +++ b/OpenKeychain/src/main/res/layout/view_key_userids_item.xml @@ -42,8 +42,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/label_email" - android:textAppearance="?android:attr/textAppearanceSmall" - android:paddingLeft="10dp" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> </LinearLayout> |