From b819e1a83e6066fb716206e10135e220e4b528d8 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 27 Jun 2018 23:51:25 +0200 Subject: [PATCH] remove unified query from KeychainProvider --- .../keychain/actions/CustomActions.java | 1 - .../keychain/matcher/CustomMatchers.java | 1 - .../keychain/operations/BackupOperation.java | 7 - .../keychain/provider/KeychainContract.java | 20 -- .../keychain/provider/KeychainProvider.java | 270 +------------- .../keychain/ui/adapter/KeyAdapter.java | 332 ------------------ .../ui/adapter/KeySelectableAdapter.java | 98 ------ 7 files changed, 11 insertions(+), 718 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java index 14fb14e35..032aae0ad 100644 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java @@ -28,7 +28,6 @@ import com.tokenautocomplete.TokenCompleteTextView; import org.hamcrest.Matcher; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeyWritableRepository; -import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter; import static android.support.test.InstrumentationRegistry.getTargetContext; diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java index d029c5974..fd44c4ad1 100644 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java @@ -31,7 +31,6 @@ import com.nispok.snackbar.Snackbar; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter.KeyItem; import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java index 65bbd4d7c..1f5f59a1a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BackupOperation.java @@ -52,7 +52,6 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.TemporaryFileProvider; import org.sufficientlysecure.keychain.service.BackupKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; @@ -75,12 +74,6 @@ import timber.log.Timber; * either the name of a file or an output uri to write to. */ public class BackupOperation extends BaseOperation { - - private static final String[] PROJECTION = new String[] { - KeyRings.MASTER_KEY_ID, - KeyRings.HAS_ANY_SECRET - }; - // this is a very simple matcher, we only need basic sanitization private static final Pattern HEADER_PATTERN = Pattern.compile("[a-zA-Z0-9_-]+: [^\\n]+"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java index 76ee5f6f8..e991cc99e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainContract.java @@ -97,34 +97,14 @@ public class KeychainContract { public static final String BASE_KEY_SIGNATURES = "key_signatures"; - public static final String PATH_UNIFIED = "unified"; - public static final String PATH_PUBLIC = "public"; public static final String PATH_USER_IDS = "user_ids"; public static final String PATH_KEYS = "keys"; public static final String PATH_CERTS = "certs"; public static class KeyRings implements BaseColumns, KeysColumns, UserPacketsColumns { - public static final String MASTER_KEY_ID = KeysColumns.MASTER_KEY_ID; - public static final String IS_REVOKED = KeysColumns.IS_REVOKED; - public static final String IS_SECURE = KeysColumns.IS_SECURE; - public static final String VERIFIED = CertsColumns.VERIFIED; - public static final String IS_EXPIRED = "is_expired"; - public static final String HAS_ANY_SECRET = "has_any_secret"; - public static final String HAS_ENCRYPT = "has_encrypt"; - public static final String HAS_SIGN_SECRET = "has_sign_secret"; - public static final String HAS_CERTIFY_SECRET = "has_certify_secret"; - public static final String HAS_AUTHENTICATE = "has_authenticate"; - public static final String HAS_AUTHENTICATE_SECRET = "has_authenticate_secret"; - public static final String HAS_DUPLICATE_USER_ID = "has_duplicate_user_id"; - public static final String API_KNOWN_TO_PACKAGE_NAMES = "known_to_apps"; - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() .appendPath(BASE_KEY_RINGS).build(); - - public static Uri buildUnifiedKeyRingsUri() { - return CONTENT_URI.buildUpon().appendPath(PATH_UNIFIED).build(); - } } public static class KeyRingData implements KeyRingsColumns, BaseColumns { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java index a3d63d849..ec13f24ca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainProvider.java @@ -18,11 +18,6 @@ package org.sufficientlysecure.keychain.provider; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.List; - import android.arch.persistence.db.SupportSQLiteDatabase; import android.content.ContentProvider; import android.content.ContentValues; @@ -30,32 +25,21 @@ import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteConstraintException; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.support.annotation.NonNull; import android.text.TextUtils; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.model.AutocryptPeer; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeySignatures; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPacketsColumns; import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; -import org.sufficientlysecure.keychain.util.DatabaseUtil; import timber.log.Timber; -import static android.database.DatabaseUtils.dumpCursorToString; - public class KeychainProvider extends ContentProvider implements SimpleContentResolverInterface { - - private static final int KEY_RINGS_UNIFIED = 101; - - private static final int KEY_RING_UNIFIED = 200; private static final int KEY_RING_KEYS = 201; private static final int KEY_RING_USER_IDS = 202; private static final int KEY_RING_PUBLIC = 203; @@ -74,33 +58,16 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe String authority = KeychainContract.CONTENT_AUTHORITY; - /* - * list key_rings - * - *
-         * key_rings/unified
-         * key_rings/user_ids
-         * 
- */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS - + "/" + KeychainContract.PATH_UNIFIED, - KEY_RINGS_UNIFIED); - /* * list key_ring specifics * *
-         * key_rings/_/unified
          * key_rings/_/keys
          * key_rings/_/user_ids
-         * key_rings/_/linked_ids
          * key_rings/_/public
          * key_rings/_/certs
          * 
*/ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" - + KeychainContract.PATH_UNIFIED, - KEY_RING_UNIFIED); matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/*/" + KeychainContract.PATH_KEYS, KEY_RING_KEYS); @@ -122,9 +89,6 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe private KeychainDatabase mKeychainDatabase; - /** - * {@inheritDoc} - */ @Override public boolean onCreate() { mUriMatcher = buildUriMatcher(); @@ -132,234 +96,28 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe } public KeychainDatabase getDb() { - if(mKeychainDatabase == null) + if(mKeychainDatabase == null) { mKeychainDatabase = KeychainDatabase.getInstance(getContext()); + } return mKeychainDatabase; } - /** - * {@inheritDoc} - */ @Override public String getType(@NonNull Uri uri) { throw new UnsupportedOperationException(); } + @Override + public Cursor query( + @NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + throw new UnsupportedOperationException(); + } + /** * {@inheritDoc} */ @Override - public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - Timber.v("query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); - - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - int match = mUriMatcher.match(uri); - - // all query() parameters, for good measure - String groupBy; - - switch (match) { - case KEY_RING_UNIFIED: - case KEY_RINGS_UNIFIED: { - HashMap projectionMap = new HashMap<>(); - projectionMap.put(KeyRings._ID, Tables.KEYS + ".oid AS _id"); - projectionMap.put(KeyRings.MASTER_KEY_ID, Tables.KEYS + "." + Keys.MASTER_KEY_ID); - projectionMap.put(KeyRings.KEY_ID, Tables.KEYS + "." + Keys.KEY_ID); - projectionMap.put(KeyRings.KEY_SIZE, Tables.KEYS + "." + Keys.KEY_SIZE); - projectionMap.put(KeyRings.KEY_CURVE_OID, Tables.KEYS + "." + Keys.KEY_CURVE_OID); - projectionMap.put(KeyRings.IS_REVOKED, Tables.KEYS + "." + Keys.IS_REVOKED); - projectionMap.put(KeyRings.IS_SECURE, Tables.KEYS + "." + Keys.IS_SECURE); - projectionMap.put(KeyRings.CAN_CERTIFY, Tables.KEYS + "." + Keys.CAN_CERTIFY); - projectionMap.put(KeyRings.CAN_ENCRYPT, Tables.KEYS + "." + Keys.CAN_ENCRYPT); - projectionMap.put(KeyRings.CAN_SIGN, Tables.KEYS + "." + Keys.CAN_SIGN); - projectionMap.put(KeyRings.CAN_AUTHENTICATE, Tables.KEYS + "." + Keys.CAN_AUTHENTICATE); - projectionMap.put(KeyRings.CREATION, Tables.KEYS + "." + Keys.CREATION); - projectionMap.put(KeyRings.EXPIRY, Tables.KEYS + "." + Keys.EXPIRY); - projectionMap.put(KeyRings.ALGORITHM, Tables.KEYS + "." + Keys.ALGORITHM); - projectionMap.put(KeyRings.FINGERPRINT, Tables.KEYS + "." + Keys.FINGERPRINT); - projectionMap.put(KeyRings.USER_ID, Tables.USER_PACKETS + "." + UserPackets.USER_ID); - projectionMap.put(KeyRings.NAME, Tables.USER_PACKETS + "." + UserPackets.NAME); - projectionMap.put(KeyRings.EMAIL, Tables.USER_PACKETS + "." + UserPackets.EMAIL); - projectionMap.put(KeyRings.COMMENT, Tables.USER_PACKETS + "." + UserPackets.COMMENT); - projectionMap.put(KeyRings.HAS_DUPLICATE_USER_ID, - "(EXISTS (SELECT * FROM " + Tables.USER_PACKETS + " AS dups" - + " WHERE dups." + UserPackets.MASTER_KEY_ID - + " != " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND dups." + UserPackets.RANK + " = 0" - + " AND dups." + UserPackets.NAME - + " = " + Tables.USER_PACKETS + "." + UserPackets.NAME + " COLLATE NOCASE" - + " AND dups." + UserPackets.EMAIL - + " = " + Tables.USER_PACKETS + "." + UserPackets.EMAIL + " COLLATE NOCASE" - + ")) AS " + KeyRings.HAS_DUPLICATE_USER_ID); - projectionMap.put(KeyRings.VERIFIED, Tables.CERTS + "." + Certs.VERIFIED); - projectionMap.put(KeyRings.HAS_SECRET, Tables.KEYS + "." + KeyRings.HAS_SECRET); - projectionMap.put(KeyRings.HAS_ANY_SECRET, - "(EXISTS (SELECT * FROM " + Tables.KEYS + " AS k WHERE " - + "k." + Keys.HAS_SECRET + " != 0" - + " AND k." + Keys.MASTER_KEY_ID + " = " - + Tables.KEYS + "." + KeyRingData.MASTER_KEY_ID - + ")) AS " + KeyRings.HAS_ANY_SECRET); - projectionMap.put(KeyRings.HAS_ENCRYPT, - "kE." + Keys.KEY_ID + " AS " + KeyRings.HAS_ENCRYPT); - projectionMap.put(KeyRings.HAS_SIGN_SECRET, - "kS." + Keys.KEY_ID + " AS " + KeyRings.HAS_SIGN_SECRET); - projectionMap.put(KeyRings.HAS_AUTHENTICATE, - "kA." + Keys.KEY_ID + " AS " + KeyRings.HAS_AUTHENTICATE); - projectionMap.put(KeyRings.HAS_AUTHENTICATE_SECRET, - "kA." + Keys.KEY_ID + " AS " + KeyRings.HAS_AUTHENTICATE_SECRET); - projectionMap.put(KeyRings.HAS_CERTIFY_SECRET, - "kC." + Keys.KEY_ID + " AS " + KeyRings.HAS_CERTIFY_SECRET); - projectionMap.put(KeyRings.IS_EXPIRED, - "(" + Tables.KEYS + "." + Keys.EXPIRY + " IS NOT NULL AND " + Tables.KEYS + "." + Keys.EXPIRY - + " < " + new Date().getTime() / 1000 + ") AS " + KeyRings.IS_EXPIRED); - projectionMap.put(KeyRings.API_KNOWN_TO_PACKAGE_NAMES, - "GROUP_CONCAT(DISTINCT aTI." + AutocryptPeer.PACKAGE_NAME + ") AS " - + KeyRings.API_KNOWN_TO_PACKAGE_NAMES); - qb.setProjectionMap(projectionMap); - - if (projection == null) { - throw new IllegalArgumentException("Please provide a projection!"); - } - - // Need this as list so we can search in it - List plist = Arrays.asList(projection); - - qb.setTables( - Tables.KEYS - + " INNER JOIN " + Tables.USER_PACKETS + " ON (" - + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " = " - + Tables.USER_PACKETS + "." + UserPackets.MASTER_KEY_ID - // we KNOW that the rank zero user packet is a user id! - + " AND " + Tables.USER_PACKETS + "." + UserPackets.RANK + " = 0" - + ") LEFT JOIN " + Tables.CERTS + " ON (" - + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " = " - + Tables.CERTS + "." + KeyRings.MASTER_KEY_ID - + " AND " + Tables.CERTS + "." + Certs.VERIFIED - + " = " + Certs.VERIFIED_SECRET - + ")" - // fairly expensive joins following, only do when requested - + (plist.contains(KeyRings.HAS_ENCRYPT) ? - " LEFT JOIN " + Tables.KEYS + " AS kE ON (" - +"kE." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND kE." + Keys.IS_REVOKED + " = 0" - + " AND kE." + Keys.IS_SECURE + " = 1" - + " AND kE." + Keys.CAN_ENCRYPT + " = 1" - + " AND ( kE." + Keys.EXPIRY + " IS NULL OR kE." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")" : "") - + (plist.contains(KeyRings.HAS_SIGN_SECRET) ? - " LEFT JOIN " + Tables.KEYS + " AS kS ON (" - +"kS." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND kS." + Keys.IS_REVOKED + " = 0" - + " AND kS." + Keys.IS_SECURE + " = 1" - + " AND kS." + Keys.CAN_SIGN + " = 1" - + " AND kS." + Keys.HAS_SECRET + " > 1" - + " AND ( kS." + Keys.EXPIRY + " IS NULL OR kS." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")" : "") - + (plist.contains(KeyRings.HAS_AUTHENTICATE) ? - " LEFT JOIN " + Tables.KEYS + " AS kA ON (" - +"kA." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND kA." + Keys.IS_REVOKED + " = 0" - + " AND kA." + Keys.IS_SECURE + " = 1" - + " AND kA." + Keys.CAN_AUTHENTICATE + " = 1" - + " AND ( kA." + Keys.EXPIRY + " IS NULL OR kA." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")" : "") - + (plist.contains(KeyRings.HAS_AUTHENTICATE_SECRET) ? - " LEFT JOIN " + Tables.KEYS + " AS kA ON (" - +"kA." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND kA." + Keys.IS_REVOKED + " = 0" - + " AND kA." + Keys.IS_SECURE + " = 1" - + " AND kA." + Keys.CAN_AUTHENTICATE + " = 1" - + " AND kA." + Keys.HAS_SECRET + " > 1" - + " AND ( kA." + Keys.EXPIRY + " IS NULL OR kA." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")" : "") - + (plist.contains(KeyRings.HAS_CERTIFY_SECRET) ? - " LEFT JOIN " + Tables.KEYS + " AS kC ON (" - +"kC." + Keys.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + " AND kC." + Keys.IS_REVOKED + " = 0" - + " AND kC." + Keys.IS_SECURE + " = 1" - + " AND kC." + Keys.CAN_CERTIFY + " = 1" - + " AND kC." + Keys.HAS_SECRET + " > 1" - + " AND ( kC." + Keys.EXPIRY + " IS NULL OR kC." + Keys.EXPIRY - + " >= " + new Date().getTime() / 1000 + " )" - + ")" : "") - + (plist.contains(KeyRings.API_KNOWN_TO_PACKAGE_NAMES) ? - " LEFT JOIN " + AutocryptPeer.TABLE_NAME + " AS aTI ON (" - +"aTI." + AutocryptPeer.MASTER_KEY_ID - + " = " + Tables.KEYS + "." + Keys.MASTER_KEY_ID - + ")" : "") - ); - qb.appendWhere(Tables.KEYS + "." + Keys.RANK + " = 0"); - // in case there are multiple verifying certificates - groupBy = Tables.KEYS + "." + Keys.MASTER_KEY_ID; - - qb.appendWhere(" AND " + Tables.KEYS + "." + Keys.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(1)); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_PACKETS + "." + UserPackets.USER_ID + " ASC"; - } - - // uri to watch is all /key_rings/ - uri = KeyRings.CONTENT_URI; - - break; - } - - default: { - throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); - } - - } - - // If no sort order is specified use the default - String orderBy; - if (TextUtils.isEmpty(sortOrder)) { - orderBy = null; - } else { - orderBy = sortOrder; - } - - SupportSQLiteDatabase db = getDb().getReadableDatabase(); - - String query = qb.buildQuery(projection, selection, groupBy, null, orderBy, null); - Cursor cursor = db.query(query, selectionArgs); - if (cursor != null) { - // Tell the cursor what uri to watch, so it knows when its source data changes - cursor.setNotificationUri(getContext().getContentResolver(), uri); - } - - Timber.d("Query: " + qb.buildQuery(projection, selection, null, null, orderBy, null)); - - if (Constants.DEBUG && Constants.DEBUG_LOG_DB_QUERIES) { - Timber.d("Cursor: " + dumpCursorToString(cursor)); - } - - if (Constants.DEBUG && Constants.DEBUG_EXPLAIN_QUERIES) { - String rawQuery = qb.buildQuery(projection, selection, groupBy, null, orderBy, null); - DatabaseUtil.explainQuery(db, rawQuery); - } - - return cursor; - } - - /** - * {@inheritDoc} - */ - @Override - public Uri insert(Uri uri, ContentValues values) { + public Uri insert(@NonNull Uri uri, ContentValues values) { Timber.d("insert(uri=" + uri + ", values=" + values.toString() + ")"); final SupportSQLiteDatabase db = getDb().getWritableDatabase(); @@ -372,7 +130,7 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe switch (match) { case KEY_RING_PUBLIC: { db.insert(Tables.KEY_RINGS_PUBLIC, SQLiteDatabase.CONFLICT_FAIL, values); - keyId = values.getAsLong(KeyRings.MASTER_KEY_ID); + keyId = values.getAsLong(Keys.MASTER_KEY_ID); break; } case KEY_RING_KEYS: { @@ -424,19 +182,13 @@ public class KeychainProvider extends ContentProvider implements SimpleContentRe return rowUri; } - /** - * {@inheritDoc} - */ @Override public int delete(@NonNull Uri uri, String additionalSelection, String[] selectionArgs) { throw new UnsupportedOperationException(); } - /** - * {@inheritDoc} - */ @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) { Timber.v("update(uri=" + uri + ", values=" + values.toString() + ")"); final SupportSQLiteDatabase db = getDb().getWritableDatabase(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java deleted file mode 100644 index 9912cb697..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui.adapter; - - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import android.content.Context; -import android.database.Cursor; -import android.support.v4.widget.CursorAdapter; -import android.text.format.DateUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import org.openintents.openpgp.util.OpenPgpUtils; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey; -import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.ui.util.FormattingUtils; -import org.sufficientlysecure.keychain.ui.util.Highlighter; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; - -public class KeyAdapter extends CursorAdapter { - - protected String mQuery; - protected LayoutInflater mInflater; - protected Context mContext; - - // These are the rows that we will retrieve. - public static final String[] PROJECTION = new String[]{ - KeyRings._ID, - KeyRings.MASTER_KEY_ID, - KeyRings.USER_ID, - KeyRings.IS_REVOKED, - KeyRings.IS_EXPIRED, - KeyRings.IS_SECURE, - KeyRings.VERIFIED, - KeyRings.HAS_ANY_SECRET, - KeyRings.HAS_DUPLICATE_USER_ID, - KeyRings.FINGERPRINT, - KeyRings.CREATION, - KeyRings.HAS_ENCRYPT, - KeyRings.NAME, - KeyRings.EMAIL, - KeyRings.COMMENT - }; - - public static final int INDEX_MASTER_KEY_ID = 1; - public static final int INDEX_USER_ID = 2; - public static final int INDEX_IS_REVOKED = 3; - public static final int INDEX_IS_EXPIRED = 4; - public static final int INDEX_IS_SECURE = 5; - public static final int INDEX_VERIFIED = 6; - public static final int INDEX_HAS_ANY_SECRET = 7; - public static final int INDEX_HAS_DUPLICATE_USER_ID = 8; - public static final int INDEX_FINGERPRINT = 9; - public static final int INDEX_CREATION = 10; - public static final int INDEX_HAS_ENCRYPT = 11; - public static final int INDEX_NAME = 12; - public static final int INDEX_EMAIL = 13; - public static final int INDEX_COMMENT = 14; - - public KeyAdapter(Context context, Cursor c, int flags) { - super(context, c, flags); - - mContext = context; - mInflater = LayoutInflater.from(context); - } - - public void setSearchQuery(String query) { - mQuery = query; - } - - public static class KeyItemViewHolder { - public View mView; - public View mLayoutData; - public Long mMasterKeyId; - public TextView mMainUserId; - public TextView mMainUserIdRest; - public TextView mCreationDate; - public ImageView mStatus; - - public KeyItem mDisplayedItem; - - public KeyItemViewHolder(View view) { - mView = view; - mLayoutData = view.findViewById(R.id.key_list_item_data); - mMainUserId = view.findViewById(R.id.key_list_item_name); - mMainUserIdRest = view.findViewById(R.id.key_list_item_email); - mStatus = view.findViewById(R.id.key_list_item_status_icon); - mCreationDate = view.findViewById(R.id.key_list_item_creation); - } - - public void setData(Context context, KeyItem item, Highlighter highlighter, boolean enabled) { - mDisplayedItem = item; - - { // set name and stuff, common to both key types - OpenPgpUtils.UserId userIdSplit = item.mUserId; - if (userIdSplit.name != null) { - mMainUserId.setText(highlighter.highlight(userIdSplit.name)); - } else { - mMainUserId.setText(R.string.user_id_no_name); - } - if (userIdSplit.email != null) { - mMainUserIdRest.setText(highlighter.highlight(userIdSplit.email)); - mMainUserIdRest.setVisibility(View.VISIBLE); - } else { - mMainUserIdRest.setVisibility(View.GONE); - } - } - - // sort of a hack: if this item isn't enabled, we make it clickable - // to intercept its click events. either way, no listener! - mView.setClickable(!enabled); - - { // set edit button and status, specific by key type - - mMasterKeyId = item.mKeyId; - - int textColor; - - // Note: order is important! - if (item.mIsRevoked) { - KeyFormattingUtils - .setStatusImage(context, mStatus, null, State.REVOKED, R.color.key_flag_gray); - mStatus.setVisibility(View.VISIBLE); - textColor = context.getResources().getColor(R.color.key_flag_gray); - } else if (item.mIsExpired) { - KeyFormattingUtils.setStatusImage(context, mStatus, null, State.EXPIRED, R.color.key_flag_gray); - mStatus.setVisibility(View.VISIBLE); - textColor = context.getResources().getColor(R.color.key_flag_gray); - } else if (!item.mIsSecure) { - KeyFormattingUtils.setStatusImage(context, mStatus, null, State.INSECURE, R.color.key_flag_gray); - mStatus.setVisibility(View.VISIBLE); - textColor = context.getResources().getColor(R.color.key_flag_gray); - } else if (item.mIsSecret) { - mStatus.setVisibility(View.GONE); - textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText); - } else { - // this is a public key - show if it's verified - if (item.mIsVerified) { - KeyFormattingUtils.setStatusImage(context, mStatus, State.VERIFIED); - mStatus.setVisibility(View.VISIBLE); - } else { - KeyFormattingUtils.setStatusImage(context, mStatus, State.UNVERIFIED); - mStatus.setVisibility(View.VISIBLE); - } - textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText); - } - - if (!enabled) { - textColor = context.getResources().getColor(R.color.key_flag_gray); - } - - mMainUserId.setTextColor(textColor); - mMainUserIdRest.setTextColor(textColor); - - if (item.mHasDuplicate) { - String dateTime = DateUtils.formatDateTime(context, - item.mCreation.getTime(), - DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_TIME - | DateUtils.FORMAT_SHOW_YEAR - | DateUtils.FORMAT_ABBREV_MONTH); - mCreationDate.setText(context.getString(R.string.label_key_created, - dateTime)); - mCreationDate.setTextColor(textColor); - mCreationDate.setVisibility(View.VISIBLE); - } else { - mCreationDate.setVisibility(View.GONE); - } - } - } - } - - public boolean isEnabled(Cursor cursor) { - return true; - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - View view = mInflater.inflate(R.layout.key_list_item, parent, false); - KeyItemViewHolder holder = new KeyItemViewHolder(view); - view.setTag(holder); - return view; - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - Highlighter highlighter = new Highlighter(context, mQuery); - KeyItem item = new KeyItem(cursor); - boolean isEnabled = isEnabled(cursor); - - KeyItemViewHolder h = (KeyItemViewHolder) view.getTag(); - h.setData(context, item, highlighter, isEnabled); - } - - public boolean isSecretAvailable(int id) { - if (!mCursor.moveToPosition(id)) { - throw new IllegalStateException("couldn't move cursor to position " + id); - } - - return mCursor.getInt(INDEX_HAS_ANY_SECRET) != 0; - } - - public long getMasterKeyId(int id) { - if (!mCursor.moveToPosition(id)) { - throw new IllegalStateException("couldn't move cursor to position " + id); - } - - return mCursor.getLong(INDEX_MASTER_KEY_ID); - } - - @Override - public KeyItem getItem(int position) { - Cursor c = getCursor(); - if (c.isClosed() || !c.moveToPosition(position)) { - return null; - } - return new KeyItem(c); - } - - @Override - public long getItemId(int position) { - Cursor cursor = getCursor(); - // prevent a crash on rapid cursor changes - if (cursor != null && getCursor().isClosed()) { - return 0L; - } - return super.getItemId(position); - } - - // must be serializable for TokenCompleTextView state - public static class KeyItem implements Serializable { - - public final String mUserIdFull; - public final OpenPgpUtils.UserId mUserId; - public final String mName; - public final String mEmail; - public final String mComment; - public final long mKeyId; - public final boolean mHasDuplicate; - public final boolean mHasEncrypt; - public final Date mCreation; - public final String mFingerprint; - public final boolean mIsSecret, mIsRevoked, mIsExpired, mIsSecure, mIsVerified; - - private KeyItem(Cursor cursor) { - String userId = cursor.getString(INDEX_USER_ID); - mUserId = KeyRing.splitUserId(userId); - mName = cursor.getString(INDEX_NAME); - mEmail = cursor.getString(INDEX_EMAIL); - mComment = cursor.getString(INDEX_COMMENT); - mUserIdFull = userId; - mKeyId = cursor.getLong(INDEX_MASTER_KEY_ID); - mHasDuplicate = cursor.getLong(INDEX_HAS_DUPLICATE_USER_ID) > 0; - mHasEncrypt = cursor.getInt(INDEX_HAS_ENCRYPT) != 0; - mCreation = new Date(cursor.getLong(INDEX_CREATION) * 1000); - mFingerprint = KeyFormattingUtils.convertFingerprintToHex( - cursor.getBlob(INDEX_FINGERPRINT)); - mIsSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0; - mIsRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; - mIsExpired = cursor.getInt(INDEX_IS_EXPIRED) > 0; - mIsSecure = cursor.getInt(INDEX_IS_SECURE) > 0; - mIsVerified = cursor.getInt(INDEX_VERIFIED) > 0; - } - - public KeyItem(CanonicalizedPublicKeyRing ring) { - CanonicalizedPublicKey key = ring.getPublicKey(); - String userId = key.getPrimaryUserIdWithFallback(); - mUserId = KeyRing.splitUserId(userId); - mName = mUserId.name; - mEmail = mUserId.email; - mComment = mUserId.comment; - mUserIdFull = userId; - mKeyId = ring.getMasterKeyId(); - mHasDuplicate = false; - mHasEncrypt = key.getKeyRing().getEncryptIds().size() > 0; - mCreation = key.getCreationTime(); - mFingerprint = KeyFormattingUtils.convertFingerprintToHex( - ring.getFingerprint()); - mIsRevoked = key.isRevoked(); - mIsExpired = key.isExpired(); - mIsSecure = key.isSecure(); - - // these two are actually "don't know"s - mIsSecret = false; - mIsVerified = false; - } - - public String getReadableName() { - if (mName != null) { - return mName; - } else { - return mEmail; - } - } - } - - public static String[] getProjectionWith(String[] projection) { - List list = new ArrayList<>(); - list.addAll(Arrays.asList(PROJECTION)); - list.addAll(Arrays.asList(projection)); - return list.toArray(new String[list.size()]); - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java deleted file mode 100644 index 1ee67f2ec..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui.adapter; - -import android.content.Context; -import android.database.Cursor; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.CheckBox; - -import org.sufficientlysecure.keychain.R; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class KeySelectableAdapter extends KeyAdapter implements OnItemClickListener { - - private HashSet mSelectedItems = new HashSet<>(); - - public KeySelectableAdapter(Context context, Cursor c, int flags, Set initialChecked) { - super(context, c, flags); - if (initialChecked != null) { - mSelectedItems.addAll(initialChecked); - } - } - - public static class KeySelectableItemViewHolder extends KeyItemViewHolder { - - public CheckBox mCheckbox; - - public KeySelectableItemViewHolder(View view) { - super(view); - mCheckbox = view.findViewById(R.id.selected); - } - - public void setCheckedState(boolean checked) { - mCheckbox.setChecked(checked); - } - - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - View view = mInflater.inflate(R.layout.key_list_selectable_item, parent, false); - KeySelectableItemViewHolder holder = new KeySelectableItemViewHolder(view); - view.setTag(holder); - return view; - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - super.bindView(view, context, cursor); - - KeySelectableItemViewHolder h = (KeySelectableItemViewHolder) view.getTag(); - h.setCheckedState(mSelectedItems.contains(h.mDisplayedItem.mKeyId)); - - } - - public void setCheckedStates(Set checked) { - mSelectedItems.clear(); - mSelectedItems.addAll(checked); - notifyDataSetChanged(); - } - - public Set getSelectedMasterKeyIds() { - return Collections.unmodifiableSet(mSelectedItems); - } - - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - long masterKeyId = getMasterKeyId(position); - if (mSelectedItems.contains(masterKeyId)) { - mSelectedItems.remove(masterKeyId); - } else { - mSelectedItems.add(masterKeyId); - } - notifyDataSetChanged(); - } - -}