diff options
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org')
18 files changed, 710 insertions, 764 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 74b407cd4..c1809e4e1 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -31,6 +31,9 @@ public final class Constants { // as defined in http://tools.ietf.org/html/rfc3156, section 7 public static final String NFC_MIME = "application/pgp-keys"; + // used by QR Codes (Guardian Project, Monkeysphere compatiblity) + public static final String FINGERPRINT_SCHEME = "openpgp4fpr"; + // Not BC due to the use of Spongy Castle for Android public static final String SC = BouncyCastleProvider.PROVIDER_NAME; public static final String BOUNCY_CASTLE_PROVIDER_NAME = SC; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java index e14c8bbdf..3fc63cda1 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java @@ -42,17 +42,6 @@ import android.content.Context; public class PgpKeyHelper { - /** - * Returns the last 9 chars of a fingerprint - * - * @param fingerprint - * String containing short or long fingerprint - * @return - */ - public static String shortifyFingerprint(String fingerprint) { - return fingerprint.substring(41); - } - public static Date getCreationDate(PGPPublicKey key) { return key.getCreationTime(); } @@ -175,10 +164,6 @@ public class PgpKeyHelper { return true; } - public static boolean isExpired(PGPSecretKey key) { - return isExpired(key.getPublicKey()); - } - public static Vector<PGPSecretKey> getUsableCertificationKeys(PGPSecretKeyRing keyRing) { Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>(); Vector<PGPSecretKey> signingKeys = getCertificationKeys(keyRing); @@ -460,12 +445,12 @@ public class PgpKeyHelper { * @param fp * @return */ - public static String convertFingerprintToHex(byte[] fp) { + public static String convertFingerprintToHex(byte[] fp, boolean chunked) { String fingerPrint = ""; for (int i = 0; i < fp.length; ++i) { - if (i != 0 && i % 10 == 0) { + if (chunked && i != 0 && i % 10 == 0) { fingerPrint += " "; - } else if (i != 0 && i % 2 == 0) { + } else if (chunked && i != 0 && i % 2 == 0) { fingerPrint += " "; } String chunk = Integer.toHexString((fp[i] + 256) % 256).toUpperCase(Locale.US); @@ -491,21 +476,21 @@ public class PgpKeyHelper { key = secretKey.getPublicKey(); } - return convertFingerprintToHex(key.getFingerprint()); + return convertFingerprintToHex(key.getFingerprint(), true); } public static boolean isSecretKeyPrivateEmpty(PGPSecretKey secretKey) { return secretKey.isPrivateKeyEmpty(); } - public static boolean isSecretKeyPrivateEmpty(Context context, long keyId) { - PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId); - if (secretKey == null) { - Log.e(Constants.TAG, "Key could not be found!"); - return false; // could be a public key, assume it is not empty - } - return isSecretKeyPrivateEmpty(secretKey); - } +// public static boolean isSecretKeyPrivateEmpty(Context context, long keyId) { +// PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, keyId); +// if (secretKey == null) { +// Log.e(Constants.TAG, "Key could not be found!"); +// return false; // could be a public key, assume it is not empty +// } +// return isSecretKeyPrivateEmpty(secretKey); +// } public static String convertKeyIdToHex(long keyId) { String fingerPrint = Long.toHexString(keyId & 0xffffffffL).toUpperCase(Locale.US); @@ -539,9 +524,23 @@ public class PgpKeyHelper { * @return array with naming (0), email (1), comment (2) */ public static String[] splitUserId(String userId) { - String[] result = new String[] { "", "", "" }; + String[] result = new String[] { null, null, null }; + + if (userId == null || userId.equals("")) { + return result; + } - Pattern withComment = Pattern.compile("^(.*) \\((.*)\\) <(.*)>$"); + /* + * User ID matching: + * http://fiddle.re/t4p6f + * + * test cases: + * "Max Mustermann (this is a comment) <max@example.com>" + * "Max Mustermann <max@example.com>" + * "Max Mustermann (this is a comment)" + * "Max Mustermann [this is nothing]" + */ + Pattern withComment = Pattern.compile("^(.*?)(?: \\((.*)\\))?(?: <(.*)>)?$"); Matcher matcher = withComment.matcher(userId); if (matcher.matches()) { result[0] = matcher.group(1); @@ -550,13 +549,6 @@ public class PgpKeyHelper { return result; } - Pattern withoutComment = Pattern.compile("^(.*) <(.*)>$"); - matcher = withoutComment.matcher(userId); - if (matcher.matches()) { - result[0] = matcher.group(1); - result[1] = matcher.group(2); - return result; - } return result; } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index d2381f6f0..d8de30b37 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -45,6 +45,7 @@ public class KeychainContract { String KEY_RING_ROW_ID = "key_ring_row_id"; // foreign key to key_rings._ID String KEY_DATA = "key_data"; // PGPPublicKey/PGPSecretKey blob String RANK = "rank"; + String FINGERPRINT = "fingerprint"; } interface UserIdsColumns { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 60c5c91a8..3a00f3101 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -31,7 +31,7 @@ import android.provider.BaseColumns; public class KeychainDatabase extends SQLiteOpenHelper { private static final String DATABASE_NAME = "apg.db"; - private static final int DATABASE_VERSION = 6; + private static final int DATABASE_VERSION = 7; public interface Tables { String KEY_RINGS = "key_rings"; @@ -42,33 +42,45 @@ public class KeychainDatabase extends SQLiteOpenHelper { private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + KeyRingsColumns.MASTER_KEY_ID + " INT64, " + KeyRingsColumns.TYPE + " INTEGER, " + + KeyRingsColumns.MASTER_KEY_ID + " INT64, " + + KeyRingsColumns.TYPE + " INTEGER, " + KeyRingsColumns.KEY_RING_DATA + " BLOB)"; private static final String CREATE_KEYS = "CREATE TABLE IF NOT EXISTS " + Tables.KEYS + " (" - + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KeysColumns.KEY_ID - + " INT64, " + KeysColumns.TYPE + " INTEGER, " + KeysColumns.IS_MASTER_KEY - + " INTEGER, " + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.KEY_SIZE - + " INTEGER, " + KeysColumns.CAN_CERTIFY + " INTEGER, " + KeysColumns.CAN_SIGN - + " INTEGER, " + KeysColumns.CAN_ENCRYPT + " INTEGER, " + KeysColumns.IS_REVOKED - + " INTEGER, " + KeysColumns.CREATION + " INTEGER, " + KeysColumns.EXPIRY - + " INTEGER, " + KeysColumns.KEY_DATA + " BLOB," + KeysColumns.RANK + " INTEGER, " + + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + KeysColumns.KEY_ID + " INT64, " + + KeysColumns.TYPE + " INTEGER, " + + KeysColumns.IS_MASTER_KEY + " INTEGER, " + + KeysColumns.ALGORITHM + " INTEGER, " + + KeysColumns.KEY_SIZE + " INTEGER, " + + KeysColumns.CAN_CERTIFY + " INTEGER, " + + KeysColumns.CAN_SIGN + " INTEGER, " + + KeysColumns.CAN_ENCRYPT + " INTEGER, " + + KeysColumns.IS_REVOKED + " INTEGER, " + + KeysColumns.CREATION + " INTEGER, " + + KeysColumns.EXPIRY + " INTEGER, " + + KeysColumns.KEY_DATA + " BLOB," + + KeysColumns.RANK + " INTEGER, " + + KeysColumns.FINGERPRINT + " BLOB, " + KeysColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, FOREIGN KEY(" + KeysColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)"; private static final String CREATE_USER_IDS = "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + UserIdsColumns.USER_ID + " TEXT, " + UserIdsColumns.RANK + " INTEGER, " + + UserIdsColumns.USER_ID + " TEXT, " + + UserIdsColumns.RANK + " INTEGER, " + UserIdsColumns.KEY_RING_ROW_ID + " INTEGER NOT NULL, FOREIGN KEY(" + UserIdsColumns.KEY_RING_ROW_ID + ") REFERENCES " + Tables.KEY_RINGS + "(" + BaseColumns._ID + ") ON DELETE CASCADE)"; private static final String CREATE_API_APPS = "CREATE TABLE IF NOT EXISTS " + Tables.API_APPS + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + ApiAppsColumns.PACKAGE_NAME + " TEXT UNIQUE, " + ApiAppsColumns.PACKAGE_SIGNATURE - + " BLOB, " + ApiAppsColumns.KEY_ID + " INT64, " + ApiAppsColumns.ENCRYPTION_ALGORITHM - + " INTEGER, " + ApiAppsColumns.HASH_ALORITHM + " INTEGER, " + + ApiAppsColumns.PACKAGE_NAME + " TEXT UNIQUE, " + + ApiAppsColumns.PACKAGE_SIGNATURE + " BLOB, " + + ApiAppsColumns.KEY_ID + " INT64, " + + ApiAppsColumns.ENCRYPTION_ALGORITHM + " INTEGER, " + + ApiAppsColumns.HASH_ALORITHM + " INTEGER, " + ApiAppsColumns.COMPRESSION + " INTEGER)"; KeychainDatabase(Context context) { @@ -103,21 +115,24 @@ public class KeychainDatabase extends SQLiteOpenHelper { Log.w(Constants.TAG, "Upgrading database to version " + version); switch (version) { - case 3: - db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.CAN_CERTIFY - + " INTEGER DEFAULT 0;"); - db.execSQL("UPDATE " + Tables.KEYS + " SET " + KeysColumns.CAN_CERTIFY - + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;"); - break; - case 4: - db.execSQL(CREATE_API_APPS); - case 5: - // new column: package_signature - db.execSQL("DROP TABLE IF EXISTS " + Tables.API_APPS); - db.execSQL(CREATE_API_APPS); - - default: - break; + case 3: + db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.CAN_CERTIFY + + " INTEGER DEFAULT 0;"); + db.execSQL("UPDATE " + Tables.KEYS + " SET " + KeysColumns.CAN_CERTIFY + + " = 1 WHERE " + KeysColumns.IS_MASTER_KEY + "= 1;"); + break; + case 4: + db.execSQL(CREATE_API_APPS); + case 5: + // new column: package_signature + db.execSQL("DROP TABLE IF EXISTS " + Tables.API_APPS); + db.execSQL(CREATE_API_APPS); + case 6: + // new column: fingerprint + db.execSQL("ALTER TABLE " + Tables.KEYS + " ADD COLUMN " + KeysColumns.FINGERPRINT + + " BLOB;"); + default: + break; } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index 70fb11e47..cd3007353 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -96,7 +96,7 @@ public class KeychainProvider extends ContentProvider { /** * public key rings - * + * * <pre> * key_rings/public * key_rings/public/# @@ -128,7 +128,7 @@ public class KeychainProvider extends ContentProvider { /** * public keys - * + * * <pre> * key_rings/public/#/keys * key_rings/public/#/keys/# @@ -143,7 +143,7 @@ public class KeychainProvider extends ContentProvider { /** * public user ids - * + * * <pre> * key_rings/public/#/user_ids * key_rings/public/#/user_ids/# @@ -158,7 +158,7 @@ public class KeychainProvider extends ContentProvider { /** * secret key rings - * + * * <pre> * key_rings/secret * key_rings/secret/# @@ -190,7 +190,7 @@ public class KeychainProvider extends ContentProvider { /** * secret keys - * + * * <pre> * key_rings/secret/#/keys * key_rings/secret/#/keys/# @@ -205,7 +205,7 @@ public class KeychainProvider extends ContentProvider { /** * secret user ids - * + * * <pre> * key_rings/secret/#/user_ids * key_rings/secret/#/user_ids/# @@ -228,7 +228,7 @@ public class KeychainProvider extends ContentProvider { /** * data stream - * + * * <pre> * data / _ * </pre> @@ -240,7 +240,9 @@ public class KeychainProvider extends ContentProvider { private KeychainDatabase mApgDatabase; - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public boolean onCreate() { mUriMatcher = buildUriMatcher(); @@ -248,120 +250,125 @@ public class KeychainProvider extends ContentProvider { return true; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public String getType(Uri uri) { final int match = mUriMatcher.match(uri); switch (match) { - case PUBLIC_KEY_RING: - case PUBLIC_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - case SECRET_KEY_RING: - case SECRET_KEY_RING_BY_EMAILS: - case SECRET_KEY_RING_BY_LIKE_EMAIL: - return KeyRings.CONTENT_TYPE; - - case PUBLIC_KEY_RING_BY_ROW_ID: - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - case SECRET_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_KEY_ID: - return KeyRings.CONTENT_ITEM_TYPE; - - case PUBLIC_KEY_RING_KEY: - case SECRET_KEY_RING_KEY: - return Keys.CONTENT_TYPE; - - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - return Keys.CONTENT_ITEM_TYPE; - - case PUBLIC_KEY_RING_USER_ID: - case SECRET_KEY_RING_USER_ID: - return UserIds.CONTENT_TYPE; - - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - return UserIds.CONTENT_ITEM_TYPE; - - case API_APPS: - return ApiApps.CONTENT_TYPE; - - case API_APPS_BY_ROW_ID: - case API_APPS_BY_PACKAGE_NAME: - return ApiApps.CONTENT_ITEM_TYPE; - - default: - throw new UnsupportedOperationException("Unknown uri: " + uri); + case PUBLIC_KEY_RING: + case PUBLIC_KEY_RING_BY_EMAILS: + case PUBLIC_KEY_RING_BY_LIKE_EMAIL: + case SECRET_KEY_RING: + case SECRET_KEY_RING_BY_EMAILS: + case SECRET_KEY_RING_BY_LIKE_EMAIL: + return KeyRings.CONTENT_TYPE; + + case PUBLIC_KEY_RING_BY_ROW_ID: + case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: + case PUBLIC_KEY_RING_BY_KEY_ID: + case SECRET_KEY_RING_BY_ROW_ID: + case SECRET_KEY_RING_BY_MASTER_KEY_ID: + case SECRET_KEY_RING_BY_KEY_ID: + return KeyRings.CONTENT_ITEM_TYPE; + + case PUBLIC_KEY_RING_KEY: + case SECRET_KEY_RING_KEY: + return Keys.CONTENT_TYPE; + + case PUBLIC_KEY_RING_KEY_BY_ROW_ID: + case SECRET_KEY_RING_KEY_BY_ROW_ID: + return Keys.CONTENT_ITEM_TYPE; + + case PUBLIC_KEY_RING_USER_ID: + case SECRET_KEY_RING_USER_ID: + return UserIds.CONTENT_TYPE; + + case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: + case SECRET_KEY_RING_USER_ID_BY_ROW_ID: + return UserIds.CONTENT_ITEM_TYPE; + + case API_APPS: + return ApiApps.CONTENT_TYPE; + + case API_APPS_BY_ROW_ID: + case API_APPS_BY_PACKAGE_NAME: + return ApiApps.CONTENT_ITEM_TYPE; + + default: + throw new UnsupportedOperationException("Unknown uri: " + uri); } } /** * Returns type of the query (secret/public) - * + * * @param uri * @return */ private int getKeyType(int match) { int type; switch (match) { - case PUBLIC_KEY_RING: - case PUBLIC_KEY_RING_BY_ROW_ID: - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - case PUBLIC_KEY_RING_KEY: - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case PUBLIC_KEY_RING_USER_ID: - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - type = KeyTypes.PUBLIC; - break; - - case SECRET_KEY_RING: - case SECRET_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_KEY_ID: - case SECRET_KEY_RING_BY_EMAILS: - case SECRET_KEY_RING_BY_LIKE_EMAIL: - case SECRET_KEY_RING_KEY: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - type = KeyTypes.SECRET; - break; - - default: - Log.e(Constants.TAG, "Unknown match " + match); - type = -1; - break; + case PUBLIC_KEY_RING: + case PUBLIC_KEY_RING_BY_ROW_ID: + case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: + case PUBLIC_KEY_RING_BY_KEY_ID: + case PUBLIC_KEY_RING_BY_EMAILS: + case PUBLIC_KEY_RING_BY_LIKE_EMAIL: + case PUBLIC_KEY_RING_KEY: + case PUBLIC_KEY_RING_KEY_BY_ROW_ID: + case PUBLIC_KEY_RING_USER_ID: + case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: + type = KeyTypes.PUBLIC; + break; + + case SECRET_KEY_RING: + case SECRET_KEY_RING_BY_ROW_ID: + case SECRET_KEY_RING_BY_MASTER_KEY_ID: + case SECRET_KEY_RING_BY_KEY_ID: + case SECRET_KEY_RING_BY_EMAILS: + case SECRET_KEY_RING_BY_LIKE_EMAIL: + case SECRET_KEY_RING_KEY: + case SECRET_KEY_RING_KEY_BY_ROW_ID: + case SECRET_KEY_RING_USER_ID: + case SECRET_KEY_RING_USER_ID_BY_ROW_ID: + type = KeyTypes.SECRET; + break; + + default: + Log.e(Constants.TAG, "Unknown match " + match); + type = -1; + break; } return type; } /** - * Set result of query to specific columns, don't show blob column for external content provider - * + * Set result of query to specific columns, don't show blob column + * * @return */ private HashMap<String, String> getProjectionMapForKeyRings() { HashMap<String, String> projectionMap = new HashMap<String, String>(); projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); - projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." - + KeyRingsColumns.MASTER_KEY_ID); projectionMap.put(KeyRingsColumns.KEY_RING_DATA, Tables.KEY_RINGS + "." + KeyRingsColumns.KEY_RING_DATA); + projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID); + // TODO: deprecated master key id + //projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.KEY_ID); + projectionMap.put(KeysColumns.FINGERPRINT, Tables.KEYS + "." + KeysColumns.FINGERPRINT); + projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID); return projectionMap; } /** - * Set result of query to specific columns, don't show blob column for external content provider - * + * Set result of query to specific columns, don't show blob column + * * @return */ private HashMap<String, String> getProjectionMapForKeys() { @@ -381,27 +388,26 @@ public class KeychainProvider extends ContentProvider { projectionMap.put(KeysColumns.KEY_RING_ROW_ID, KeysColumns.KEY_RING_ROW_ID); projectionMap.put(KeysColumns.KEY_DATA, KeysColumns.KEY_DATA); projectionMap.put(KeysColumns.RANK, KeysColumns.RANK); + projectionMap.put(KeysColumns.FINGERPRINT, KeysColumns.FINGERPRINT); return projectionMap; } /** - * Builds default query for keyRings: KeyRings table is joined with UserIds - * - * @param qb - * @param match - * @param isMasterKey - * @param sortOrder - * @return + * Builds default query for keyRings: KeyRings table is joined with UserIds and Keys */ - private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match, String sortOrder) { + private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match) { // public or secret keyring qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = "); qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - // join keyrings with userIds to every keyring - qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.USER_IDS + " ON " + "(" - + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "." + // join keyrings with keys and userIds + // Only get user id and key with rank 0 (main user id and main key) + qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" + + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." + + KeysColumns.KEY_RING_ROW_ID + " AND " + Tables.KEYS + "." + + KeysColumns.RANK + " = '0') " + " INNER JOIN " + Tables.USER_IDS + " ON " + + "(" + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.USER_IDS + "." + UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "." + UserIdsColumns.RANK + " = '0')"); @@ -411,16 +417,11 @@ public class KeychainProvider extends ContentProvider { } /** - * Builds default query for keyRings: KeyRings table is joined with Keys and UserIds - * - * @param qb - * @param match - * @param isMasterKey - * @param sortOrder - * @return + * Builds default query for keyRings: KeyRings table is joined with UserIds and Keys + * <p/> + * Here only one key should be selected in the query to return a single keyring! */ - private SQLiteQueryBuilder buildKeyRingQueryWithKeys(SQLiteQueryBuilder qb, int match, - String sortOrder) { + private SQLiteQueryBuilder buildKeyRingQueryWithSpecificKey(SQLiteQueryBuilder qb, int match) { // public or secret keyring qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = "); qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); @@ -438,11 +439,13 @@ public class KeychainProvider extends ContentProvider { return qb; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @SuppressWarnings("deprecation") @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { + String sortOrder) { Log.v(Constants.TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); @@ -451,169 +454,169 @@ public class KeychainProvider extends ContentProvider { int match = mUriMatcher.match(uri); switch (match) { - case PUBLIC_KEY_RING: - case SECRET_KEY_RING: - qb = buildKeyRingQuery(qb, match, sortOrder); + case PUBLIC_KEY_RING: + case SECRET_KEY_RING: + qb = buildKeyRingQuery(qb, match); - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } + if (TextUtils.isEmpty(sortOrder)) { + sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; + } - break; + break; - case PUBLIC_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_ROW_ID: - qb = buildKeyRingQuery(qb, match, sortOrder); + case PUBLIC_KEY_RING_BY_ROW_ID: + case SECRET_KEY_RING_BY_ROW_ID: + qb = buildKeyRingQuery(qb, match); - qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + BaseColumns._ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } + if (TextUtils.isEmpty(sortOrder)) { + sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; + } - break; + break; - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - qb = buildKeyRingQuery(qb, match, sortOrder); + case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: + case SECRET_KEY_RING_BY_MASTER_KEY_ID: + qb = buildKeyRingQuery(qb, match); - qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; + if (TextUtils.isEmpty(sortOrder)) { + sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; + } - case SECRET_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - qb = buildKeyRingQueryWithKeys(qb, match, sortOrder); + break; - qb.appendWhere(" AND " + Tables.KEYS + "." + KeysColumns.KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + case SECRET_KEY_RING_BY_KEY_ID: + case PUBLIC_KEY_RING_BY_KEY_ID: + qb = buildKeyRingQueryWithSpecificKey(qb, match); - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } + qb.appendWhere(" AND " + Tables.KEYS + "." + KeysColumns.KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); - break; + if (TextUtils.isEmpty(sortOrder)) { + sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; + } - case SECRET_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_EMAILS: - qb = buildKeyRingQuery(qb, match, sortOrder); + break; - String emails = uri.getLastPathSegment(); - String chunks[] = emails.split(" *, *"); - boolean gotCondition = false; - String emailWhere = ""; - for (int i = 0; i < chunks.length; ++i) { - if (chunks[i].length() == 0) { - continue; + case SECRET_KEY_RING_BY_EMAILS: + case PUBLIC_KEY_RING_BY_EMAILS: + qb = buildKeyRingQuery(qb, match); + + String emails = uri.getLastPathSegment(); + String chunks[] = emails.split(" *, *"); + boolean gotCondition = false; + String emailWhere = ""; + for (int i = 0; i < chunks.length; ++i) { + if (chunks[i].length() == 0) { + continue; + } + if (i != 0) { + emailWhere += " OR "; + } + emailWhere += "tmp." + UserIdsColumns.USER_ID + " LIKE "; + // match '*<email>', so it has to be at the *end* of the user id + emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">"); + gotCondition = true; } - if (i != 0) { - emailWhere += " OR "; - } - emailWhere += "tmp." + UserIdsColumns.USER_ID + " LIKE "; - // match '*<email>', so it has to be at the *end* of the user id - emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">"); - gotCondition = true; - } - if (gotCondition) { - qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM " - + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID - + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + emailWhere - + "))"); - } + if (gotCondition) { + qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM " + + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID + + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + emailWhere + + "))"); + } - break; + break; - case SECRET_KEY_RING_BY_LIKE_EMAIL: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - qb = buildKeyRingQuery(qb, match, sortOrder); + case SECRET_KEY_RING_BY_LIKE_EMAIL: + case PUBLIC_KEY_RING_BY_LIKE_EMAIL: + qb = buildKeyRingQuery(qb, match); - String likeEmail = uri.getLastPathSegment(); + String likeEmail = uri.getLastPathSegment(); - String likeEmailWhere = "tmp." + UserIdsColumns.USER_ID + " LIKE " - + DatabaseUtils.sqlEscapeString("%<%" + likeEmail + "%>"); + String likeEmailWhere = "tmp." + UserIdsColumns.USER_ID + " LIKE " + + DatabaseUtils.sqlEscapeString("%<%" + likeEmail + "%>"); - qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM " - + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID - + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + likeEmailWhere - + "))"); + qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM " + + Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_RING_ROW_ID + + " = " + Tables.KEY_RINGS + "." + BaseColumns._ID + " AND (" + likeEmailWhere + + "))"); - break; + break; - case PUBLIC_KEY_RING_KEY: - case SECRET_KEY_RING_KEY: - qb.setTables(Tables.KEYS); - qb.appendWhere(KeysColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); + case PUBLIC_KEY_RING_KEY: + case SECRET_KEY_RING_KEY: + qb.setTables(Tables.KEYS); + qb.appendWhere(KeysColumns.TYPE + " = "); + qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - qb.setProjectionMap(getProjectionMapForKeys()); + qb.setProjectionMap(getProjectionMapForKeys()); - break; + break; - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - qb.setTables(Tables.KEYS); - qb.appendWhere(KeysColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); + case PUBLIC_KEY_RING_KEY_BY_ROW_ID: + case SECRET_KEY_RING_KEY_BY_ROW_ID: + qb.setTables(Tables.KEYS); + qb.appendWhere(KeysColumns.TYPE + " = "); + qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - qb.appendWhere(" AND " + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + qb.appendWhere(" AND " + BaseColumns._ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); - qb.setProjectionMap(getProjectionMapForKeys()); + qb.setProjectionMap(getProjectionMapForKeys()); - break; + break; - case PUBLIC_KEY_RING_USER_ID: - case SECRET_KEY_RING_USER_ID: - qb.setTables(Tables.USER_IDS); - qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + case PUBLIC_KEY_RING_USER_ID: + case SECRET_KEY_RING_USER_ID: + qb.setTables(Tables.USER_IDS); + qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - break; + break; - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - qb.setTables(Tables.USER_IDS); - qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: + case SECRET_KEY_RING_USER_ID_BY_ROW_ID: + qb.setTables(Tables.USER_IDS); + qb.appendWhere(UserIdsColumns.KEY_RING_ROW_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - qb.appendWhere(" AND " + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + qb.appendWhere(" AND " + BaseColumns._ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); - break; + break; - case API_APPS: - qb.setTables(Tables.API_APPS); + case API_APPS: + qb.setTables(Tables.API_APPS); - break; - case API_APPS_BY_ROW_ID: - qb.setTables(Tables.API_APPS); + break; + case API_APPS_BY_ROW_ID: + qb.setTables(Tables.API_APPS); - qb.appendWhere(BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); + qb.appendWhere(BaseColumns._ID + " = "); + qb.appendWhereEscapeString(uri.getLastPathSegment()); - break; - case API_APPS_BY_PACKAGE_NAME: - qb.setTables(Tables.API_APPS); - qb.appendWhere(ApiApps.PACKAGE_NAME + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + break; + case API_APPS_BY_PACKAGE_NAME: + qb.setTables(Tables.API_APPS); + qb.appendWhere(ApiApps.PACKAGE_NAME + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - break; + break; - default: - throw new IllegalArgumentException("Unknown URI " + uri); + default: + throw new IllegalArgumentException("Unknown URI " + uri); } @@ -634,14 +637,16 @@ public class KeychainProvider extends ContentProvider { Log.d(Constants.TAG, "Query: " + qb.buildQuery(projection, selection, selectionArgs, null, null, - orderBy, null)); + orderBy, null)); Log.d(Constants.TAG, "Cursor: " + DatabaseUtils.dumpCursorToString(c)); } return c; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public Uri insert(Uri uri, ContentValues values) { Log.d(Constants.TAG, "insert(uri=" + uri + ", values=" + values.toString() + ")"); @@ -654,56 +659,56 @@ public class KeychainProvider extends ContentProvider { final int match = mUriMatcher.match(uri); switch (match) { - case PUBLIC_KEY_RING: - values.put(KeyRings.TYPE, KeyTypes.PUBLIC); - - rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); - rowUri = KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case PUBLIC_KEY_RING_KEY: - values.put(Keys.TYPE, KeyTypes.PUBLIC); - - rowId = db.insertOrThrow(Tables.KEYS, null, values); - rowUri = Keys.buildPublicKeysUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case PUBLIC_KEY_RING_USER_ID: - rowId = db.insertOrThrow(Tables.USER_IDS, null, values); - rowUri = UserIds.buildPublicUserIdsUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case SECRET_KEY_RING: - values.put(KeyRings.TYPE, KeyTypes.SECRET); - - rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); - rowUri = KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case SECRET_KEY_RING_KEY: - values.put(Keys.TYPE, KeyTypes.SECRET); - - rowId = db.insertOrThrow(Tables.KEYS, null, values); - rowUri = Keys.buildSecretKeysUri(Long.toString(rowId)); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - - break; - case SECRET_KEY_RING_USER_ID: - rowId = db.insertOrThrow(Tables.USER_IDS, null, values); - rowUri = UserIds.buildSecretUserIdsUri(Long.toString(rowId)); - - break; - case API_APPS: - rowId = db.insertOrThrow(Tables.API_APPS, null, values); - rowUri = ApiApps.buildIdUri(Long.toString(rowId)); - - break; - default: - throw new UnsupportedOperationException("Unknown uri: " + uri); + case PUBLIC_KEY_RING: + values.put(KeyRings.TYPE, KeyTypes.PUBLIC); + + rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); + rowUri = KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case PUBLIC_KEY_RING_KEY: + values.put(Keys.TYPE, KeyTypes.PUBLIC); + + rowId = db.insertOrThrow(Tables.KEYS, null, values); + rowUri = Keys.buildPublicKeysUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case PUBLIC_KEY_RING_USER_ID: + rowId = db.insertOrThrow(Tables.USER_IDS, null, values); + rowUri = UserIds.buildPublicUserIdsUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case SECRET_KEY_RING: + values.put(KeyRings.TYPE, KeyTypes.SECRET); + + rowId = db.insertOrThrow(Tables.KEY_RINGS, null, values); + rowUri = KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case SECRET_KEY_RING_KEY: + values.put(Keys.TYPE, KeyTypes.SECRET); + + rowId = db.insertOrThrow(Tables.KEYS, null, values); + rowUri = Keys.buildSecretKeysUri(Long.toString(rowId)); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case SECRET_KEY_RING_USER_ID: + rowId = db.insertOrThrow(Tables.USER_IDS, null, values); + rowUri = UserIds.buildSecretUserIdsUri(Long.toString(rowId)); + + break; + case API_APPS: + rowId = db.insertOrThrow(Tables.API_APPS, null, values); + rowUri = ApiApps.buildIdUri(Long.toString(rowId)); + + break; + default: + throw new UnsupportedOperationException("Unknown uri: " + uri); } // notify of changes in db @@ -716,7 +721,9 @@ public class KeychainProvider extends ContentProvider { return rowUri; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { Log.v(Constants.TAG, "delete(uri=" + uri + ")"); @@ -728,113 +735,115 @@ public class KeychainProvider extends ContentProvider { String defaultSelection = null; switch (match) { - case PUBLIC_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_ROW_ID: - defaultSelection = BaseColumns._ID + "=" + uri.getLastPathSegment(); - // corresponding keys and userIds are deleted by ON DELETE CASCADE - count = db.delete(Tables.KEY_RINGS, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), - selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - defaultSelection = KeyRings.MASTER_KEY_ID + "=" + uri.getLastPathSegment(); - // corresponding keys and userIds are deleted by ON DELETE CASCADE - count = db.delete(Tables.KEY_RINGS, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), - selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; - case PUBLIC_KEY_RING_KEY_BY_ROW_ID: - case SECRET_KEY_RING_KEY_BY_ROW_ID: - count = db.delete(Tables.KEYS, - buildDefaultKeysSelection(uri, getKeyType(match), selection), selectionArgs); - sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; - case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: - case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - count = db.delete(Tables.KEYS, buildDefaultUserIdsSelection(uri, selection), - selectionArgs); - break; - case API_APPS_BY_ROW_ID: - count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, false, selection), - selectionArgs); - break; - case API_APPS_BY_PACKAGE_NAME: - count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, true, selection), - selectionArgs); - break; - default: - throw new UnsupportedOperationException("Unknown uri: " + uri); - } - - // notify of changes in db - getContext().getContentResolver().notifyChange(uri, null); - - return count; - } - - /** {@inheritDoc} */ - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - Log.v(Constants.TAG, "update(uri=" + uri + ", values=" + values.toString() + ")"); - - final SQLiteDatabase db = mApgDatabase.getWritableDatabase(); - - String defaultSelection = null; - int count = 0; - try { - final int match = mUriMatcher.match(uri); - switch (match) { case PUBLIC_KEY_RING_BY_ROW_ID: case SECRET_KEY_RING_BY_ROW_ID: defaultSelection = BaseColumns._ID + "=" + uri.getLastPathSegment(); - - count = db.update( - Tables.KEY_RINGS, - values, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), - selection), selectionArgs); + // corresponding keys and userIds are deleted by ON DELETE CASCADE + count = db.delete(Tables.KEY_RINGS, + buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), + selectionArgs); sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: case SECRET_KEY_RING_BY_MASTER_KEY_ID: defaultSelection = KeyRings.MASTER_KEY_ID + "=" + uri.getLastPathSegment(); - - count = db.update( - Tables.KEY_RINGS, - values, - buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), - selection), selectionArgs); + // corresponding keys and userIds are deleted by ON DELETE CASCADE + count = db.delete(Tables.KEY_RINGS, + buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), selection), + selectionArgs); sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; case PUBLIC_KEY_RING_KEY_BY_ROW_ID: case SECRET_KEY_RING_KEY_BY_ROW_ID: - count = db - .update(Tables.KEYS, values, - buildDefaultKeysSelection(uri, getKeyType(match), selection), - selectionArgs); + count = db.delete(Tables.KEYS, + buildDefaultKeysSelection(uri, getKeyType(match), selection), selectionArgs); sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); - break; case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: case SECRET_KEY_RING_USER_ID_BY_ROW_ID: - count = db.update(Tables.USER_IDS, values, - buildDefaultUserIdsSelection(uri, selection), selectionArgs); + count = db.delete(Tables.KEYS, buildDefaultUserIdsSelection(uri, selection), + selectionArgs); break; case API_APPS_BY_ROW_ID: - count = db.update(Tables.API_APPS, values, - buildDefaultApiAppsSelection(uri, false, selection), selectionArgs); + count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, false, selection), + selectionArgs); break; case API_APPS_BY_PACKAGE_NAME: - count = db.update(Tables.API_APPS, values, - buildDefaultApiAppsSelection(uri, true, selection), selectionArgs); + count = db.delete(Tables.API_APPS, buildDefaultApiAppsSelection(uri, true, selection), + selectionArgs); break; default: throw new UnsupportedOperationException("Unknown uri: " + uri); + } + + // notify of changes in db + getContext().getContentResolver().notifyChange(uri, null); + + return count; + } + + /** + * {@inheritDoc} + */ + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + Log.v(Constants.TAG, "update(uri=" + uri + ", values=" + values.toString() + ")"); + + final SQLiteDatabase db = mApgDatabase.getWritableDatabase(); + + String defaultSelection = null; + int count = 0; + try { + final int match = mUriMatcher.match(uri); + switch (match) { + case PUBLIC_KEY_RING_BY_ROW_ID: + case SECRET_KEY_RING_BY_ROW_ID: + defaultSelection = BaseColumns._ID + "=" + uri.getLastPathSegment(); + + count = db.update( + Tables.KEY_RINGS, + values, + buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), + selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: + case SECRET_KEY_RING_BY_MASTER_KEY_ID: + defaultSelection = KeyRings.MASTER_KEY_ID + "=" + uri.getLastPathSegment(); + + count = db.update( + Tables.KEY_RINGS, + values, + buildDefaultKeyRingsSelection(defaultSelection, getKeyType(match), + selection), selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case PUBLIC_KEY_RING_KEY_BY_ROW_ID: + case SECRET_KEY_RING_KEY_BY_ROW_ID: + count = db + .update(Tables.KEYS, values, + buildDefaultKeysSelection(uri, getKeyType(match), selection), + selectionArgs); + sendBroadcastDatabaseChange(getKeyType(match), getType(uri)); + + break; + case PUBLIC_KEY_RING_USER_ID_BY_ROW_ID: + case SECRET_KEY_RING_USER_ID_BY_ROW_ID: + count = db.update(Tables.USER_IDS, values, + buildDefaultUserIdsSelection(uri, selection), selectionArgs); + break; + case API_APPS_BY_ROW_ID: + count = db.update(Tables.API_APPS, values, + buildDefaultApiAppsSelection(uri, false, selection), selectionArgs); + break; + case API_APPS_BY_PACKAGE_NAME: + count = db.update(Tables.API_APPS, values, + buildDefaultApiAppsSelection(uri, true, selection), selectionArgs); + break; + default: + throw new UnsupportedOperationException("Unknown uri: " + uri); } // notify of changes in db @@ -850,13 +859,13 @@ public class KeychainProvider extends ContentProvider { /** * Build default selection statement for KeyRings. If no extra selection is specified only build * where clause with rowId - * + * * @param uri * @param selection * @return */ private String buildDefaultKeyRingsSelection(String defaultSelection, Integer keyType, - String selection) { + String selection) { String andType = ""; if (keyType != null) { andType = " AND " + KeyRingsColumns.TYPE + "=" + keyType; @@ -873,7 +882,7 @@ public class KeychainProvider extends ContentProvider { /** * Build default selection statement for Keys. If no extra selection is specified only build * where clause with rowId - * + * * @param uri * @param selection * @return @@ -901,7 +910,7 @@ public class KeychainProvider extends ContentProvider { /** * Build default selection statement for UserIds. If no extra selection is specified only build * where clause with rowId - * + * * @param uri * @param selection * @return @@ -924,7 +933,7 @@ public class KeychainProvider extends ContentProvider { /** * Build default selection statement for API apps. If no extra selection is specified only build * where clause with rowId - * + * * @param uri * @param selection * @return diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 10404e0ff..a4992163a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -23,6 +23,8 @@ import java.util.ArrayList; import java.util.Date; import org.spongycastle.bcpg.ArmoredOutputStream; +import org.spongycastle.bcpg.UserAttributePacket; +import org.spongycastle.bcpg.UserAttributeSubpacket; import org.spongycastle.openpgp.PGPKeyRing; import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPPublicKeyRing; @@ -55,10 +57,6 @@ public class ProviderHelper { /** * Private helper method to get PGPKeyRing from database - * - * @param context - * @param queryUri - * @return */ public static PGPKeyRing getPGPKeyRing(Context context, Uri queryUri) { Cursor cursor = context.getContentResolver().query(queryUri, @@ -83,10 +81,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPPublicKeyRing object from the database blob based on the rowId - * - * @param context - * @param rowId - * @return */ public static PGPPublicKeyRing getPGPPublicKeyRingByRowId(Context context, long rowId) { Uri queryUri = KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)); @@ -95,10 +89,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPPublicKeyRing object from the database blob based on the maserKeyId - * - * @param context - * @param masterKeyId - * @return */ public static PGPPublicKeyRing getPGPPublicKeyRingByMasterKeyId(Context context, long masterKeyId) { @@ -109,10 +99,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPPublicKeyRing object from the database blob associated with a key * with this keyId - * - * @param context - * @param keyId - * @return */ public static PGPPublicKeyRing getPGPPublicKeyRingByKeyId(Context context, long keyId) { Uri queryUri = KeyRings.buildPublicKeyRingsByKeyIdUri(Long.toString(keyId)); @@ -122,10 +108,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPPublicKey object from the database blob associated with a key with * this keyId - * - * @param context - * @param keyId - * @return */ public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) { PGPPublicKeyRing keyRing = getPGPPublicKeyRingByKeyId(context, keyId); @@ -138,10 +120,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPSecretKeyRing object from the database blob based on the rowId - * - * @param context - * @param rowId - * @return */ public static PGPSecretKeyRing getPGPSecretKeyRingByRowId(Context context, long rowId) { Uri queryUri = KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); @@ -150,10 +128,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPSecretKeyRing object from the database blob based on the maserKeyId - * - * @param context - * @param masterKeyId - * @return */ public static PGPSecretKeyRing getPGPSecretKeyRingByMasterKeyId(Context context, long masterKeyId) { @@ -164,10 +138,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPSecretKeyRing object from the database blob associated with a key * with this keyId - * - * @param context - * @param keyId - * @return */ public static PGPSecretKeyRing getPGPSecretKeyRingByKeyId(Context context, long keyId) { Uri queryUri = KeyRings.buildSecretKeyRingsByKeyIdUri(Long.toString(keyId)); @@ -177,10 +147,6 @@ public class ProviderHelper { /** * Retrieves the actual PGPSecretKey object from the database blob associated with a key with * this keyId - * - * @param context - * @param keyId - * @return */ public static PGPSecretKey getPGPSecretKeyByKeyId(Context context, long keyId) { PGPSecretKeyRing keyRing = getPGPSecretKeyRingByKeyId(context, keyId); @@ -193,12 +159,6 @@ public class ProviderHelper { /** * Saves PGPPublicKeyRing with its keys and userIds in DB - * - * @param context - * @param keyRing - * @return - * @throws IOException - * @throws GeneralException */ @SuppressWarnings("unchecked") public static void saveKeyRing(Context context, PGPPublicKeyRing keyRing) throws IOException { @@ -263,12 +223,6 @@ public class ProviderHelper { /** * Saves PGPSecretKeyRing with its keys and userIds in DB - * - * @param context - * @param keyRing - * @return - * @throws IOException - * @throws GeneralException */ @SuppressWarnings("unchecked") public static void saveKeyRing(Context context, PGPSecretKeyRing keyRing) throws IOException { @@ -333,13 +287,6 @@ public class ProviderHelper { /** * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing - * - * @param context - * @param keyRingRowId - * @param key - * @param rank - * @return - * @throws IOException */ private static ContentProviderOperation buildPublicKeyOperations(Context context, long keyRingRowId, PGPPublicKey key, int rank) throws IOException { @@ -359,6 +306,7 @@ public class ProviderHelper { values.put(Keys.KEY_RING_ROW_ID, keyRingRowId); values.put(Keys.KEY_DATA, key.getEncoded()); values.put(Keys.RANK, rank); + values.put(Keys.FINGERPRINT, key.getFingerprint()); Uri uri = Keys.buildPublicKeysUri(Long.toString(keyRingRowId)); @@ -367,13 +315,6 @@ public class ProviderHelper { /** * Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing - * - * @param context - * @param keyRingRowId - * @param key - * @param rank - * @return - * @throws IOException */ private static ContentProviderOperation buildPublicUserIdOperations(Context context, long keyRingRowId, String userId, int rank) { @@ -389,13 +330,6 @@ public class ProviderHelper { /** * Build ContentProviderOperation to add PGPSecretKey to database corresponding to a keyRing - * - * @param context - * @param keyRingRowId - * @param key - * @param rank - * @return - * @throws IOException */ private static ContentProviderOperation buildSecretKeyOperations(Context context, long keyRingRowId, PGPSecretKey key, int rank) throws IOException { @@ -424,6 +358,7 @@ public class ProviderHelper { values.put(Keys.KEY_RING_ROW_ID, keyRingRowId); values.put(Keys.KEY_DATA, key.getEncoded()); values.put(Keys.RANK, rank); + values.put(Keys.FINGERPRINT, key.getPublicKey().getFingerprint()); Uri uri = Keys.buildSecretKeysUri(Long.toString(keyRingRowId)); @@ -432,13 +367,6 @@ public class ProviderHelper { /** * Build ContentProviderOperation to add SecretUserIds to database corresponding to a keyRing - * - * @param context - * @param keyRingRowId - * @param key - * @param rank - * @return - * @throws IOException */ private static ContentProviderOperation buildSecretUserIdOperations(Context context, long keyRingRowId, String userId, int rank) { @@ -454,10 +382,6 @@ public class ProviderHelper { /** * Private helper method - * - * @param context - * @param queryUri - * @return */ private static ArrayList<Long> getKeyRingsMasterKeyIds(Context context, Uri queryUri) { Cursor cursor = context.getContentResolver().query(queryUri, @@ -482,9 +406,6 @@ public class ProviderHelper { /** * Retrieves ids of all SecretKeyRings - * - * @param context - * @return */ public static ArrayList<Long> getSecretKeyRingsMasterKeyIds(Context context) { Uri queryUri = KeyRings.buildSecretKeyRingsUri(); @@ -493,9 +414,6 @@ public class ProviderHelper { /** * Retrieves ids of all PublicKeyRings - * - * @param context - * @return */ public static ArrayList<Long> getPublicKeyRingsMasterKeyIds(Context context) { Uri queryUri = KeyRings.buildPublicKeyRingsUri(); @@ -514,10 +432,6 @@ public class ProviderHelper { /** * Get master key id of keyring by its row id - * - * @param context - * @param keyRingRowId - * @return */ public static long getPublicMasterKeyId(Context context, long keyRingRowId) { Uri queryUri = KeyRings.buildPublicKeyRingsUri(String.valueOf(keyRingRowId)); @@ -526,10 +440,6 @@ public class ProviderHelper { /** * Get empty status of master key of keyring by its row id - * - * @param context - * @param keyRingRowId - * @return */ public static boolean getSecretMasterKeyCanSign(Context context, long keyRingRowId) { Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId)); @@ -538,11 +448,6 @@ public class ProviderHelper { /** * Private helper method to get master key private empty status of keyring by its row id - * - * @param context - * @param queryUri - * @param keyRingRowId - * @return */ private static boolean getMasterKeyCanSign(Context context, Uri queryUri, long keyRingRowId) { String[] projection = new String[]{ @@ -572,10 +477,6 @@ public class ProviderHelper { /** * Get master key id of keyring by its row id - * - * @param context - * @param keyRingRowId - * @return */ public static long getSecretMasterKeyId(Context context, long keyRingRowId) { Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId)); @@ -583,41 +484,84 @@ public class ProviderHelper { } /** - * Private helper method to get master key id of keyring by its row id - * - * @param context - * @param queryUri - * @param keyRingRowId - * @return + * Get master key id of key */ public static long getMasterKeyId(Context context, Uri queryUri) { String[] projection = new String[]{KeyRings.MASTER_KEY_ID}; + Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null); - ContentResolver cr = context.getContentResolver(); - Cursor cursor = cr.query(queryUri, projection, null, null, null); - - long masterKeyId = -1; - if (cursor != null && cursor.moveToFirst()) { - int masterKeyIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID); - - masterKeyId = cursor.getLong(masterKeyIdCol); - } + long masterKeyId = 0; + try { + if (cursor != null && cursor.moveToFirst()) { + int masterKeyIdCol = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID); - if (cursor != null) { - cursor.close(); + masterKeyId = cursor.getLong(masterKeyIdCol); + } + } finally { + if (cursor != null) { + cursor.close(); + } } return masterKeyId; } - public static ArrayList<String> getPublicKeyRingsAsArmoredString(Context context, - long[] masterKeyIds) { - return getKeyRingsAsArmoredString(context, KeyRings.buildPublicKeyRingsUri(), masterKeyIds); - } + /** + * Get fingerprint of key + */ + public static byte[] getFingerprint(Context context, Uri queryUri) { + String[] projection = new String[]{Keys.FINGERPRINT}; + Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null); + + byte[] fingerprint = null; + try { + if (cursor != null && cursor.moveToFirst()) { + int col = cursor.getColumnIndexOrThrow(Keys.FINGERPRINT); - public static ArrayList<String> getSecretKeyRingsAsArmoredString(Context context, - long[] masterKeyIds) { - return getKeyRingsAsArmoredString(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds); + fingerprint = cursor.getBlob(col); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + + // FALLBACK: If fingerprint is not in database, get it from key blob! + // this could happen if the key was saved by a previous version of Keychain! + if (fingerprint == null) { + Log.d(Constants.TAG, "FALLBACK: fingerprint is not in database, get it from key blob!"); + + // get master key id + projection = new String[]{KeyRings.MASTER_KEY_ID}; + cursor = context.getContentResolver().query(queryUri, projection, null, null, null); + long masterKeyId = 0; + try { + if (cursor != null && cursor.moveToFirst()) { + int col = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID); + + masterKeyId = cursor.getLong(col); + } + } finally { + if (cursor != null) { + cursor.close(); + } + } + + PGPPublicKey key = ProviderHelper.getPGPPublicKeyByKeyId(context, masterKeyId); + // if it is no public key get it from your own keys... + if (key == null) { + PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyByKeyId(context, masterKeyId); + if (secretKey == null) { + Log.e(Constants.TAG, "Key could not be found!"); + return null; + } + key = secretKey.getPublicKey(); + } + + fingerprint = key.getFingerprint(); + } + + return fingerprint; } public static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri, @@ -681,14 +625,6 @@ public class ProviderHelper { } } - public static byte[] getPublicKeyRingsAsByteArray(Context context, long[] masterKeyIds) { - return getKeyRingsAsByteArray(context, KeyRings.buildPublicKeyRingsUri(), masterKeyIds); - } - - public static byte[] getSecretKeyRingsAsByteArray(Context context, long[] masterKeyIds) { - return getKeyRingsAsByteArray(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds); - } - public static byte[] getKeyRingsAsByteArray(Context context, Uri uri, long[] masterKeyIds) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java index 170b946d2..5a338c757 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java @@ -69,12 +69,12 @@ public class KeychainIntentServiceHandler extends Handler { switch (message.arg1) { case MESSAGE_OKAY: - mProgressDialogFragment.dismiss(); + mProgressDialogFragment.dismissAllowingStateLoss(); break; case MESSAGE_EXCEPTION: - mProgressDialogFragment.dismiss(); + mProgressDialogFragment.dismissAllowingStateLoss(); // show error from service if (data.containsKey(DATA_ERROR)) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 1be5b8548..26ebc8e79 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -35,6 +36,7 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NfcAdapter; import android.os.Bundle; @@ -56,6 +58,8 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi 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"; + public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = Constants.INTENT_PREFIX + + "IMPORT_KEY_FROM_KEYSERVER"; // Actions for internal use only: public static final String ACTION_IMPORT_KEY_FROM_FILE = Constants.INTENT_PREFIX @@ -63,24 +67,19 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi public static final String ACTION_IMPORT_KEY_FROM_NFC = Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_NFC"; - // only used by IMPORT + // only used by ACTION_IMPORT_KEY public static final String EXTRA_KEY_BYTES = "key_bytes"; - // TODO: import keys from server - // public static final String EXTRA_KEY_ID = "keyId"; + // only used by ACTION_IMPORT_KEY_FROM_KEYSERVER + public static final String EXTRA_QUERY = "query"; protected boolean mDeleteAfterImport = false; - FileDialogFragment mFileDialog; - ImportKeysListFragment mListFragment; - OnNavigationListener mOnNavigationListener; - String[] mNavigationStrings; - - Fragment mCurrentFragment; - - BootstrapButton mImportButton; - - // BootstrapButton mImportSignUploadButton; + // view + private ImportKeysListFragment mListFragment; + private String[] mNavigationStrings; + private Fragment mCurrentFragment; + private BootstrapButton mImportButton; @Override protected void onCreate(Bundle savedInstanceState) { @@ -95,21 +94,11 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi importKeys(); } }); - // mImportSignUploadButton = (BootstrapButton) findViewById(R.id.import_sign_and_upload); - // mImportSignUploadButton.setOnClickListener(new OnClickListener() { - // @Override - // public void onClick(View v) { - // signAndUploadOnClick(); - // } - // }); getSupportActionBar().setDisplayShowTitleEnabled(false); setupDrawerNavigation(savedInstanceState); - // set actionbar without home button if called from another app - // ActionBarHelper.setBackButton(this); - // set drop down navigation mNavigationStrings = getResources().getStringArray(R.array.import_action_list); Context context = getSupportActionBar().getThemedContext(); @@ -125,6 +114,8 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi protected void handleActions(Bundle savedInstanceState, Intent intent) { String action = intent.getAction(); Bundle extras = intent.getExtras(); + Uri dataUri = intent.getData(); + String scheme = intent.getScheme(); if (extras == null) { extras = new Bundle(); @@ -140,6 +131,15 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi } /** + * Scanning a fingerprint directly with Barcode Scanner + */ + if (scheme != null && scheme.toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) { + getSupportActionBar().setSelectedNavigationItem(0); + loadFragment(ImportKeysQrCodeFragment.class, null, mNavigationStrings[0]); + loadFromFingerprintUri(dataUri); + } + + /** * Keychain's own Actions */ if (ACTION_IMPORT_KEY.equals(action)) { @@ -160,14 +160,25 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi // directly load data startListFragment(savedInstanceState, importData, null); } + } else if (ACTION_IMPORT_KEY_FROM_KEYSERVER.equals(action)) { + if (!extras.containsKey(EXTRA_QUERY)) { + Log.e(Constants.TAG, "IMPORT_KEY_FROM_KEYSERVER action needs to contain the 'query' extra!"); + return; + } + + String query = extras.getString(EXTRA_QUERY); + + // TODO: implement KEYSERVER! + } else { - // Internal actions + // Other actions startListFragment(savedInstanceState, null, null); if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { getSupportActionBar().setSelectedNavigationItem(1); loadFragment(ImportKeysFileFragment.class, null, mNavigationStrings[1]); } else if (ACTION_IMPORT_KEY_FROM_QR_CODE.equals(action)) { + // also exposed in AndroidManifest getSupportActionBar().setSelectedNavigationItem(2); loadFragment(ImportKeysQrCodeFragment.class, null, mNavigationStrings[2]); } else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) { @@ -239,6 +250,23 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi ft.commit(); } + public void loadFromFingerprintUri(Uri dataUri) { + String fingerprint = dataUri.toString().split(":")[1].toLowerCase(Locale.ENGLISH); + + Log.d(Constants.TAG, "fingerprint: " + fingerprint); + + if (fingerprint.length() < 16) { + Toast.makeText(this, R.string.import_qr_code_too_short_fingerprint, + Toast.LENGTH_LONG).show(); + return; + } + + Intent queryIntent = new Intent(this, KeyServerQueryActivity.class); + queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); + queryIntent.putExtra(KeyServerQueryActivity.EXTRA_FINGERPRINT, fingerprint); + startActivity(queryIntent); + } + public void loadCallback(byte[] importData, String importFilename) { mListFragment.loadNew(importData, importFilename); } @@ -413,19 +441,6 @@ public class ImportKeysActivity extends DrawerActivity implements OnNavigationLi } } - public void importOnClick() { - importKeys(); - } - - // public void signAndUploadOnClick() { - // // first, import! - // // importOnClick(view); - // - // // TODO: implement sign and upload! - // Toast.makeText(ImportKeysActivity.this, "Not implemented right now!", Toast.LENGTH_SHORT) - // .show(); - // } - /** * NFC */ diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java index 3ede641d3..e714c231d 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java @@ -26,6 +26,7 @@ import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4; import org.sufficientlysecure.keychain.util.Log; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -101,8 +102,8 @@ public class ImportKeysQrCodeFragment extends Fragment { Log.d(Constants.TAG, "scanResult content: " + scanResult.getContents()); // look if it's fingerprint only - if (scanResult.getContents().toLowerCase(Locale.ENGLISH).startsWith("openpgp4fpr")) { - importFingerprint(scanResult.getContents().toLowerCase(Locale.ENGLISH)); + if (scanResult.getContents().toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) { + importFingerprint(Uri.parse(scanResult.getContents())); return; } @@ -128,21 +129,8 @@ public class ImportKeysQrCodeFragment extends Fragment { } } - private void importFingerprint(String uri) { - String fingerprint = uri.split(":")[1]; - - Log.d(Constants.TAG, "fingerprint: " + fingerprint); - - if (fingerprint.length() < 16) { - Toast.makeText(getActivity(), R.string.import_qr_code_too_short_fingerprint, - Toast.LENGTH_LONG).show(); - return; - } - - Intent queryIntent = new Intent(getActivity(), KeyServerQueryActivity.class); - queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID); - queryIntent.putExtra(KeyServerQueryActivity.EXTRA_FINGERPRINT, fingerprint); - startActivity(queryIntent); + public void importFingerprint(Uri dataUri) { + mImportActivity.loadFromFingerprintUri(dataUri); } private void importParts(String[] parts) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java index c985f1f60..5d8885e2f 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java @@ -32,10 +32,12 @@ import com.beardedhen.androidbootstrap.BootstrapButton; public class ImportKeysServerFragment extends Fragment { private BootstrapButton mButton; + String mQuery; + /** * Creates new instance of this fragment */ - public static ImportKeysServerFragment newInstance() { + public static ImportKeysServerFragment newInstance(String query) { ImportKeysServerFragment frag = new ImportKeysServerFragment(); Bundle args = new Bundle(); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index bb43719a6..638036701 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -21,8 +21,6 @@ package org.sufficientlysecure.keychain.ui; import java.util.ArrayList; import java.util.Date; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; @@ -198,12 +196,9 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements @Override public void onClick(View v) { - // TODO: don't get object here!!! solve this differently! - PGPPublicKeyRing ring = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing( - ViewKeyActivity.this, mDataUri); - PGPPublicKey publicKey = ring.getPublicKey(); + long keyId = ProviderHelper.getMasterKeyId(ViewKeyActivity.this, mDataUri); - long[] encryptionKeyIds = new long[]{publicKey.getKeyID()}; + long[] encryptionKeyIds = new long[]{keyId}; Intent intent = new Intent(ViewKeyActivity.this, EncryptActivity.class); intent.setAction(EncryptActivity.ACTION_ENCRYPT); intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds); @@ -248,7 +243,7 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements static final String[] KEYS_PROJECTION = new String[]{Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM, Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, - Keys.CAN_ENCRYPT, Keys.CREATION, Keys.EXPIRY}; + Keys.CAN_ENCRYPT, Keys.CREATION, Keys.EXPIRY, Keys.FINGERPRINT}; static final String KEYS_SORT_ORDER = Keys.RANK + " ASC"; static final int KEYS_INDEX_ID = 0; static final int KEYS_INDEX_KEY_ID = 1; @@ -260,6 +255,7 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements static final int KEYS_INDEX_CAN_ENCRYPT = 7; static final int KEYS_INDEX_CREATION = 8; static final int KEYS_INDEX_EXPIRY = 9; + static final int KEYS_INDEX_FINGERPRINT = 10; public Loader<Cursor> onCreateLoader(int id, Bundle args) { switch (id) { @@ -300,7 +296,7 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements // get name, email, and comment from USER_ID String[] mainUserId = PgpKeyHelper.splitUserId(data .getString(KEYRING_INDEX_USER_ID)); - if (mainUserId[0] != null && mainUserId[0].length() > 0) { + if (mainUserId[0] != null) { setTitle(mainUserId[0]); mName.setText(mainUserId[0]); } else { @@ -348,13 +344,15 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements data.getInt(KEYS_INDEX_ALGORITHM), data.getInt(KEYS_INDEX_KEY_SIZE)); mAlgorithm.setText(algorithmStr); - // TODO: Can this be done better? fingerprint in db? - String fingerprint = PgpKeyHelper.getFingerPrint(this, keyId); + byte[] fingerprintBlob = data.getBlob(KEYS_INDEX_FINGERPRINT); + if (fingerprintBlob == null) { + // FALLBACK for old databases + fingerprintBlob = ProviderHelper.getFingerprint(this, mDataUri); + } + String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob, true); fingerprint = fingerprint.replace(" ", "\n"); - mFingerprint.setText(fingerprint); - // TODO: get image with getUserAttributes() on key and then - // PGPUserAttributeSubpacketVector + mFingerprint.setText(fingerprint); } mKeysAdapter.swapCursor(data); @@ -392,13 +390,8 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements } private void updateFromKeyserver(Uri dataUri) { - long updateKeyId = 0; - PGPPublicKeyRing updateRing = (PGPPublicKeyRing) ProviderHelper - .getPGPKeyRing(this, dataUri); + long updateKeyId = ProviderHelper.getMasterKeyId(ViewKeyActivity.this, mDataUri); - if (updateRing != null) { - updateKeyId = PgpKeyHelper.getMasterKey(updateRing).getKeyID(); - } if (updateKeyId == 0) { Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!"); return; @@ -421,14 +414,10 @@ public class ViewKeyActivity extends SherlockFragmentActivity implements private void shareKey(Uri dataUri, boolean fingerprintOnly) { String content = null; if (fingerprintOnly) { - long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); - - // TODO: dublicated in ShareQrCodeDialog - content = "openpgp4fpr:"; - - String fingerprint = PgpKeyHelper.convertKeyToHex(masterKeyId); + byte[] fingerprintBlob = ProviderHelper.getFingerprint(this, dataUri); + String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob, false); - content = content + fingerprint; + content = Constants.FINGERPRINT_SCHEME + fingerprint; } else { // get public keyring as ascii armored string long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 6229e5202..8170defe4 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -93,26 +93,24 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> { // main user id String userId = entry.userIds.get(0); - if (userId != null) { - String[] userIdSplit = PgpKeyHelper.splitUserId(userId); - - // name - if (userIdSplit[0] != null && userIdSplit[0].length() > 0) { - // show red user id if it is a secret key - if (entry.secretKey) { - userIdSplit[0] = mActivity.getString(R.string.secret_key) + " " + userIdSplit[0]; - mainUserId.setTextColor(Color.RED); - } - mainUserId.setText(userIdSplit[0]); + String[] userIdSplit = PgpKeyHelper.splitUserId(userId); + + // name + if (userIdSplit[0] != null) { + // show red user id if it is a secret key + if (entry.secretKey) { + userIdSplit[0] = mActivity.getString(R.string.secret_key) + " " + userIdSplit[0]; + mainUserId.setTextColor(Color.RED); } + mainUserId.setText(userIdSplit[0]); + } - // email - if (userIdSplit[1] != null && userIdSplit[1].length() > 0) { - mainUserIdRest.setText(userIdSplit[1]); - mainUserIdRest.setVisibility(View.VISIBLE); - } else { - mainUserIdRest.setVisibility(View.GONE); - } + // email + if (userIdSplit[1] != null) { + mainUserIdRest.setText(userIdSplit[1]); + mainUserIdRest.setVisibility(View.VISIBLE); + } else { + mainUserIdRest.setVisibility(View.GONE); } keyId.setText(entry.hexKeyId); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java index 1a100a585..3ad82ea0b 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListEntry.java @@ -83,7 +83,7 @@ public class ImportKeysListEntry implements Serializable { this.revoked = pgpKeyRing.getPublicKey().isRevoked(); this.fingerPrint = PgpKeyHelper.convertFingerprintToHex(pgpKeyRing.getPublicKey() - .getFingerprint()); + .getFingerprint(), true); this.hexKeyId = PgpKeyHelper.convertKeyIdToHex(keyId); this.bitStrength = pgpKeyRing.getPublicKey().getBitStrength(); int algorithm = pgpKeyRing.getPublicKey().getAlgorithm(); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java index d852c16a8..f0e926655 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java @@ -89,16 +89,13 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea mainUserIdRest.setText(""); String userId = cursor.getString(mIndexUserId); - if (userId != null) { - String[] userIdSplit = PgpKeyHelper.splitUserId(userId); + String[] userIdSplit = PgpKeyHelper.splitUserId(userId); - if (userIdSplit[0] != null && userIdSplit[0].length() > 0) { - mainUserId.setText(userIdSplit[0]); - } - - if (userIdSplit[1] != null && userIdSplit[1].length() > 0) { - mainUserIdRest.setText(userIdSplit[1]); - } + if (userIdSplit[0] != null) { + mainUserId.setText(userIdSplit[0]); + } + if (userIdSplit[1] != null) { + mainUserIdRest.setText(userIdSplit[1]); } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java index ec087b46c..ce9b48bff 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java @@ -76,16 +76,13 @@ public class KeyListSecretAdapter extends CursorAdapter { mainUserIdRest.setText(""); String userId = cursor.getString(mIndexUserId); - if (userId != null) { - String[] userIdSplit = PgpKeyHelper.splitUserId(userId); + String[] userIdSplit = PgpKeyHelper.splitUserId(userId); - if (userIdSplit[0] != null && userIdSplit[0].length() > 0) { - mainUserId.setText(userIdSplit[0]); - } - - if (userIdSplit[1] != null && userIdSplit[1].length() > 0) { - mainUserIdRest.setText(userIdSplit[1]); - } + if (userIdSplit[0] != null) { + mainUserId.setText(userIdSplit[0]); + } + if (userIdSplit[1] != null) { + mainUserIdRest.setText(userIdSplit[1]); } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java index 54c334fd5..7e01faf9b 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java @@ -105,16 +105,13 @@ public class SelectKeyCursorAdapter extends CursorAdapter { status.setText(R.string.unknown_status); String userId = cursor.getString(mIndexUserId); - if (userId != null) { - String[] userIdSplit = PgpKeyHelper.splitUserId(userId); + String[] userIdSplit = PgpKeyHelper.splitUserId(userId); - if (userIdSplit[0] != null && userIdSplit[0].length() > 0) { - mainUserId.setText(userIdSplit[0]); - } - - if (userIdSplit[1] != null && userIdSplit[1].length() > 0) { - mainUserIdRest.setText(userIdSplit[1]); - } + if (userIdSplit[0] != null) { + mainUserId.setText(userIdSplit[0]); + } + if (userIdSplit[1] != null) { + mainUserIdRest.setText(userIdSplit[1]); } long masterKeyId = cursor.getLong(mIndexMasterKeyId); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java index 771816bfc..833f9714d 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java @@ -40,12 +40,14 @@ import android.widget.TextView; import com.actionbarsherlock.app.SherlockDialogFragment; public class ShareQrCodeDialogFragment extends SherlockDialogFragment { - private static final String ARG_URI = "uri"; + private static final String ARG_KEY_URI = "uri"; private static final String ARG_FINGERPRINT_ONLY = "fingerprint_only"; private ImageView mImage; private TextView mText; + private boolean mFingerprintOnly; + private ArrayList<String> mContentList; private int mCounter; @@ -53,15 +55,11 @@ public class ShareQrCodeDialogFragment extends SherlockDialogFragment { /** * Creates new instance of this dialog fragment - * - * @param content - * Content to be shared via QR Codes - * @return */ public static ShareQrCodeDialogFragment newInstance(Uri dataUri, boolean fingerprintOnly) { ShareQrCodeDialogFragment frag = new ShareQrCodeDialogFragment(); Bundle args = new Bundle(); - args.putParcelable(ARG_URI, dataUri); + args.putParcelable(ARG_KEY_URI, dataUri); args.putBoolean(ARG_FINGERPRINT_ONLY, fingerprintOnly); frag.setArguments(args); @@ -76,8 +74,8 @@ public class ShareQrCodeDialogFragment extends SherlockDialogFragment { public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); - Uri dataUri = getArguments().getParcelable(ARG_URI); - boolean fingerprintOnly = getArguments().getBoolean(ARG_FINGERPRINT_ONLY); + Uri dataUri = getArguments().getParcelable(ARG_KEY_URI); + mFingerprintOnly = getArguments().getBoolean(ARG_FINGERPRINT_ONLY); AlertDialog.Builder alert = new AlertDialog.Builder(activity); @@ -90,29 +88,29 @@ public class ShareQrCodeDialogFragment extends SherlockDialogFragment { mImage = (ImageView) view.findViewById(R.id.share_qr_code_dialog_image); mText = (TextView) view.findViewById(R.id.share_qr_code_dialog_text); - // TODO - long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); - String content = null; - if (fingerprintOnly) { - content = "openpgp4fpr:"; - - String fingerprint = PgpKeyHelper.convertKeyToHex(masterKeyId); + if (mFingerprintOnly) { + byte[] fingerprintBlob = ProviderHelper.getFingerprint(getActivity(), dataUri); + String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob, false); - mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " - + fingerprint); - - content = content + fingerprint; + mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint); + content = Constants.FINGERPRINT_SCHEME + fingerprint; Log.d(Constants.TAG, "content: " + content); alert.setPositiveButton(R.string.btn_okay, null); + + setQrCode(content); } else { mText.setText(R.string.share_qr_code_dialog_start); + // TODO + long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); + + // get public keyring as ascii armored string ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( - getActivity(), dataUri, new long[] { masterKeyId }); + getActivity(), dataUri, new long[]{masterKeyId}); // TODO: binary? @@ -122,13 +120,13 @@ public class ShareQrCodeDialogFragment extends SherlockDialogFragment { // http://stackoverflow.com/questions/2620444/how-to-prevent-a-dialog-from-closing-when-a-button-is-clicked alert.setPositiveButton(R.string.btn_next, null); alert.setNegativeButton(android.R.string.cancel, null); - } - mContentList = splitString(content, 1000); + mContentList = splitString(content, 1000); - // start with first - mCounter = 0; - updateQrCode(); + // start with first + mCounter = 0; + updatePartsQrCode(); + } return alert.create(); } @@ -136,41 +134,47 @@ public class ShareQrCodeDialogFragment extends SherlockDialogFragment { @Override public void onResume() { super.onResume(); - AlertDialog alertDialog = (AlertDialog) getDialog(); - final Button backButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE); - final Button nextButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); - - backButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mCounter > 0) { - mCounter--; - updateQrCode(); - updateDialog(backButton, nextButton); - } else { - dismiss(); + + if (!mFingerprintOnly) { + AlertDialog alertDialog = (AlertDialog) getDialog(); + final Button backButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE); + final Button nextButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE); + + backButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mCounter > 0) { + mCounter--; + updatePartsQrCode(); + updateDialog(backButton, nextButton); + } else { + dismiss(); + } } - } - }); - nextButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - - if (mCounter < mContentList.size() - 1) { - mCounter++; - updateQrCode(); - updateDialog(backButton, nextButton); - } else { - dismiss(); + }); + nextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if (mCounter < mContentList.size() - 1) { + mCounter++; + updatePartsQrCode(); + updateDialog(backButton, nextButton); + } else { + dismiss(); + } } - } - }); + }); + } } - private void updateQrCode() { + private void updatePartsQrCode() { // Content: <counter>,<size>,<content> - mImage.setImageBitmap(QrCodeUtils.getQRCodeBitmap(mCounter + "," + mContentList.size() - + "," + mContentList.get(mCounter), QR_CODE_SIZE)); + setQrCode(mCounter + "," + mContentList.size() + "," + mContentList.get(mCounter)); + } + + private void setQrCode(String data) { + mImage.setImageBitmap(QrCodeUtils.getQRCodeBitmap(data, QR_CODE_SIZE)); } private void updateDialog(Button backButton, Button nextButton) { @@ -191,7 +195,7 @@ public class ShareQrCodeDialogFragment extends SherlockDialogFragment { /** * Split String by number of characters - * + * * @param text * @param size * @return diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index 96e434e20..277f75c1a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -326,14 +326,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor PGPSecretKey newKey = (PGPSecretKey) PgpConversionHelper .BytesToPGPSecretKey(data .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); - - // add view with new key - KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, - mEditors, false); - view.setEditorListener(SectionView.this); - view.setValue(newKey, newKey.isMasterKey(), -1); - mEditors.addView(view); - SectionView.this.updateEditorsVisible(); + addGeneratedKeyToView(newKey); } }; }; @@ -347,4 +340,14 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor // start service with intent mActivity.startService(intent); } + + private void addGeneratedKeyToView(PGPSecretKey newKey) { + // add view with new key + KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, + mEditors, false); + view.setEditorListener(SectionView.this); + view.setValue(newKey, newKey.isMasterKey(), -1); + mEditors.addView(view); + SectionView.this.updateEditorsVisible(); + } } |