Merge branch 'unified-keylist'
Conflicts: OpenPGP-Keychain/src/main/AndroidManifest.xml OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java OpenPGP-Keychain/src/main/res/layout/key_list_secret_item.xml OpenPGP-Keychain/src/main/res/menu/key_list.xml OpenPGP-Keychain/src/main/res/menu/key_list_multi.xml OpenPGP-Keychain/src/main/res/menu/key_list_secret_multi.xml
This commit is contained in:
@@ -78,6 +78,7 @@ public class KeychainContract {
|
||||
|
||||
public static final String PATH_PUBLIC = "public";
|
||||
public static final String PATH_SECRET = "secret";
|
||||
public static final String PATH_UNIFIED = "unified";
|
||||
|
||||
public static final String PATH_BY_MASTER_KEY_ID = "master_key_id";
|
||||
public static final String PATH_BY_KEY_ID = "key_id";
|
||||
@@ -100,6 +101,10 @@ public class KeychainContract {
|
||||
/** Use if a single item is returned */
|
||||
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key_ring";
|
||||
|
||||
public static Uri buildUnifiedKeyRingsUri() {
|
||||
return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build();
|
||||
}
|
||||
|
||||
public static Uri buildPublicKeyRingsUri() {
|
||||
return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).build();
|
||||
}
|
||||
|
||||
@@ -81,6 +81,8 @@ public class KeychainProvider extends ContentProvider {
|
||||
private static final int API_APPS_BY_ROW_ID = 302;
|
||||
private static final int API_APPS_BY_PACKAGE_NAME = 303;
|
||||
|
||||
private static final int UNIFIED_KEY_RING = 401;
|
||||
|
||||
// private static final int DATA_STREAM = 401;
|
||||
|
||||
protected UriMatcher mUriMatcher;
|
||||
@@ -226,6 +228,16 @@ public class KeychainProvider extends ContentProvider {
|
||||
matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/"
|
||||
+ KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME);
|
||||
|
||||
/**
|
||||
* unified key rings
|
||||
* <pre>
|
||||
*
|
||||
* key_rings/unified
|
||||
*
|
||||
*/
|
||||
matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/"
|
||||
+ KeychainContract.PATH_UNIFIED, UNIFIED_KEY_RING);
|
||||
|
||||
/**
|
||||
* data stream
|
||||
*
|
||||
@@ -455,6 +467,69 @@ public class KeychainProvider extends ContentProvider {
|
||||
|
||||
int match = mUriMatcher.match(uri);
|
||||
|
||||
// screw that switch
|
||||
if(match == UNIFIED_KEY_RING) {
|
||||
|
||||
// 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')");
|
||||
|
||||
{
|
||||
HashMap<String, String> projectionMap = new HashMap<String, String>();
|
||||
|
||||
projectionMap.put(KeyRingsColumns.TYPE, "MAX(" + Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + ")");
|
||||
|
||||
projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._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(KeysColumns.IS_REVOKED, Tables.KEYS + "." + KeysColumns.IS_REVOKED);
|
||||
|
||||
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID);
|
||||
|
||||
qb.setProjectionMap(projectionMap);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
|
||||
}
|
||||
|
||||
// If no sort order is specified use the default
|
||||
String orderBy;
|
||||
if (TextUtils.isEmpty(sortOrder)) {
|
||||
orderBy = Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " DESC";
|
||||
} else {
|
||||
orderBy = Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " DESC, " + sortOrder;
|
||||
}
|
||||
|
||||
Cursor c = qb.query(db, projection, selection, selectionArgs,
|
||||
Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID,
|
||||
null, orderBy);
|
||||
|
||||
// Tell the cursor what uri to watch, so it knows when its source data changes
|
||||
c.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
|
||||
if (Constants.DEBUG) {
|
||||
Log.d(Constants.TAG,
|
||||
"Query: "
|
||||
+ qb.buildQuery(projection, selection, selectionArgs, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID, null,
|
||||
orderBy, null));
|
||||
Log.d(Constants.TAG, "Cursor: " + DatabaseUtils.dumpCursorToString(c));
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
switch (match) {
|
||||
case PUBLIC_KEY_RING:
|
||||
case SECRET_KEY_RING:
|
||||
|
||||
@@ -483,13 +483,13 @@ public class ProviderHelper {
|
||||
*/
|
||||
public static boolean getSecretMasterKeyCanSign(Context context, long keyRingRowId) {
|
||||
Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId));
|
||||
return getMasterKeyCanSign(context, queryUri, keyRingRowId);
|
||||
return getMasterKeyCanSign(context, queryUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private helper method to get master key private empty status of keyring by its row id
|
||||
*/
|
||||
private static boolean getMasterKeyCanSign(Context context, Uri queryUri, long keyRingRowId) {
|
||||
public static boolean getMasterKeyCanSign(Context context, Uri queryUri) {
|
||||
String[] projection = new String[]{
|
||||
KeyRings.MASTER_KEY_ID,
|
||||
"(SELECT COUNT(sign_keys." + Keys._ID + ") FROM " + Tables.KEYS
|
||||
@@ -515,6 +515,12 @@ public class ProviderHelper {
|
||||
return (masterKeyId > 0);
|
||||
}
|
||||
|
||||
public static boolean hasSecretKeyByMasterKeyId(Context context, long masterKeyId) {
|
||||
Uri queryUri = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId));
|
||||
// see if we can get our master key id back from the uri
|
||||
return getMasterKeyId(context, queryUri) == masterKeyId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get master key id of keyring by its row id
|
||||
*/
|
||||
@@ -546,6 +552,26 @@ public class ProviderHelper {
|
||||
return masterKeyId;
|
||||
}
|
||||
|
||||
public static long getRowId(Context context, Uri queryUri) {
|
||||
String[] projection = new String[]{KeyRings._ID};
|
||||
Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
|
||||
|
||||
long rowId = 0;
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
int idCol = cursor.getColumnIndexOrThrow(KeyRings._ID);
|
||||
|
||||
rowId = cursor.getLong(idCol);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
return rowId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fingerprint of key
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user