diff options
Diffstat (limited to 'OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider')
7 files changed, 0 insertions, 2415 deletions
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java deleted file mode 100644 index d2381f6f0..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.provider; - -import org.sufficientlysecure.keychain.Constants; - -import android.net.Uri; -import android.provider.BaseColumns; - -public class KeychainContract { - - interface KeyRingsColumns { - String MASTER_KEY_ID = "master_key_id"; // not a database id - String TYPE = "type"; // see KeyTypes - String KEY_RING_DATA = "key_ring_data"; // PGPPublicKeyRing / PGPSecretKeyRing blob - } - - interface KeysColumns { - String KEY_ID = "key_id"; // not a database id - String TYPE = "type"; // see KeyTypes - String IS_MASTER_KEY = "is_master_key"; - String ALGORITHM = "algorithm"; - String KEY_SIZE = "key_size"; - String CAN_CERTIFY = "can_certify"; - String CAN_SIGN = "can_sign"; - String CAN_ENCRYPT = "can_encrypt"; - String IS_REVOKED = "is_revoked"; - String CREATION = "creation"; - String EXPIRY = "expiry"; - 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"; - } - - interface UserIdsColumns { - String KEY_RING_ROW_ID = "key_ring_row_id"; // foreign key to key_rings._ID - String USER_ID = "user_id"; // not a database id - String RANK = "rank"; - } - - interface ApiAppsColumns { - String PACKAGE_NAME = "package_name"; - String PACKAGE_SIGNATURE = "package_signature"; - String KEY_ID = "key_id"; // not a database id - String ENCRYPTION_ALGORITHM = "encryption_algorithm"; - String HASH_ALORITHM = "hash_algorithm"; - String COMPRESSION = "compression"; - } - - public static final class KeyTypes { - public static final int PUBLIC = 0; - public static final int SECRET = 1; - } - - public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider"; - - private static final Uri BASE_CONTENT_URI_INTERNAL = Uri - .parse("content://" + CONTENT_AUTHORITY); - - public static final String BASE_KEY_RINGS = "key_rings"; - public static final String BASE_DATA = "data"; - - public static final String PATH_PUBLIC = "public"; - public static final String PATH_SECRET = "secret"; - - public static final String PATH_BY_MASTER_KEY_ID = "master_key_id"; - public static final String PATH_BY_KEY_ID = "key_id"; - public static final String PATH_BY_EMAILS = "emails"; - public static final String PATH_BY_LIKE_EMAIL = "like_email"; - - public static final String PATH_USER_IDS = "user_ids"; - public static final String PATH_KEYS = "keys"; - - public static final String BASE_API_APPS = "api_apps"; - public static final String PATH_BY_PACKAGE_NAME = "package_name"; - - public static class KeyRings implements KeyRingsColumns, BaseColumns { - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_KEY_RINGS).build(); - - /** Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.key_ring"; - - /** 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 buildPublicKeyRingsUri() { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).build(); - } - - public static Uri buildPublicKeyRingsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId).build(); - } - - public static Uri buildPublicKeyRingsByMasterKeyIdUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC) - .appendPath(PATH_BY_MASTER_KEY_ID).appendPath(masterKeyId).build(); - } - - public static Uri buildPublicKeyRingsByKeyIdUri(String keyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(PATH_BY_KEY_ID) - .appendPath(keyId).build(); - } - - public static Uri buildPublicKeyRingsByEmailsUri(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(PATH_BY_EMAILS) - .appendPath(emails).build(); - } - - public static Uri buildPublicKeyRingsByLikeEmailUri(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(PATH_BY_LIKE_EMAIL) - .appendPath(emails).build(); - } - - public static Uri buildSecretKeyRingsUri() { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).build(); - } - - public static Uri buildSecretKeyRingsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId).build(); - } - - public static Uri buildSecretKeyRingsByMasterKeyIdUri(String masterKeyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET) - .appendPath(PATH_BY_MASTER_KEY_ID).appendPath(masterKeyId).build(); - } - - public static Uri buildSecretKeyRingsByKeyIdUri(String keyId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_KEY_ID) - .appendPath(keyId).build(); - } - - public static Uri buildSecretKeyRingsByEmailsUri(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_EMAILS) - .appendPath(emails).build(); - } - - public static Uri buildSecretKeyRingsByLikeEmails(String emails) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(PATH_BY_LIKE_EMAIL) - .appendPath(emails).build(); - } - } - - public static class Keys implements KeysColumns, BaseColumns { - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_KEY_RINGS).build(); - - /** Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.key"; - - /** Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.key"; - - public static Uri buildPublicKeysUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).build(); - } - - public static Uri buildPublicKeysUri(String keyRingRowId, String keyRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).appendPath(keyRowId).build(); - } - - public static Uri buildSecretKeysUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).build(); - } - - public static Uri buildSecretKeysUri(String keyRingRowId, String keyRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_KEYS).appendPath(keyRowId).build(); - } - - public static Uri buildKeysUri(Uri keyRingUri) { - return keyRingUri.buildUpon().appendPath(PATH_KEYS).build(); - } - - public static Uri buildKeysUri(Uri keyRingUri, String keyRowId) { - return keyRingUri.buildUpon().appendPath(PATH_KEYS).appendPath(keyRowId).build(); - } - } - - public static class UserIds implements UserIdsColumns, BaseColumns { - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_KEY_RINGS).build(); - - /** Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.user_id"; - - /** Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.user_id"; - - public static Uri buildPublicUserIdsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).build(); - } - - public static Uri buildPublicUserIdsUri(String keyRingRowId, String userIdRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_PUBLIC).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).appendPath(userIdRowId).build(); - } - - public static Uri buildSecretUserIdsUri(String keyRingRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).build(); - } - - public static Uri buildSecretUserIdsUri(String keyRingRowId, String userIdRowId) { - return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId) - .appendPath(PATH_USER_IDS).appendPath(userIdRowId).build(); - } - - public static Uri buildUserIdsUri(Uri keyRingUri) { - return keyRingUri.buildUpon().appendPath(PATH_USER_IDS).build(); - } - - public static Uri buildUserIdsUri(Uri keyRingUri, String userIdRowId) { - return keyRingUri.buildUpon().appendPath(PATH_USER_IDS).appendPath(userIdRowId).build(); - } - } - - public static class ApiApps implements ApiAppsColumns, BaseColumns { - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_API_APPS).build(); - - /** Use if multiple items get returned */ - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.api_apps"; - - /** Use if a single item is returned */ - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.api_apps"; - - public static Uri buildIdUri(String rowId) { - return CONTENT_URI.buildUpon().appendPath(rowId).build(); - } - - public static Uri buildByPackageNameUri(String packageName) { - return CONTENT_URI.buildUpon().appendPath(PATH_BY_PACKAGE_NAME).appendPath(packageName) - .build(); - } - } - - public static class DataStream { - public static final Uri CONTENT_URI = BASE_CONTENT_URI_INTERNAL.buildUpon() - .appendPath(BASE_DATA).build(); - - public static Uri buildDataStreamUri(String streamFilename) { - return CONTENT_URI.buildUpon().appendPath(streamFilename).build(); - } - } - - private KeychainContract() { - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java deleted file mode 100644 index 60c5c91a8..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.provider; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAppsColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.provider.BaseColumns; - -public class KeychainDatabase extends SQLiteOpenHelper { - private static final String DATABASE_NAME = "apg.db"; - private static final int DATABASE_VERSION = 6; - - public interface Tables { - String KEY_RINGS = "key_rings"; - String KEYS = "keys"; - String USER_IDS = "user_ids"; - String API_APPS = "api_apps"; - } - - 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.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, " - + 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.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.COMPRESSION + " INTEGER)"; - - KeychainDatabase(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - Log.w(Constants.TAG, "Creating database..."); - - db.execSQL(CREATE_KEY_RINGS); - db.execSQL(CREATE_KEYS); - db.execSQL(CREATE_USER_IDS); - db.execSQL(CREATE_API_APPS); - } - - @Override - public void onOpen(SQLiteDatabase db) { - super.onOpen(db); - if (!db.isReadOnly()) { - // Enable foreign key constraints - db.execSQL("PRAGMA foreign_keys=ON;"); - } - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w(Constants.TAG, "Upgrading database from version " + oldVersion + " to " + newVersion); - - // Upgrade from oldVersion through all methods to newest one - for (int version = oldVersion; version < newVersion; ++version) { - 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; - - } - } - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java deleted file mode 100644 index 70fb11e47..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainProvider.java +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * Copyright (C) 2010 Thialfihar <thi@thialfihar.org> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.sufficientlysecure.keychain.provider; - -import java.util.Arrays; -import java.util.HashMap; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingsColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyTypes; -import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeysColumns; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIdsColumns; -import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.UriMatcher; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteConstraintException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteQueryBuilder; -import android.net.Uri; -import android.provider.BaseColumns; -import android.text.TextUtils; - -public class KeychainProvider extends ContentProvider { - // public static final String ACTION_BROADCAST_DATABASE_CHANGE = Constants.PACKAGE_NAME - // + ".action.DATABASE_CHANGE"; - // - // public static final String EXTRA_BROADCAST_KEY_TYPE = "key_type"; - // public static final String EXTRA_BROADCAST_CONTENT_ITEM_TYPE = "contentItemType"; - - private static final int PUBLIC_KEY_RING = 101; - private static final int PUBLIC_KEY_RING_BY_ROW_ID = 102; - private static final int PUBLIC_KEY_RING_BY_MASTER_KEY_ID = 103; - private static final int PUBLIC_KEY_RING_BY_KEY_ID = 104; - private static final int PUBLIC_KEY_RING_BY_EMAILS = 105; - private static final int PUBLIC_KEY_RING_BY_LIKE_EMAIL = 106; - - private static final int PUBLIC_KEY_RING_KEY = 111; - private static final int PUBLIC_KEY_RING_KEY_BY_ROW_ID = 112; - - private static final int PUBLIC_KEY_RING_USER_ID = 121; - private static final int PUBLIC_KEY_RING_USER_ID_BY_ROW_ID = 122; - - private static final int SECRET_KEY_RING = 201; - private static final int SECRET_KEY_RING_BY_ROW_ID = 202; - private static final int SECRET_KEY_RING_BY_MASTER_KEY_ID = 203; - private static final int SECRET_KEY_RING_BY_KEY_ID = 204; - private static final int SECRET_KEY_RING_BY_EMAILS = 205; - private static final int SECRET_KEY_RING_BY_LIKE_EMAIL = 206; - - private static final int SECRET_KEY_RING_KEY = 211; - private static final int SECRET_KEY_RING_KEY_BY_ROW_ID = 212; - - private static final int SECRET_KEY_RING_USER_ID = 221; - private static final int SECRET_KEY_RING_USER_ID_BY_ROW_ID = 222; - - private static final int API_APPS = 301; - private static final int API_APPS_BY_ROW_ID = 302; - private static final int API_APPS_BY_PACKAGE_NAME = 303; - - // private static final int DATA_STREAM = 401; - - protected UriMatcher mUriMatcher; - - /** - * Build and return a {@link UriMatcher} that catches all {@link Uri} variations supported by - * this {@link ContentProvider}. - */ - protected UriMatcher buildUriMatcher() { - final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); - - String authority = KeychainContract.CONTENT_AUTHORITY; - - /** - * public key rings - * - * <pre> - * key_rings/public - * key_rings/public/# - * key_rings/public/master_key_id/_ - * key_rings/public/key_id/_ - * key_rings/public/emails/_ - * key_rings/public/like_email/_ - * </pre> - */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC, PUBLIC_KEY_RING); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#", PUBLIC_KEY_RING_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_MASTER_KEY_ID - + "/*", PUBLIC_KEY_RING_BY_MASTER_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_KEY_ID + "/*", - PUBLIC_KEY_RING_BY_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_EMAILS + "/*", - PUBLIC_KEY_RING_BY_EMAILS); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_EMAILS, - PUBLIC_KEY_RING_BY_EMAILS); // without emails specified - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/" + KeychainContract.PATH_BY_LIKE_EMAIL + "/*", - PUBLIC_KEY_RING_BY_LIKE_EMAIL); - - /** - * public keys - * - * <pre> - * key_rings/public/#/keys - * key_rings/public/#/keys/# - * </pre> - */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_KEYS, - PUBLIC_KEY_RING_KEY); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_KEYS + "/#", - PUBLIC_KEY_RING_KEY_BY_ROW_ID); - - /** - * public user ids - * - * <pre> - * key_rings/public/#/user_ids - * key_rings/public/#/user_ids/# - * </pre> - */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_USER_IDS, - PUBLIC_KEY_RING_USER_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_PUBLIC + "/#/" + KeychainContract.PATH_USER_IDS + "/#", - PUBLIC_KEY_RING_USER_ID_BY_ROW_ID); - - /** - * secret key rings - * - * <pre> - * key_rings/secret - * key_rings/secret/# - * key_rings/secret/master_key_id/_ - * key_rings/secret/key_id/_ - * key_rings/secret/emails/_ - * key_rings/secret/like_email/_ - * </pre> - */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET, SECRET_KEY_RING); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#", SECRET_KEY_RING_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_MASTER_KEY_ID - + "/*", SECRET_KEY_RING_BY_MASTER_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_KEY_ID + "/*", - SECRET_KEY_RING_BY_KEY_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_EMAILS + "/*", - SECRET_KEY_RING_BY_EMAILS); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_EMAILS, - SECRET_KEY_RING_BY_EMAILS); // without emails specified - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/" + KeychainContract.PATH_BY_LIKE_EMAIL + "/*", - SECRET_KEY_RING_BY_LIKE_EMAIL); - - /** - * secret keys - * - * <pre> - * key_rings/secret/#/keys - * key_rings/secret/#/keys/# - * </pre> - */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_KEYS, - SECRET_KEY_RING_KEY); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_KEYS + "/#", - SECRET_KEY_RING_KEY_BY_ROW_ID); - - /** - * secret user ids - * - * <pre> - * key_rings/secret/#/user_ids - * key_rings/secret/#/user_ids/# - * </pre> - */ - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_USER_IDS, - SECRET_KEY_RING_USER_ID); - matcher.addURI(authority, KeychainContract.BASE_KEY_RINGS + "/" - + KeychainContract.PATH_SECRET + "/#/" + KeychainContract.PATH_USER_IDS + "/#", - SECRET_KEY_RING_USER_ID_BY_ROW_ID); - - /** - * API apps - */ - matcher.addURI(authority, KeychainContract.BASE_API_APPS, API_APPS); - matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/#", API_APPS_BY_ROW_ID); - matcher.addURI(authority, KeychainContract.BASE_API_APPS + "/" - + KeychainContract.PATH_BY_PACKAGE_NAME + "/*", API_APPS_BY_PACKAGE_NAME); - - /** - * data stream - * - * <pre> - * data / _ - * </pre> - */ - // matcher.addURI(authority, KeychainContract.BASE_DATA + "/*", DATA_STREAM); - - return matcher; - } - - private KeychainDatabase mApgDatabase; - - /** {@inheritDoc} */ - @Override - public boolean onCreate() { - mUriMatcher = buildUriMatcher(); - mApgDatabase = new KeychainDatabase(getContext()); - return true; - } - - /** {@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); - } - } - - /** - * 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; - } - - return type; - } - - /** - * Set result of query to specific columns, don't show blob column for external content provider - * - * @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(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 - * - * @return - */ - private HashMap<String, String> getProjectionMapForKeys() { - HashMap<String, String> projectionMap = new HashMap<String, String>(); - - projectionMap.put(BaseColumns._ID, BaseColumns._ID); - projectionMap.put(KeysColumns.KEY_ID, KeysColumns.KEY_ID); - projectionMap.put(KeysColumns.IS_MASTER_KEY, KeysColumns.IS_MASTER_KEY); - projectionMap.put(KeysColumns.ALGORITHM, KeysColumns.ALGORITHM); - projectionMap.put(KeysColumns.KEY_SIZE, KeysColumns.KEY_SIZE); - projectionMap.put(KeysColumns.CAN_CERTIFY, KeysColumns.CAN_CERTIFY); - projectionMap.put(KeysColumns.CAN_SIGN, KeysColumns.CAN_SIGN); - projectionMap.put(KeysColumns.CAN_ENCRYPT, KeysColumns.CAN_ENCRYPT); - projectionMap.put(KeysColumns.IS_REVOKED, KeysColumns.IS_REVOKED); - projectionMap.put(KeysColumns.CREATION, KeysColumns.CREATION); - projectionMap.put(KeysColumns.EXPIRY, KeysColumns.EXPIRY); - 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); - - return projectionMap; - } - - /** - * Builds default query for keyRings: KeyRings table is joined with UserIds - * - * @param qb - * @param match - * @param isMasterKey - * @param sortOrder - * @return - */ - private SQLiteQueryBuilder buildKeyRingQuery(SQLiteQueryBuilder qb, int match, String sortOrder) { - // 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 + "." - + UserIdsColumns.KEY_RING_ROW_ID + " AND " + Tables.USER_IDS + "." - + UserIdsColumns.RANK + " = '0')"); - - qb.setProjectionMap(getProjectionMapForKeyRings()); - - return qb; - } - - /** - * Builds default query for keyRings: KeyRings table is joined with Keys and UserIds - * - * @param qb - * @param match - * @param isMasterKey - * @param sortOrder - * @return - */ - private SQLiteQueryBuilder buildKeyRingQueryWithKeys(SQLiteQueryBuilder qb, int match, - String sortOrder) { - // public or secret keyring - qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = "); - qb.appendWhereEscapeString(Integer.toString(getKeyType(match))); - - // join keyrings with keys and userIds to every keyring - qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" - + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." - + KeysColumns.KEY_RING_ROW_ID + ") " + " 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')"); - - qb.setProjectionMap(getProjectionMapForKeyRings()); - - return qb; - } - - /** {@inheritDoc} */ - @SuppressWarnings("deprecation") - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - Log.v(Constants.TAG, "query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); - - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - SQLiteDatabase db = mApgDatabase.getReadableDatabase(); - - int match = mUriMatcher.match(uri); - - switch (match) { - case PUBLIC_KEY_RING: - case SECRET_KEY_RING: - qb = buildKeyRingQuery(qb, match, sortOrder); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - - case PUBLIC_KEY_RING_BY_ROW_ID: - case SECRET_KEY_RING_BY_ROW_ID: - qb = buildKeyRingQuery(qb, match, sortOrder); - - qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - - case PUBLIC_KEY_RING_BY_MASTER_KEY_ID: - case SECRET_KEY_RING_BY_MASTER_KEY_ID: - qb = buildKeyRingQuery(qb, match, sortOrder); - - 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; - - case SECRET_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - qb = buildKeyRingQueryWithKeys(qb, match, sortOrder); - - qb.appendWhere(" AND " + Tables.KEYS + "." + KeysColumns.KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; - } - - break; - - case SECRET_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_EMAILS: - qb = buildKeyRingQuery(qb, match, sortOrder); - - 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 (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; - - case SECRET_KEY_RING_BY_LIKE_EMAIL: - case PUBLIC_KEY_RING_BY_LIKE_EMAIL: - qb = buildKeyRingQuery(qb, match, sortOrder); - - String likeEmail = uri.getLastPathSegment(); - - 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 - + "))"); - - 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))); - - qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - - qb.setProjectionMap(getProjectionMapForKeys()); - - 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))); - - qb.appendWhere(" AND " + KeysColumns.KEY_RING_ROW_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - - qb.appendWhere(" AND " + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - qb.setProjectionMap(getProjectionMapForKeys()); - - 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)); - - 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)); - - qb.appendWhere(" AND " + BaseColumns._ID + " = "); - qb.appendWhereEscapeString(uri.getLastPathSegment()); - - break; - - case API_APPS: - 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()); - - break; - case API_APPS_BY_PACKAGE_NAME: - qb.setTables(Tables.API_APPS); - qb.appendWhere(ApiApps.PACKAGE_NAME + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - - break; - - default: - throw new IllegalArgumentException("Unknown URI " + uri); - - } - - // If no sort order is specified use the default - String orderBy; - if (TextUtils.isEmpty(sortOrder)) { - orderBy = null; - } else { - orderBy = sortOrder; - } - - Cursor c = qb.query(db, projection, selection, selectionArgs, null, 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, null, null, - orderBy, null)); - Log.d(Constants.TAG, "Cursor: " + DatabaseUtils.dumpCursorToString(c)); - } - - return c; - } - - /** {@inheritDoc} */ - @Override - public Uri insert(Uri uri, ContentValues values) { - Log.d(Constants.TAG, "insert(uri=" + uri + ", values=" + values.toString() + ")"); - - final SQLiteDatabase db = mApgDatabase.getWritableDatabase(); - - Uri rowUri = null; - long rowId = -1; - try { - 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); - } - - // notify of changes in db - getContext().getContentResolver().notifyChange(uri, null); - - } catch (SQLiteConstraintException e) { - Log.e(Constants.TAG, "Constraint exception on insert! Entry already existing?"); - } - - return rowUri; - } - - /** {@inheritDoc} */ - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - Log.v(Constants.TAG, "delete(uri=" + uri + ")"); - - final SQLiteDatabase db = mApgDatabase.getWritableDatabase(); - - int count; - final int match = mUriMatcher.match(uri); - - 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); - 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 - getContext().getContentResolver().notifyChange(uri, null); - - } catch (SQLiteConstraintException e) { - Log.e(Constants.TAG, "Constraint exception on update! Entry already existing?"); - } - - return count; - } - - /** - * 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 andType = ""; - if (keyType != null) { - andType = " AND " + KeyRingsColumns.TYPE + "=" + keyType; - } - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - return defaultSelection + andType + andSelection; - } - - /** - * Build default selection statement for Keys. If no extra selection is specified only build - * where clause with rowId - * - * @param uri - * @param selection - * @return - */ - private String buildDefaultKeysSelection(Uri uri, Integer keyType, String selection) { - String rowId = uri.getLastPathSegment(); - - String foreignKeyRingRowId = uri.getPathSegments().get(2); - String andForeignKeyRing = " AND " + KeysColumns.KEY_RING_ROW_ID + " = " - + foreignKeyRingRowId; - - String andType = ""; - if (keyType != null) { - andType = " AND " + KeysColumns.TYPE + "=" + keyType; - } - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - return BaseColumns._ID + "=" + rowId + andForeignKeyRing + andType + andSelection; - } - - /** - * Build default selection statement for UserIds. If no extra selection is specified only build - * where clause with rowId - * - * @param uri - * @param selection - * @return - */ - private String buildDefaultUserIdsSelection(Uri uri, String selection) { - String rowId = uri.getLastPathSegment(); - - String foreignKeyRingRowId = uri.getPathSegments().get(2); - String andForeignKeyRing = " AND " + KeysColumns.KEY_RING_ROW_ID + " = " - + foreignKeyRingRowId; - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - return BaseColumns._ID + "=" + rowId + andForeignKeyRing + andSelection; - } - - /** - * Build default selection statement for API apps. If no extra selection is specified only build - * where clause with rowId - * - * @param uri - * @param selection - * @return - */ - private String buildDefaultApiAppsSelection(Uri uri, boolean packageSelection, String selection) { - String lastPathSegment = uri.getLastPathSegment(); - - String andSelection = ""; - if (!TextUtils.isEmpty(selection)) { - andSelection = " AND (" + selection + ")"; - } - - if (packageSelection) { - return ApiApps.PACKAGE_NAME + "=" + lastPathSegment + andSelection; - } else { - return BaseColumns._ID + "=" + lastPathSegment + andSelection; - } - } - - // @Override - // public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - // int match = mUriMatcher.match(uri); - // if (match != DATA_STREAM) { - // throw new FileNotFoundException(); - // } - // String fileName = uri.getLastPathSegment(); - // File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName); - // return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); - // } - - /** - * This broadcast is send system wide to inform other application that a keyring was inserted, - * updated, or deleted - */ - private void sendBroadcastDatabaseChange(int keyType, String contentItemType) { - // TODO: Disabled, old API - // Intent intent = new Intent(); - // intent.setAction(ACTION_BROADCAST_DATABASE_CHANGE); - // intent.putExtra(EXTRA_BROADCAST_KEY_TYPE, keyType); - // intent.putExtra(EXTRA_BROADCAST_CONTENT_ITEM_TYPE, contentItemType); - // - // getContext().sendBroadcast(intent, Constants.PERMISSION_ACCESS_API); - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java deleted file mode 100644 index a879d60a8..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobContract.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.provider; - -import org.sufficientlysecure.keychain.Constants; - -import android.net.Uri; -import android.provider.BaseColumns; - -public class KeychainServiceBlobContract { - - interface BlobsColumns { - String KEY = "key"; - } - - public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".blobs"; - - private static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY); - - public static class Blobs implements BlobsColumns, BaseColumns { - public static final Uri CONTENT_URI = BASE_CONTENT_URI; - } - - private KeychainServiceBlobContract() { - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java deleted file mode 100644 index fcee76fd7..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobDatabase.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * Copyright (C) 2011 Markus Doits <markus.doits@googlemail.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.provider; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.provider.BaseColumns; - -import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns; - -public class KeychainServiceBlobDatabase extends SQLiteOpenHelper { - private static final String DATABASE_NAME = "apg_blob.db"; - private static final int DATABASE_VERSION = 2; - - public static final String TABLE = "data"; - - public KeychainServiceBlobDatabase(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE + " ( " + BaseColumns._ID - + " INTEGER PRIMARY KEY AUTOINCREMENT, " + BlobsColumns.KEY + " TEXT NOT NULL)"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - // no upgrade necessary yet - } -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java deleted file mode 100644 index 5693e6de2..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainServiceBlobProvider.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * Copyright (C) 2011 Markus Doits <markus.doits@googlemail.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.provider; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.Blobs; -import org.sufficientlysecure.keychain.provider.KeychainServiceBlobContract.BlobsColumns; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.ContentProvider; -import android.content.ContentUris; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.provider.BaseColumns; - - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.List; -import java.util.UUID; - -public class KeychainServiceBlobProvider extends ContentProvider { - private static final String STORE_PATH = Constants.path.APP_DIR + "/ApgBlobs"; - - private KeychainServiceBlobDatabase mBlobDatabase = null; - - public KeychainServiceBlobProvider() { - File dir = new File(STORE_PATH); - dir.mkdirs(); - } - - @Override - public boolean onCreate() { - mBlobDatabase = new KeychainServiceBlobDatabase(getContext()); - return true; - } - - /** {@inheritDoc} */ - @Override - public Uri insert(Uri uri, ContentValues ignored) { - // ContentValues are actually ignored, because we want to store a blob with no more - // information but have to create an record with the password generated here first - ContentValues vals = new ContentValues(); - - // Insert a random key in the database. This has to provided by the caller when updating or - // getting the blob - String password = UUID.randomUUID().toString(); - vals.put(BlobsColumns.KEY, password); - - SQLiteDatabase db = mBlobDatabase.getWritableDatabase(); - long newRowId = db.insert(KeychainServiceBlobDatabase.TABLE, null, vals); - Uri insertedUri = ContentUris.withAppendedId(Blobs.CONTENT_URI, newRowId); - - return Uri.withAppendedPath(insertedUri, password); - } - - /** {@inheritDoc} */ - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) throws SecurityException, - FileNotFoundException { - Log.d(Constants.TAG, "openFile() called with uri: " + uri.toString() + " and mode: " + mode); - - List<String> segments = uri.getPathSegments(); - if (segments.size() < 2) { - throw new SecurityException("Password not found in URI"); - } - String id = segments.get(0); - String key = segments.get(1); - - Log.d(Constants.TAG, "Got id: " + id + " and key: " + key); - - // get the data - SQLiteDatabase db = mBlobDatabase.getReadableDatabase(); - Cursor result = db.query(KeychainServiceBlobDatabase.TABLE, new String[] { BaseColumns._ID }, - BaseColumns._ID + " = ? and " + BlobsColumns.KEY + " = ?", - new String[] { id, key }, null, null, null); - - if (result.getCount() == 0) { - // either the key is wrong or no id exists - throw new FileNotFoundException("No file found with that ID and/or password"); - } - - File targetFile = new File(STORE_PATH, id); - if (mode.equals("w")) { - Log.d(Constants.TAG, "Try to open file w"); - if (!targetFile.exists()) { - try { - targetFile.createNewFile(); - } catch (IOException e) { - Log.e(Constants.TAG, "Got IEOException on creating new file", e); - throw new FileNotFoundException("Could not create file to write to"); - } - } - return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_WRITE_ONLY - | ParcelFileDescriptor.MODE_TRUNCATE); - } else if (mode.equals("r")) { - Log.d(Constants.TAG, "Try to open file r"); - if (!targetFile.exists()) { - throw new FileNotFoundException("Error: Could not find the file requested"); - } - return ParcelFileDescriptor.open(targetFile, ParcelFileDescriptor.MODE_READ_ONLY); - } - - return null; - } - - /** {@inheritDoc} */ - @Override - public String getType(Uri uri) { - return null; - } - - /** {@inheritDoc} */ - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - /** {@inheritDoc} */ - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - /** {@inheritDoc} */ - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } - -} diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java deleted file mode 100644 index 1683c7c0e..000000000 --- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ /dev/null @@ -1,809 +0,0 @@ -/* - * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.provider; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Date; - -import org.spongycastle.bcpg.ArmoredOutputStream; -import org.spongycastle.openpgp.PGPKeyRing; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; -import org.sufficientlysecure.keychain.pgp.PgpHelper; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; -import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; -import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; -import org.sufficientlysecure.keychain.service.remote.AppSettings; -import org.sufficientlysecure.keychain.util.IterableIterator; -import org.sufficientlysecure.keychain.util.Log; - -import android.content.ContentProviderOperation; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.OperationApplicationException; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.net.Uri; -import android.os.RemoteException; - -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, - new String[] { KeyRings._ID, KeyRings.KEY_RING_DATA }, null, null, null); - - PGPKeyRing keyRing = null; - if (cursor != null && cursor.moveToFirst()) { - int keyRingDataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA); - - byte[] data = cursor.getBlob(keyRingDataCol); - if (data != null) { - keyRing = PgpConversionHelper.BytesToPGPKeyRing(data); - } - } - - if (cursor != null) { - cursor.close(); - } - - return keyRing; - } - - /** - * 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)); - return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * 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) { - Uri queryUri = KeyRings.buildPublicKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); - return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * 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)); - return (PGPPublicKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * 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); - if (keyRing == null) { - return null; - } - - return keyRing.getPublicKey(keyId); - } - - /** - * 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)); - return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * 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) { - Uri queryUri = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); - return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * 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)); - return (PGPSecretKeyRing) getPGPKeyRing(context, queryUri); - } - - /** - * 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); - if (keyRing == null) { - return null; - } - - return keyRing.getSecretKey(keyId); - } - - /** - * 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 { - PGPPublicKey masterKey = keyRing.getPublicKey(); - long masterKeyId = masterKey.getKeyID(); - - // delete old version of this keyRing, which also deletes all keys and userIds on cascade - Uri deleteUri = KeyRings.buildPublicKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); - - try { - context.getContentResolver().delete(deleteUri, null, null); - } catch (UnsupportedOperationException e) { - Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e); - } - - ContentValues values = new ContentValues(); - values.put(KeyRings.MASTER_KEY_ID, masterKeyId); - values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); - - // insert new version of this keyRing - Uri uri = KeyRings.buildPublicKeyRingsUri(); - Uri insertedUri = context.getContentResolver().insert(uri, values); - long keyRingRowId = Long.valueOf(insertedUri.getLastPathSegment()); - - // save all keys and userIds included in keyRing object in database - ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); - - int rank = 0; - for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) { - operations.add(buildPublicKeyOperations(context, keyRingRowId, key, rank)); - ++rank; - } - - int userIdRank = 0; - for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) { - operations.add(buildPublicUserIdOperations(context, keyRingRowId, userId, userIdRank)); - ++userIdRank; - } - - try { - context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY, operations); - } catch (RemoteException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); - } catch (OperationApplicationException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); - } - } - - /** - * 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 { - PGPSecretKey masterKey = keyRing.getSecretKey(); - long masterKeyId = masterKey.getKeyID(); - - // delete old version of this keyRing, which also deletes all keys and userIds on cascade - Uri deleteUri = KeyRings.buildSecretKeyRingsByMasterKeyIdUri(Long.toString(masterKeyId)); - - try { - context.getContentResolver().delete(deleteUri, null, null); - } catch (UnsupportedOperationException e) { - Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e); - } - - ContentValues values = new ContentValues(); - values.put(KeyRings.MASTER_KEY_ID, masterKeyId); - values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); - - // insert new version of this keyRing - Uri uri = KeyRings.buildSecretKeyRingsUri(); - Uri insertedUri = context.getContentResolver().insert(uri, values); - long keyRingRowId = Long.valueOf(insertedUri.getLastPathSegment()); - - // save all keys and userIds included in keyRing object in database - ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); - - int rank = 0; - for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) { - operations.add(buildSecretKeyOperations(context, keyRingRowId, key, rank)); - ++rank; - } - - int userIdRank = 0; - for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) { - operations.add(buildSecretUserIdOperations(context, keyRingRowId, userId, userIdRank)); - ++userIdRank; - } - - try { - context.getContentResolver().applyBatch(KeychainContract.CONTENT_AUTHORITY, operations); - } catch (RemoteException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); - } catch (OperationApplicationException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); - } - } - - /** - * 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 { - ContentValues values = new ContentValues(); - values.put(Keys.KEY_ID, key.getKeyID()); - values.put(Keys.IS_MASTER_KEY, key.isMasterKey()); - values.put(Keys.ALGORITHM, key.getAlgorithm()); - values.put(Keys.KEY_SIZE, key.getBitStrength()); - values.put(Keys.CAN_SIGN, PgpKeyHelper.isSigningKey(key)); - values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key)); - values.put(Keys.IS_REVOKED, key.isRevoked()); - values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000); - Date expiryDate = PgpKeyHelper.getExpiryDate(key); - if (expiryDate != null) { - values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); - } - values.put(Keys.KEY_RING_ROW_ID, keyRingRowId); - values.put(Keys.KEY_DATA, key.getEncoded()); - values.put(Keys.RANK, rank); - - Uri uri = Keys.buildPublicKeysUri(Long.toString(keyRingRowId)); - - return ContentProviderOperation.newInsert(uri).withValues(values).build(); - } - - /** - * 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) { - ContentValues values = new ContentValues(); - values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId); - values.put(UserIds.USER_ID, userId); - values.put(UserIds.RANK, rank); - - Uri uri = UserIds.buildPublicUserIdsUri(Long.toString(keyRingRowId)); - - return ContentProviderOperation.newInsert(uri).withValues(values).build(); - } - - /** - * 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 { - ContentValues values = new ContentValues(); - - boolean has_private = true; - if (key.isMasterKey()) { - if (PgpKeyHelper.isSecretKeyPrivateEmpty(key)) { - has_private = false; - } - } - - values.put(Keys.KEY_ID, key.getKeyID()); - values.put(Keys.IS_MASTER_KEY, key.isMasterKey()); - values.put(Keys.ALGORITHM, key.getPublicKey().getAlgorithm()); - values.put(Keys.KEY_SIZE, key.getPublicKey().getBitStrength()); - values.put(Keys.CAN_CERTIFY, (PgpKeyHelper.isCertificationKey(key) && has_private)); - values.put(Keys.CAN_SIGN, (PgpKeyHelper.isSigningKey(key) && has_private)); - values.put(Keys.CAN_ENCRYPT, PgpKeyHelper.isEncryptionKey(key)); - values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked()); - values.put(Keys.CREATION, PgpKeyHelper.getCreationDate(key).getTime() / 1000); - Date expiryDate = PgpKeyHelper.getExpiryDate(key); - if (expiryDate != null) { - values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); - } - values.put(Keys.KEY_RING_ROW_ID, keyRingRowId); - values.put(Keys.KEY_DATA, key.getEncoded()); - values.put(Keys.RANK, rank); - - Uri uri = Keys.buildSecretKeysUri(Long.toString(keyRingRowId)); - - return ContentProviderOperation.newInsert(uri).withValues(values).build(); - } - - /** - * 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) { - ContentValues values = new ContentValues(); - values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId); - values.put(UserIds.USER_ID, userId); - values.put(UserIds.RANK, rank); - - Uri uri = UserIds.buildSecretUserIdsUri(Long.toString(keyRingRowId)); - - return ContentProviderOperation.newInsert(uri).withValues(values).build(); - } - - /** - * Private helper method - * - * @param context - * @param queryUri - * @return - */ - private static ArrayList<Long> getKeyRingsMasterKeyIds(Context context, Uri queryUri) { - Cursor cursor = context.getContentResolver().query(queryUri, - new String[] { KeyRings.MASTER_KEY_ID }, null, null, null); - - ArrayList<Long> masterKeyIds = new ArrayList<Long>(); - if (cursor != null) { - int masterKeyIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID); - if (cursor.moveToFirst()) { - do { - masterKeyIds.add(cursor.getLong(masterKeyIdCol)); - } while (cursor.moveToNext()); - } - } - - if (cursor != null) { - cursor.close(); - } - - return masterKeyIds; - } - - /** - * Retrieves ids of all SecretKeyRings - * - * @param context - * @return - */ - public static ArrayList<Long> getSecretKeyRingsMasterKeyIds(Context context) { - Uri queryUri = KeyRings.buildSecretKeyRingsUri(); - return getKeyRingsMasterKeyIds(context, queryUri); - } - - /** - * Retrieves ids of all PublicKeyRings - * - * @param context - * @return - */ - public static ArrayList<Long> getPublicKeyRingsMasterKeyIds(Context context) { - Uri queryUri = KeyRings.buildPublicKeyRingsUri(); - return getKeyRingsMasterKeyIds(context, queryUri); - } - - public static void deletePublicKeyRing(Context context, long rowId) { - ContentResolver cr = context.getContentResolver(); - cr.delete(KeyRings.buildPublicKeyRingsUri(Long.toString(rowId)), null, null); - } - - public static void deleteSecretKeyRing(Context context, long rowId) { - ContentResolver cr = context.getContentResolver(); - cr.delete(KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)), null, null); - } - - /** - * 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)); - return getMasterKeyId(context, queryUri); - } - - /** - * 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)); - return getMasterKeyCanSign(context, queryUri, keyRingRowId); - } - - /** - * 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[] { - KeyRings.MASTER_KEY_ID, - "(SELECT COUNT(sign_keys." + Keys._ID + ") FROM " + Tables.KEYS - + " AS sign_keys WHERE sign_keys." + Keys.KEY_RING_ROW_ID + " = " - + KeychainDatabase.Tables.KEY_RINGS + "." + KeyRings._ID - + " AND sign_keys." + Keys.CAN_SIGN + " = '1' AND " + Keys.IS_MASTER_KEY - + " = 1) AS sign", }; - - 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("sign"); - - masterKeyId = cursor.getLong(masterKeyIdCol); - } - - if (cursor != null) { - cursor.close(); - } - - return (masterKeyId > 0); - } - - /** - * 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)); - return getMasterKeyId(context, queryUri); - } - - /** - * Private helper method to get master key id of keyring by its row id - * - * @param context - * @param queryUri - * @param keyRingRowId - * @return - */ - public static long getMasterKeyId(Context context, Uri queryUri) { - String[] projection = new String[] { KeyRings.MASTER_KEY_ID }; - - 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); - } - - if (cursor != null) { - cursor.close(); - } - - return masterKeyId; - } - - public static ArrayList<String> getPublicKeyRingsAsArmoredString(Context context, - long[] masterKeyIds) { - return getKeyRingsAsArmoredString(context, KeyRings.buildPublicKeyRingsUri(), masterKeyIds); - } - - public static ArrayList<String> getSecretKeyRingsAsArmoredString(Context context, - long[] masterKeyIds) { - return getKeyRingsAsArmoredString(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds); - } - - public static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri, - long[] masterKeyIds) { - ArrayList<String> output = new ArrayList<String>(); - - if (masterKeyIds != null && masterKeyIds.length > 0) { - - Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds); - - if (cursor != null) { - int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID); - int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA); - if (cursor.moveToFirst()) { - do { - Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol)); - - // get actual keyring data blob and write it to ByteArrayOutputStream - try { - Object keyRing = null; - byte[] data = cursor.getBlob(dataCol); - if (data != null) { - keyRing = PgpConversionHelper.BytesToPGPKeyRing(data); - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ArmoredOutputStream aos = new ArmoredOutputStream(bos); - aos.setHeader("Version", PgpHelper.getFullVersion(context)); - - if (keyRing instanceof PGPSecretKeyRing) { - aos.write(((PGPSecretKeyRing) keyRing).getEncoded()); - } else if (keyRing instanceof PGPPublicKeyRing) { - aos.write(((PGPPublicKeyRing) keyRing).getEncoded()); - } - aos.close(); - - String armoredKey = bos.toString("UTF-8"); - - Log.d(Constants.TAG, "armouredKey:" + armoredKey); - - output.add(armoredKey); - } catch (IOException e) { - Log.e(Constants.TAG, "IOException", e); - } - } while (cursor.moveToNext()); - } - } - - if (cursor != null) { - cursor.close(); - } - - } else { - Log.e(Constants.TAG, "No master keys given!"); - } - - if (output.size() > 0) { - return output; - } else { - return null; - } - } - - 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(); - - if (masterKeyIds != null && masterKeyIds.length > 0) { - - Cursor cursor = getCursorWithSelectedKeyringMasterKeyIds(context, uri, masterKeyIds); - - if (cursor != null) { - int masterIdCol = cursor.getColumnIndex(KeyRings.MASTER_KEY_ID); - int dataCol = cursor.getColumnIndex(KeyRings.KEY_RING_DATA); - if (cursor.moveToFirst()) { - do { - Log.d(Constants.TAG, "masterKeyId: " + cursor.getLong(masterIdCol)); - - // get actual keyring data blob and write it to ByteArrayOutputStream - try { - bos.write(cursor.getBlob(dataCol)); - } catch (IOException e) { - Log.e(Constants.TAG, "IOException", e); - } - } while (cursor.moveToNext()); - } - } - - if (cursor != null) { - cursor.close(); - } - - } else { - Log.e(Constants.TAG, "No master keys given!"); - } - - return bos.toByteArray(); - } - - private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, Uri baseUri, - long[] masterKeyIds) { - Cursor cursor = null; - if (masterKeyIds != null && masterKeyIds.length > 0) { - - String inMasterKeyList = KeyRings.MASTER_KEY_ID + " IN ("; - for (int i = 0; i < masterKeyIds.length; ++i) { - if (i != 0) { - inMasterKeyList += ", "; - } - inMasterKeyList += DatabaseUtils.sqlEscapeString("" + masterKeyIds[i]); - } - inMasterKeyList += ")"; - - cursor = context.getContentResolver().query(baseUri, - new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.KEY_RING_DATA }, - inMasterKeyList, null, null); - } - - return cursor; - } - - public static ArrayList<String> getRegisteredApiApps(Context context) { - Cursor cursor = context.getContentResolver().query(ApiApps.CONTENT_URI, null, null, null, - null); - - ArrayList<String> packageNames = new ArrayList<String>(); - if (cursor != null) { - int packageNameCol = cursor.getColumnIndex(ApiApps.PACKAGE_NAME); - if (cursor.moveToFirst()) { - do { - packageNames.add(cursor.getString(packageNameCol)); - } while (cursor.moveToNext()); - } - } - - if (cursor != null) { - cursor.close(); - } - - return packageNames; - } - - private static ContentValues contentValueForApiApps(AppSettings appSettings) { - ContentValues values = new ContentValues(); - values.put(ApiApps.PACKAGE_NAME, appSettings.getPackageName()); - values.put(ApiApps.PACKAGE_SIGNATURE, appSettings.getPackageSignature()); - values.put(ApiApps.KEY_ID, appSettings.getKeyId()); - values.put(ApiApps.COMPRESSION, appSettings.getCompression()); - values.put(ApiApps.ENCRYPTION_ALGORITHM, appSettings.getEncryptionAlgorithm()); - values.put(ApiApps.HASH_ALORITHM, appSettings.getHashAlgorithm()); - - return values; - } - - public static void insertApiApp(Context context, AppSettings appSettings) { - context.getContentResolver().insert(ApiApps.CONTENT_URI, - contentValueForApiApps(appSettings)); - } - - public static void updateApiApp(Context context, AppSettings appSettings, Uri uri) { - if (context.getContentResolver().update(uri, contentValueForApiApps(appSettings), null, - null) <= 0) { - throw new RuntimeException(); - } - } - - public static AppSettings getApiAppSettings(Context context, Uri uri) { - AppSettings settings = null; - - Cursor cur = context.getContentResolver().query(uri, null, null, null, null); - if (cur != null && cur.moveToFirst()) { - settings = new AppSettings(); - settings.setPackageName(cur.getString(cur - .getColumnIndex(KeychainContract.ApiApps.PACKAGE_NAME))); - settings.setPackageSignature(cur.getBlob(cur - .getColumnIndex(KeychainContract.ApiApps.PACKAGE_SIGNATURE))); - settings.setKeyId(cur.getLong(cur.getColumnIndex(KeychainContract.ApiApps.KEY_ID))); - settings.setCompression(cur.getInt(cur - .getColumnIndexOrThrow(KeychainContract.ApiApps.COMPRESSION))); - settings.setHashAlgorithm(cur.getInt(cur - .getColumnIndexOrThrow(KeychainContract.ApiApps.HASH_ALORITHM))); - settings.setEncryptionAlgorithm(cur.getInt(cur - .getColumnIndexOrThrow(KeychainContract.ApiApps.ENCRYPTION_ALGORITHM))); - } - - return settings; - } - - public static byte[] getApiAppSignature(Context context, String packageName) { - Uri queryUri = KeychainContract.ApiApps.buildByPackageNameUri(packageName); - - String[] projection = new String[] { ApiApps.PACKAGE_SIGNATURE }; - - ContentResolver cr = context.getContentResolver(); - Cursor cursor = cr.query(queryUri, projection, null, null, null); - - byte[] signature = null; - if (cursor != null && cursor.moveToFirst()) { - int signatureCol = 0; - - signature = cursor.getBlob(signatureCol); - } - - if (cursor != null) { - cursor.close(); - } - - return signature; - } -} |