From fb49f9e9c8d1b6d27a489c047431925974738a24 Mon Sep 17 00:00:00 2001 From: Dominik Date: Tue, 18 Sep 2012 18:35:14 +0200 Subject: [PATCH] started restructuring APGs Provider and Database --- org_apg/AndroidManifest.xml | 4 +- .../src/org/thialfihar/android/apg/Id.java | 8 +- .../android/apg/deprecated/DataProvider.java | 381 +++++++++++ .../android/apg/deprecated/Database.java | 617 ++++++++++++++++++ .../android/apg/helper/PGPMain.java | 146 ++--- .../android/apg/provider/ApgContract.java | 235 +++++++ .../android/apg/provider/ApgDatabase.java | 143 ++++ .../android/apg/provider/ApgProvider.java | 589 +++++++++++++++++ .../android/apg/provider/DataProvider.java | 381 ----------- .../android/apg/provider/Database.java | 617 ------------------ .../android/apg/provider/KeyRings.java | 33 - .../thialfihar/android/apg/provider/Keys.java | 51 -- .../android/apg/provider/ProviderHelper.java | 79 +++ .../android/apg/provider/UserIds.java | 31 - .../android/apg/service/ApgService.java | 32 +- .../android/apg/ui/DecryptActivity.java | 7 +- .../android/apg/ui/EditKeyActivity.java | 24 +- .../android/apg/ui/EncryptActivity.java | 2 +- .../android/apg/ui/SecretKeyListActivity.java | 2 +- .../android/apg/ui/SignKeyActivity.java | 2 +- .../ui/dialog/PassphraseDialogFragment.java | 8 +- .../android/apg/util/Compatibility.java | 3 +- 22 files changed, 2163 insertions(+), 1232 deletions(-) create mode 100644 org_apg/src/org/thialfihar/android/apg/deprecated/DataProvider.java create mode 100644 org_apg/src/org/thialfihar/android/apg/deprecated/Database.java create mode 100644 org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java create mode 100644 org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java create mode 100644 org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java delete mode 100644 org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java delete mode 100644 org_apg/src/org/thialfihar/android/apg/provider/Database.java delete mode 100644 org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java delete mode 100644 org_apg/src/org/thialfihar/android/apg/provider/Keys.java create mode 100644 org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java delete mode 100644 org_apg/src/org/thialfihar/android/apg/provider/UserIds.java diff --git a/org_apg/AndroidManifest.xml b/org_apg/AndroidManifest.xml index dfa366de3..deb62a622 100644 --- a/org_apg/AndroidManifest.xml +++ b/org_apg/AndroidManifest.xml @@ -46,7 +46,7 @@ --> @@ -339,7 +339,7 @@ diff --git a/org_apg/src/org/thialfihar/android/apg/Id.java b/org_apg/src/org/thialfihar/android/apg/Id.java index 4c83437a1..e683f43b4 100644 --- a/org_apg/src/org/thialfihar/android/apg/Id.java +++ b/org_apg/src/org/thialfihar/android/apg/Id.java @@ -147,10 +147,10 @@ public final class Id { public static final int export_keys = 0x21070002; } - public static final class database { - public static final int type_public = 0; - public static final int type_secret = 1; - } +// public static final class database { +// public static final int type_public = 0; +// public static final int type_secret = 1; +// } public static final class type { public static final int public_key = 0x21070001; diff --git a/org_apg/src/org/thialfihar/android/apg/deprecated/DataProvider.java b/org_apg/src/org/thialfihar/android/apg/deprecated/DataProvider.java new file mode 100644 index 000000000..e377fc8c4 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/deprecated/DataProvider.java @@ -0,0 +1,381 @@ +///* +// * Copyright (C) 2010 Thialfihar +// * +// * 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.thialfihar.android.apg.deprecated; +// +//import java.io.File; +//import java.io.FileNotFoundException; +//import java.util.HashMap; +// +//import org.thialfihar.android.apg.Id; +// +//import android.content.ContentProvider; +//import android.content.ContentValues; +//import android.content.UriMatcher; +//import android.database.Cursor; +//import android.database.DatabaseUtils; +//import android.database.sqlite.SQLiteQueryBuilder; +//import android.net.Uri; +//import android.os.ParcelFileDescriptor; +//import android.text.TextUtils; +// +//public class DataProvider extends ContentProvider { +// public static final String AUTHORITY = "org.thialfihar.android.apg.provider"; +// +// private static final int PUBLIC_KEY_RING = 101; +// private static final int PUBLIC_KEY_RING_ID = 102; +// private static final int PUBLIC_KEY_RING_BY_KEY_ID = 103; +// private static final int PUBLIC_KEY_RING_BY_EMAILS = 104; +// private static final int PUBLIC_KEY_RING_KEY = 111; +// private static final int PUBLIC_KEY_RING_KEY_RANK = 112; +// private static final int PUBLIC_KEY_RING_USER_ID = 121; +// private static final int PUBLIC_KEY_RING_USER_ID_RANK = 122; +// +// private static final int SECRET_KEY_RING = 201; +// private static final int SECRET_KEY_RING_ID = 202; +// private static final int SECRET_KEY_RING_BY_KEY_ID = 203; +// private static final int SECRET_KEY_RING_BY_EMAILS = 204; +// private static final int SECRET_KEY_RING_KEY = 211; +// private static final int SECRET_KEY_RING_KEY_RANK = 212; +// private static final int SECRET_KEY_RING_USER_ID = 221; +// private static final int SECRET_KEY_RING_USER_ID_RANK = 222; +// +// private static final int DATA_STREAM = 301; +// +// private static final String PUBLIC_KEY_RING_CONTENT_DIR_TYPE = +// "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key_ring"; +// private static final String PUBLIC_KEY_RING_CONTENT_ITEM_TYPE = +// "vnd.android.cursor.item/vnd.thialfihar.apg.public.key_ring"; +// +// private static final String PUBLIC_KEY_CONTENT_DIR_TYPE = +// "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key"; +// private static final String PUBLIC_KEY_CONTENT_ITEM_TYPE = +// "vnd.android.cursor.item/vnd.thialfihar.apg.public.key"; +// +// private static final String SECRET_KEY_RING_CONTENT_DIR_TYPE = +// "vnd.android.cursor.dir/vnd.thialfihar.apg.secret.key_ring"; +// private static final String SECRET_KEY_RING_CONTENT_ITEM_TYPE = +// "vnd.android.cursor.item/vnd.thialfihar.apg.secret.key_ring"; +// +// private static final String SECRET_KEY_CONTENT_DIR_TYPE = +// "vnd.android.cursor.dir/vnd.thialfihar.apg.secret.key"; +// private static final String SECRET_KEY_CONTENT_ITEM_TYPE = +// "vnd.android.cursor.item/vnd.thialfihar.apg.secret.key"; +// +// private static final String USER_ID_CONTENT_DIR_TYPE = +// "vnd.android.cursor.dir/vnd.thialfihar.apg.user_id"; +// private static final String USER_ID_CONTENT_ITEM_TYPE = +// "vnd.android.cursor.item/vnd.thialfihar.apg.user_id"; +// +// public static final String _ID = "_id"; +// public static final String MASTER_KEY_ID = "master_key_id"; +// public static final String KEY_ID = "key_id"; +// public static final String USER_ID = "user_id"; +// +// private static final UriMatcher mUriMatcher; +// +// private Database mDb; +// +// static { +// mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/key_id/*", PUBLIC_KEY_RING_BY_KEY_ID); +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/emails/*", PUBLIC_KEY_RING_BY_EMAILS); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/keys", PUBLIC_KEY_RING_KEY); +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/keys/#", PUBLIC_KEY_RING_KEY_RANK); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/user_ids", PUBLIC_KEY_RING_USER_ID); +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/user_ids/#", PUBLIC_KEY_RING_USER_ID_RANK); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/public", PUBLIC_KEY_RING); +// mUriMatcher.addURI(AUTHORITY, "key_rings/public/*", PUBLIC_KEY_RING_ID); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/key_id/*", SECRET_KEY_RING_BY_KEY_ID); +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/emails/*", SECRET_KEY_RING_BY_EMAILS); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/keys", SECRET_KEY_RING_KEY); +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/keys/#", SECRET_KEY_RING_KEY_RANK); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/user_ids", SECRET_KEY_RING_USER_ID); +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/user_ids/#", SECRET_KEY_RING_USER_ID_RANK); +// +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret", SECRET_KEY_RING); +// mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*", SECRET_KEY_RING_ID); +// +// mUriMatcher.addURI(AUTHORITY, "data/*", DATA_STREAM); +// } +// +// @Override +// public boolean onCreate() { +// mDb = new Database(getContext()); +// return true; +// } +// +// @Override +// public Cursor query(Uri uri, String[] projection, String selection, +// String[] selectionArgs, String sortOrder) { +// // TODO: implement the others, then use them for the lists +// SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); +// HashMap projectionMap = new HashMap(); +// +// int match = mUriMatcher.match(uri); +// int type; +// switch (match) { +// case PUBLIC_KEY_RING: +// case PUBLIC_KEY_RING_ID: +// case PUBLIC_KEY_RING_BY_KEY_ID: +// case PUBLIC_KEY_RING_BY_EMAILS: +// case PUBLIC_KEY_RING_KEY: +// case PUBLIC_KEY_RING_KEY_RANK: +// case PUBLIC_KEY_RING_USER_ID: +// case PUBLIC_KEY_RING_USER_ID_RANK: +// type = Id.database.type_public; +// break; +// +// case SECRET_KEY_RING: +// case SECRET_KEY_RING_ID: +// case SECRET_KEY_RING_BY_KEY_ID: +// case SECRET_KEY_RING_BY_EMAILS: +// case SECRET_KEY_RING_KEY: +// case SECRET_KEY_RING_KEY_RANK: +// case SECRET_KEY_RING_USER_ID: +// case SECRET_KEY_RING_USER_ID_RANK: +// type = Id.database.type_secret; +// break; +// +// default: { +// throw new IllegalArgumentException("Unknown URI " + uri); +// } +// } +// +// qb.appendWhere(KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = " + type); +// +// switch (match) { +// case PUBLIC_KEY_RING_ID: +// case SECRET_KEY_RING_ID: { +// qb.appendWhere(" AND " + +// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID + " = "); +// qb.appendWhereEscapeString(uri.getPathSegments().get(2)); +// +// // break omitted intentionally +// } +// +// case PUBLIC_KEY_RING: +// case SECRET_KEY_RING: { +// qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + +// "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + +// Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + +// Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + +// ") " + +// " INNER JOIN " + UserIds.TABLE_NAME + " ON " + +// "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + +// UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + +// UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); +// +// projectionMap.put(_ID, +// KeyRings.TABLE_NAME + "." + KeyRings._ID); +// projectionMap.put(MASTER_KEY_ID, +// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID); +// projectionMap.put(USER_ID, +// UserIds.TABLE_NAME + "." + UserIds.USER_ID); +// +// if (TextUtils.isEmpty(sortOrder)) { +// sortOrder = UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC"; +// } +// +// break; +// } +// +// case SECRET_KEY_RING_BY_KEY_ID: +// case PUBLIC_KEY_RING_BY_KEY_ID: { +// qb.setTables(Keys.TABLE_NAME + " AS tmp INNER JOIN " + +// KeyRings.TABLE_NAME + " ON (" + +// KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + +// "tmp." + Keys.KEY_RING_ID + ")" + +// " INNER JOIN " + Keys.TABLE_NAME + " ON " + +// "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + +// Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + +// Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + +// ") " + +// " INNER JOIN " + UserIds.TABLE_NAME + " ON " + +// "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + +// UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + +// UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); +// +// projectionMap.put(_ID, +// KeyRings.TABLE_NAME + "." + KeyRings._ID); +// projectionMap.put(MASTER_KEY_ID, +// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID); +// projectionMap.put(USER_ID, +// UserIds.TABLE_NAME + "." + UserIds.USER_ID); +// +// qb.appendWhere(" AND tmp." + Keys.KEY_ID + " = "); +// qb.appendWhereEscapeString(uri.getPathSegments().get(3)); +// +// break; +// } +// +// case SECRET_KEY_RING_BY_EMAILS: +// case PUBLIC_KEY_RING_BY_EMAILS: { +// qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + +// "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + +// Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + +// Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + +// ") " + +// " INNER JOIN " + UserIds.TABLE_NAME + " ON " + +// "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + +// UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + +// UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); +// +// projectionMap.put(_ID, +// KeyRings.TABLE_NAME + "." + KeyRings._ID); +// projectionMap.put(MASTER_KEY_ID, +// KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID); +// projectionMap.put(USER_ID, +// UserIds.TABLE_NAME + "." + UserIds.USER_ID); +// +// String emails = uri.getPathSegments().get(3); +// 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." + UserIds.USER_ID + " LIKE "; +// // match '*', 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." + UserIds._ID + +// " FROM " + UserIds.TABLE_NAME + +// " AS tmp WHERE tmp." + UserIds.KEY_ID + " = " + +// Keys.TABLE_NAME + "." + Keys._ID + +// " AND (" + emailWhere + "))"); +// } +// +// break; +// } +// +// default: { +// throw new IllegalArgumentException("Unknown URI " + uri); +// } +// } +// +// qb.setProjectionMap(projectionMap); +// +// // If no sort order is specified use the default +// String orderBy; +// if (TextUtils.isEmpty(sortOrder)) { +// orderBy = null; +// } else { +// orderBy = sortOrder; +// } +// +// //System.out.println(qb.buildQuery(projection, selection, selectionArgs, null, null, sortOrder, null).replace("WHERE", "WHERE\n")); +// Cursor c = qb.query(mDb.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); +// return c; +// } +// +// @Override +// public String getType(Uri uri) { +// switch (mUriMatcher.match(uri)) { +// case PUBLIC_KEY_RING: +// case PUBLIC_KEY_RING_BY_EMAILS: +// return PUBLIC_KEY_RING_CONTENT_DIR_TYPE; +// +// case PUBLIC_KEY_RING_ID: +// return PUBLIC_KEY_RING_CONTENT_ITEM_TYPE; +// +// case PUBLIC_KEY_RING_BY_KEY_ID: +// return PUBLIC_KEY_RING_CONTENT_ITEM_TYPE; +// +// case PUBLIC_KEY_RING_KEY: +// return PUBLIC_KEY_CONTENT_DIR_TYPE; +// +// case PUBLIC_KEY_RING_KEY_RANK: +// return PUBLIC_KEY_CONTENT_ITEM_TYPE; +// +// case PUBLIC_KEY_RING_USER_ID: +// return USER_ID_CONTENT_DIR_TYPE; +// +// case PUBLIC_KEY_RING_USER_ID_RANK: +// return USER_ID_CONTENT_ITEM_TYPE; +// +// case SECRET_KEY_RING: +// case SECRET_KEY_RING_BY_EMAILS: +// return SECRET_KEY_RING_CONTENT_DIR_TYPE; +// +// case SECRET_KEY_RING_ID: +// return SECRET_KEY_RING_CONTENT_ITEM_TYPE; +// +// case SECRET_KEY_RING_BY_KEY_ID: +// return SECRET_KEY_RING_CONTENT_ITEM_TYPE; +// +// case SECRET_KEY_RING_KEY: +// return SECRET_KEY_CONTENT_DIR_TYPE; +// +// case SECRET_KEY_RING_KEY_RANK: +// return SECRET_KEY_CONTENT_ITEM_TYPE; +// +// case SECRET_KEY_RING_USER_ID: +// return USER_ID_CONTENT_DIR_TYPE; +// +// case SECRET_KEY_RING_USER_ID_RANK: +// return USER_ID_CONTENT_ITEM_TYPE; +// +// default: +// throw new IllegalArgumentException("Unknown URI " + uri); +// } +// } +// +// @Override +// public Uri insert(Uri uri, ContentValues initialValues) { +// // not supported +// return null; +// } +// +// @Override +// public int delete(Uri uri, String where, String[] whereArgs) { +// // not supported +// return 0; +// } +// +// @Override +// public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { +// // not supported +// return 0; +// } +// +// @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.getPathSegments().get(1); +// File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName); +// return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); +// } +//} diff --git a/org_apg/src/org/thialfihar/android/apg/deprecated/Database.java b/org_apg/src/org/thialfihar/android/apg/deprecated/Database.java new file mode 100644 index 000000000..92bbaed4f --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/deprecated/Database.java @@ -0,0 +1,617 @@ +///* +// * 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.thialfihar.android.apg.deprecated; +// +//import org.spongycastle.openpgp.PGPException; +//import org.spongycastle.openpgp.PGPPublicKey; +//import org.spongycastle.openpgp.PGPPublicKeyRing; +//import org.spongycastle.openpgp.PGPSecretKey; +//import org.spongycastle.openpgp.PGPSecretKeyRing; +//import org.thialfihar.android.apg.Id; +//import org.thialfihar.android.apg.helper.PGPHelper; +//import org.thialfihar.android.apg.util.IterableIterator; +// +//import android.content.ContentValues; +//import android.content.Context; +//import android.database.Cursor; +//import android.database.sqlite.SQLiteDatabase; +//import android.database.sqlite.SQLiteOpenHelper; +//import org.thialfihar.android.apg.util.Log; +// +//import java.io.IOException; +//import java.util.Date; +//import java.util.HashMap; +//import java.util.Vector; +// +//public class Database extends SQLiteOpenHelper { +// public static class GeneralException extends Exception { +// static final long serialVersionUID = 0xf812773343L; +// +// public GeneralException(String message) { +// super(message); +// } +// } +// +// private static final String DATABASE_NAME = "apg"; +// private static final int DATABASE_VERSION = 2; +// +// public static final String AUTHORITY = "org.thialfihar.android.apg.database"; +// +// public static HashMap sKeyRingsProjection; +// public static HashMap sKeysProjection; +// public static HashMap sUserIdsProjection; +// +// private SQLiteDatabase mDb = null; +// private int mStatus = 0; +// +// static { +// sKeyRingsProjection = new HashMap(); +// sKeyRingsProjection.put(KeyRings._ID, KeyRings._ID); +// sKeyRingsProjection.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID); +// sKeyRingsProjection.put(KeyRings.TYPE, KeyRings.TYPE); +// sKeyRingsProjection.put(KeyRings.WHO_ID, KeyRings.WHO_ID); +// sKeyRingsProjection.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA); +// +// sKeysProjection = new HashMap(); +// sKeysProjection.put(Keys._ID, Keys._ID); +// sKeysProjection.put(Keys.KEY_ID, Keys.KEY_ID); +// sKeysProjection.put(Keys.TYPE, Keys.TYPE); +// sKeysProjection.put(Keys.IS_MASTER_KEY, Keys.IS_MASTER_KEY); +// sKeysProjection.put(Keys.ALGORITHM, Keys.ALGORITHM); +// sKeysProjection.put(Keys.KEY_SIZE, Keys.KEY_SIZE); +// sKeysProjection.put(Keys.CAN_SIGN, Keys.CAN_SIGN); +// sKeysProjection.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT); +// sKeysProjection.put(Keys.IS_REVOKED, Keys.IS_REVOKED); +// sKeysProjection.put(Keys.CREATION, Keys.CREATION); +// sKeysProjection.put(Keys.EXPIRY, Keys.EXPIRY); +// sKeysProjection.put(Keys.KEY_DATA, Keys.KEY_DATA); +// sKeysProjection.put(Keys.RANK, Keys.RANK); +// +// sUserIdsProjection = new HashMap(); +// sUserIdsProjection.put(UserIds._ID, UserIds._ID); +// sUserIdsProjection.put(UserIds.KEY_ID, UserIds.KEY_ID); +// sUserIdsProjection.put(UserIds.USER_ID, UserIds.USER_ID); +// sUserIdsProjection.put(UserIds.RANK, UserIds.RANK); +// } +// +// public Database(Context context) { +// super(context, DATABASE_NAME, null, DATABASE_VERSION); +// // force upgrade to test things +// //onUpgrade(getWritableDatabase(), 1, 2); +// mDb = getWritableDatabase(); +// } +// +// @Override +// protected void finalize() throws Throwable { +// mDb.close(); +// super.finalize(); +// } +// +// @Override +// public void onCreate(SQLiteDatabase db) { +// db.execSQL("CREATE TABLE " + KeyRings.TABLE_NAME + " (" + +// KeyRings._ID + " " + KeyRings._ID_type + "," + +// KeyRings.MASTER_KEY_ID + " " + KeyRings.MASTER_KEY_ID_type + ", " + +// KeyRings.TYPE + " " + KeyRings.TYPE_type + ", " + +// KeyRings.WHO_ID + " " + KeyRings.WHO_ID_type + ", " + +// KeyRings.KEY_RING_DATA + " " + KeyRings.KEY_RING_DATA_type + ");"); +// +// db.execSQL("CREATE TABLE " + Keys.TABLE_NAME + " (" + +// Keys._ID + " " + Keys._ID_type + "," + +// Keys.KEY_ID + " " + Keys.KEY_ID_type + ", " + +// Keys.TYPE + " " + Keys.TYPE_type + ", " + +// Keys.IS_MASTER_KEY + " " + Keys.IS_MASTER_KEY_type + ", " + +// Keys.ALGORITHM + " " + Keys.ALGORITHM_type + ", " + +// Keys.KEY_SIZE + " " + Keys.KEY_SIZE_type + ", " + +// Keys.CAN_SIGN + " " + Keys.CAN_SIGN_type + ", " + +// Keys.CAN_ENCRYPT + " " + Keys.CAN_ENCRYPT_type + ", " + +// Keys.IS_REVOKED + " " + Keys.IS_REVOKED_type + ", " + +// Keys.CREATION + " " + Keys.CREATION_type + ", " + +// Keys.EXPIRY + " " + Keys.EXPIRY_type + ", " + +// Keys.KEY_RING_ID + " " + Keys.KEY_RING_ID_type + ", " + +// Keys.KEY_DATA + " " + Keys.KEY_DATA_type + +// Keys.RANK + " " + Keys.RANK_type + ");"); +// +// db.execSQL("CREATE TABLE " + UserIds.TABLE_NAME + " (" + +// UserIds._ID + " " + UserIds._ID_type + "," + +// UserIds.KEY_ID + " " + UserIds.KEY_ID_type + "," + +// UserIds.USER_ID + " " + UserIds.USER_ID_type + "," + +// UserIds.RANK + " " + UserIds.RANK_type + ");"); +// +// } +// +// @Override +// public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { +// mDb = db; +// for (int version = oldVersion; version < newVersion; ++version) { +// switch (version) { +// case 1: { // upgrade 1 to 2 +// db.execSQL("DROP TABLE IF EXISTS " + KeyRings.TABLE_NAME + ";"); +// db.execSQL("DROP TABLE IF EXISTS " + Keys.TABLE_NAME + ";"); +// db.execSQL("DROP TABLE IF EXISTS " + UserIds.TABLE_NAME + ";"); +// +// db.execSQL("CREATE TABLE " + KeyRings.TABLE_NAME + " (" + +// KeyRings._ID + " " + KeyRings._ID_type + "," + +// KeyRings.MASTER_KEY_ID + " " + KeyRings.MASTER_KEY_ID_type + ", " + +// KeyRings.TYPE + " " + KeyRings.TYPE_type + ", " + +// KeyRings.WHO_ID + " " + KeyRings.WHO_ID_type + ", " + +// KeyRings.KEY_RING_DATA + " " + KeyRings.KEY_RING_DATA_type + ");"); +// +// +// db.execSQL("CREATE TABLE " + Keys.TABLE_NAME + " (" + +// Keys._ID + " " + Keys._ID_type + "," + +// Keys.KEY_ID + " " + Keys.KEY_ID_type + ", " + +// Keys.TYPE + " " + Keys.TYPE_type + ", " + +// Keys.IS_MASTER_KEY + " " + Keys.IS_MASTER_KEY_type + ", " + +// Keys.ALGORITHM + " " + Keys.ALGORITHM_type + ", " + +// Keys.KEY_SIZE + " " + Keys.KEY_SIZE_type + ", " + +// Keys.CAN_SIGN + " " + Keys.CAN_SIGN_type + ", " + +// Keys.CAN_ENCRYPT + " " + Keys.CAN_ENCRYPT_type + ", " + +// Keys.IS_REVOKED + " " + Keys.IS_REVOKED_type + ", " + +// Keys.CREATION + " " + Keys.CREATION_type + ", " + +// Keys.EXPIRY + " " + Keys.EXPIRY_type + ", " + +// Keys.KEY_RING_ID + " " + Keys.KEY_RING_ID_type + ", " + +// Keys.KEY_DATA + " " + Keys.KEY_DATA_type + +// Keys.RANK + " " + Keys.RANK_type + ");"); +// +// db.execSQL("CREATE TABLE " + UserIds.TABLE_NAME + " (" + +// UserIds._ID + " " + UserIds._ID_type + "," + +// UserIds.KEY_ID + " " + UserIds.KEY_ID_type + "," + +// UserIds.USER_ID + " " + UserIds.USER_ID_type + "," + +// UserIds.RANK + " " + UserIds.RANK_type + ");"); +// +// Cursor cursor = db.query("public_keys", new String[] { "c_key_data" }, +// null, null, null, null, null); +// if (cursor != null && cursor.moveToFirst()) { +// do { +// byte[] data = cursor.getBlob(0); +// try { +// PGPPublicKeyRing keyRing = new PGPPublicKeyRing(data); +// saveKeyRing(keyRing); +// } catch (IOException e) { +// Log.e("apg.db.upgrade", "key import failed: " + e); +// } catch (GeneralException e) { +// Log.e("apg.db.upgrade", "key import failed: " + e); +// } +// } while (cursor.moveToNext()); +// } +// +// if (cursor != null) { +// cursor.close(); +// } +// +// cursor = db.query("secret_keys", new String[]{ "c_key_data" }, +// null, null, null, null, null); +// if (cursor != null && cursor.moveToFirst()) { +// do { +// byte[] data = cursor.getBlob(0); +// try { +// PGPSecretKeyRing keyRing = new PGPSecretKeyRing(data); +// saveKeyRing(keyRing); +// } catch (IOException e) { +// Log.e("apg.db.upgrade", "key import failed: " + e); +// } catch (PGPException e) { +// Log.e("apg.db.upgrade", "key import failed: " + e); +// } catch (GeneralException e) { +// Log.e("apg.db.upgrade", "key import failed: " + e); +// } +// } while (cursor.moveToNext()); +// } +// +// if (cursor != null) { +// cursor.close(); +// } +// +// db.execSQL("DROP TABLE IF EXISTS public_keys;"); +// db.execSQL("DROP TABLE IF EXISTS secret_keys;"); +// +// break; +// } +// +// default: { +// break; +// } +// } +// } +// mDb = null; +// } +// +// public int saveKeyRing(PGPPublicKeyRing keyRing) throws IOException, GeneralException { +// mDb.beginTransaction(); +// ContentValues values = new ContentValues(); +// PGPPublicKey masterKey = keyRing.getPublicKey(); +// long masterKeyId = masterKey.getKeyID(); +// +// values.put(KeyRings.MASTER_KEY_ID, masterKeyId); +// values.put(KeyRings.TYPE, Id.database.type_public); +// values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); +// +// long rowId = insertOrUpdateKeyRing(values); +// int returnValue = mStatus; +// +// if (rowId == -1) { +// throw new GeneralException("saving public key ring " + masterKeyId + " failed"); +// } +// +// Vector seenIds = new Vector(); +// int rank = 0; +// for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { +// seenIds.add(saveKey(rowId, key, rank)); +// ++rank; +// } +// +// String seenIdsStr = ""; +// for (Integer id : seenIds) { +// if (seenIdsStr.length() > 0) { +// seenIdsStr += ","; +// } +// seenIdsStr += id; +// } +// mDb.delete(Keys.TABLE_NAME, +// Keys.KEY_RING_ID + " = ? AND " + +// Keys._ID + " NOT IN (" + seenIdsStr + ")", +// new String[] { "" + rowId }); +// +// mDb.setTransactionSuccessful(); +// mDb.endTransaction(); +// return returnValue; +// } +// +// public int saveKeyRing(PGPSecretKeyRing keyRing) throws IOException, GeneralException { +// mDb.beginTransaction(); +// ContentValues values = new ContentValues(); +// PGPSecretKey masterKey = keyRing.getSecretKey(); +// long masterKeyId = masterKey.getKeyID(); +// +// values.put(KeyRings.MASTER_KEY_ID, masterKeyId); +// values.put(KeyRings.TYPE, Id.database.type_secret); +// values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); +// +// long rowId = insertOrUpdateKeyRing(values); +// int returnValue = mStatus; +// +// if (rowId == -1) { +// throw new GeneralException("saving secret key ring " + masterKeyId + " failed"); +// } +// +// Vector seenIds = new Vector(); +// int rank = 0; +// for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { +// seenIds.add(saveKey(rowId, key, rank)); +// ++rank; +// } +// +// String seenIdsStr = ""; +// for (Integer id : seenIds) { +// if (seenIdsStr.length() > 0) { +// seenIdsStr += ","; +// } +// seenIdsStr += id; +// } +// mDb.delete(Keys.TABLE_NAME, +// Keys.KEY_RING_ID + " = ? AND " + +// Keys._ID + " NOT IN (" + seenIdsStr + ")", +// new String[] { "" + rowId }); +// +// mDb.setTransactionSuccessful(); +// mDb.endTransaction(); +// return returnValue; +// } +// +// private int saveKey(long keyRingId, PGPPublicKey key, int rank) +// throws IOException, GeneralException { +// ContentValues values = new ContentValues(); +// +// values.put(Keys.KEY_ID, key.getKeyID()); +// values.put(Keys.TYPE, Id.database.type_public); +// 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, PGPHelper.isSigningKey(key)); +// values.put(Keys.CAN_ENCRYPT, PGPHelper.isEncryptionKey(key)); +// values.put(Keys.IS_REVOKED, key.isRevoked()); +// values.put(Keys.CREATION, PGPHelper.getCreationDate(key).getTime() / 1000); +// Date expiryDate = PGPHelper.getExpiryDate(key); +// if (expiryDate != null) { +// values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); +// } +// values.put(Keys.KEY_RING_ID, keyRingId); +// values.put(Keys.KEY_DATA, key.getEncoded()); +// values.put(Keys.RANK, rank); +// +// long rowId = insertOrUpdateKey(values); +// +// if (rowId == -1) { +// throw new GeneralException("saving public key " + key.getKeyID() + " failed"); +// } +// +// Vector seenIds = new Vector(); +// int userIdRank = 0; +// for (String userId : new IterableIterator(key.getUserIDs())) { +// seenIds.add(saveUserId(rowId, userId, userIdRank)); +// ++userIdRank; +// } +// +// String seenIdsStr = ""; +// for (Integer id : seenIds) { +// if (seenIdsStr.length() > 0) { +// seenIdsStr += ","; +// } +// seenIdsStr += id; +// } +// mDb.delete(UserIds.TABLE_NAME, +// UserIds.KEY_ID + " = ? AND " + +// UserIds._ID + " NOT IN (" + seenIdsStr + ")", +// new String[] { "" + rowId }); +// +// return (int)rowId; +// } +// +// private int saveKey(long keyRingId, PGPSecretKey key, int rank) +// throws IOException, GeneralException { +// ContentValues values = new ContentValues(); +// +// values.put(Keys.KEY_ID, key.getPublicKey().getKeyID()); +// values.put(Keys.TYPE, Id.database.type_secret); +// 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_SIGN, PGPHelper.isSigningKey(key)); +// values.put(Keys.CAN_ENCRYPT, PGPHelper.isEncryptionKey(key)); +// values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked()); +// values.put(Keys.CREATION, PGPHelper.getCreationDate(key).getTime() / 1000); +// Date expiryDate = PGPHelper.getExpiryDate(key); +// if (expiryDate != null) { +// values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); +// } +// values.put(Keys.KEY_RING_ID, keyRingId); +// values.put(Keys.KEY_DATA, key.getEncoded()); +// values.put(Keys.RANK, rank); +// +// long rowId = insertOrUpdateKey(values); +// +// if (rowId == -1) { +// throw new GeneralException("saving secret key " + key.getPublicKey().getKeyID() + " failed"); +// } +// +// Vector seenIds = new Vector(); +// int userIdRank = 0; +// for (String userId : new IterableIterator(key.getUserIDs())) { +// seenIds.add(saveUserId(rowId, userId, userIdRank)); +// ++userIdRank; +// } +// +// String seenIdsStr = ""; +// for (Integer id : seenIds) { +// if (seenIdsStr.length() > 0) { +// seenIdsStr += ","; +// } +// seenIdsStr += id; +// } +// mDb.delete(UserIds.TABLE_NAME, +// UserIds.KEY_ID + " = ? AND " + +// UserIds._ID + " NOT IN (" + seenIdsStr + ")", +// new String[] { "" + rowId }); +// +// return (int)rowId; +// } +// +// private int saveUserId(long keyId, String userId, int rank) throws GeneralException { +// ContentValues values = new ContentValues(); +// +// values.put(UserIds.KEY_ID, keyId); +// values.put(UserIds.USER_ID, userId); +// values.put(UserIds.RANK, rank); +// +// long rowId = insertOrUpdateUserId(values); +// +// if (rowId == -1) { +// throw new GeneralException("saving user id " + userId + " failed"); +// } +// +// return (int)rowId; +// } +// +// private long insertOrUpdateKeyRing(ContentValues values) { +// Cursor c = mDb.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, +// KeyRings.MASTER_KEY_ID + " = ? AND " + KeyRings.TYPE + " = ?", +// new String[] { +// values.getAsString(KeyRings.MASTER_KEY_ID), +// values.getAsString(KeyRings.TYPE), +// }, +// null, null, null); +// long rowId = -1; +// if (c != null && c.moveToFirst()) { +// rowId = c.getLong(0); +// mDb.update(KeyRings.TABLE_NAME, values, +// KeyRings._ID + " = ?", new String[] { "" + rowId }); +// mStatus = Id.return_value.updated; +// } else { +// rowId = mDb.insert(KeyRings.TABLE_NAME, KeyRings.WHO_ID, values); +// mStatus = Id.return_value.ok; +// } +// +// if (c != null) { +// c.close(); +// } +// +// return rowId; +// } +// +// private long insertOrUpdateKey(ContentValues values) { +// Cursor c = mDb.query(Keys.TABLE_NAME, new String[] { Keys._ID }, +// Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?", +// new String[] { +// values.getAsString(Keys.KEY_ID), +// values.getAsString(Keys.TYPE), +// }, +// null, null, null); +// long rowId = -1; +// if (c != null && c.moveToFirst()) { +// rowId = c.getLong(0); +// mDb.update(Keys.TABLE_NAME, values, +// Keys._ID + " = ?", new String[] { "" + rowId }); +// } else { +// rowId = mDb.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values); +// } +// +// if (c != null) { +// c.close(); +// } +// +// return rowId; +// } +// +// private long insertOrUpdateUserId(ContentValues values) { +// Cursor c = mDb.query(UserIds.TABLE_NAME, new String[] { UserIds._ID }, +// UserIds.KEY_ID + " = ? AND " + UserIds.USER_ID + " = ?", +// new String[] { +// values.getAsString(UserIds.KEY_ID), +// values.getAsString(UserIds.USER_ID), +// }, +// null, null, null); +// long rowId = -1; +// if (c != null && c.moveToFirst()) { +// rowId = c.getLong(0); +// mDb.update(UserIds.TABLE_NAME, values, +// UserIds._ID + " = ?", new String[] { "" + rowId }); +// } else { +// rowId = mDb.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values); +// } +// +// if (c != null) { +// c.close(); +// } +// +// return rowId; +// } +// +// public Object getKeyRing(int keyRingId) { +// Cursor c = mDb.query(KeyRings.TABLE_NAME, +// new String[] { KeyRings.KEY_RING_DATA, KeyRings.TYPE }, +// KeyRings._ID + " = ?", +// new String[] { +// "" + keyRingId, +// }, +// null, null, null); +// byte[] data = null; +// Object keyRing = null; +// if (c != null && c.moveToFirst()) { +// data = c.getBlob(0); +// if (data != null) { +// try { +// if (c.getInt(1) == Id.database.type_public) { +// keyRing = new PGPPublicKeyRing(data); +// } else { +// keyRing = new PGPSecretKeyRing(data); +// } +// } catch (IOException e) { +// // can't load it, then +// } catch (PGPException e) { +// // can't load it, then +// } +// } +// } +// +// if (c != null) { +// c.close(); +// } +// +// return keyRing; +// } +// +// public byte[] getKeyRingDataFromKeyId(int type, long keyId) { +// Cursor c = mDb.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON (" + +// KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + +// Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + ")", +// new String[] { KeyRings.TABLE_NAME + "." + KeyRings.KEY_RING_DATA }, +// Keys.TABLE_NAME + "." + Keys.KEY_ID + " = ? AND " + +// KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", +// new String[] { +// "" + keyId, +// "" + type, +// }, +// null, null, null); +// +// byte[] data = null; +// if (c != null && c.moveToFirst()) { +// data = c.getBlob(0); +// } +// +// if (c != null) { +// c.close(); +// } +// +// return data; +// } +// +// public byte[] getKeyDataFromKeyId(int type, long keyId) { +// Cursor c = mDb.query(Keys.TABLE_NAME, new String[] { Keys.KEY_DATA }, +// Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?", +// new String[] { +// "" + keyId, +// "" + type, +// }, +// null, null, null); +// byte[] data = null; +// if (c != null && c.moveToFirst()) { +// data = c.getBlob(0); +// } +// +// if (c != null) { +// c.close(); +// } +// +// return data; +// } +// +// public void deleteKeyRing(int keyRingId) { +// mDb.beginTransaction(); +// mDb.delete(KeyRings.TABLE_NAME, +// KeyRings._ID + " = ?", new String[] { "" + keyRingId }); +// +// Cursor c = mDb.query(Keys.TABLE_NAME, new String[] { Keys._ID }, +// Keys.KEY_RING_ID + " = ?", +// new String[] { +// "" + keyRingId, +// }, +// null, null, null); +// if (c != null && c.moveToFirst()) { +// do { +// int keyId = c.getInt(0); +// deleteKey(keyId); +// } while (c.moveToNext()); +// } +// +// if (c != null) { +// c.close(); +// } +// +// mDb.setTransactionSuccessful(); +// mDb.endTransaction(); +// } +// +// private void deleteKey(int keyId) { +// mDb.delete(Keys.TABLE_NAME, +// Keys._ID + " = ?", new String[] { "" + keyId }); +// +// mDb.delete(UserIds.TABLE_NAME, +// UserIds.KEY_ID + " = ?", new String[] { "" + keyId }); +// } +// +// public SQLiteDatabase db() { +// return mDb; +// } +//} diff --git a/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java index 3890de496..8a7ffc538 100644 --- a/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java +++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java @@ -72,11 +72,6 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePGPDataEncryptorBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyDataDecryptorFactoryBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePublicKeyKeyEncryptionMethodGenerator; -import org.thialfihar.android.apg.provider.DataProvider; -import org.thialfihar.android.apg.provider.Database; -import org.thialfihar.android.apg.provider.KeyRings; -import org.thialfihar.android.apg.provider.Keys; -import org.thialfihar.android.apg.provider.UserIds; import org.thialfihar.android.apg.service.ApgService; import org.thialfihar.android.apg.util.HkpKeyServer; import org.thialfihar.android.apg.util.InputData; @@ -142,21 +137,21 @@ public class PGPMain { // Not BC due to the use of Spongy Castle for Android public static final String BOUNCY_CASTLE_PROVIDER_NAME = "SC"; - public static final String AUTHORITY = DataProvider.AUTHORITY; + // public static final String AUTHORITY = DataProvider.AUTHORITY; - public static final Uri CONTENT_URI_SECRET_KEY_RINGS = Uri.parse("content://" + AUTHORITY - + "/key_rings/secret/"); - public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://" - + AUTHORITY + "/key_rings/secret/key_id/"); - public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://" - + AUTHORITY + "/key_rings/secret/emails/"); - - public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS = Uri.parse("content://" + AUTHORITY - + "/key_rings/public/"); - public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://" - + AUTHORITY + "/key_rings/public/key_id/"); - public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://" - + AUTHORITY + "/key_rings/public/emails/"); + // public static final Uri CONTENT_URI_SECRET_KEY_RINGS = Uri.parse("content://" + AUTHORITY + // + "/key_rings/secret/"); + // public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_KEY_ID = Uri.parse("content://" + // + AUTHORITY + "/key_rings/secret/key_id/"); + // public static final Uri CONTENT_URI_SECRET_KEY_RING_BY_EMAILS = Uri.parse("content://" + // + AUTHORITY + "/key_rings/secret/emails/"); + // + // public static final Uri CONTENT_URI_PUBLIC_KEY_RINGS = Uri.parse("content://" + AUTHORITY + // + "/key_rings/public/"); + // public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_KEY_ID = Uri.parse("content://" + // + AUTHORITY + "/key_rings/public/key_id/"); + // public static final Uri CONTENT_URI_PUBLIC_KEY_RING_BY_EMAILS = Uri.parse("content://" + // + AUTHORITY + "/key_rings/public/emails/"); private static String VERSION = null; @@ -184,12 +179,12 @@ public class PGPMain { private static String mEditPassPhrase = null; - private static Database mDatabase = null; + // private static Database mDatabase = null; - public static class GeneralException extends Exception { + public static class ApgGeneralException extends Exception { static final long serialVersionUID = 0xf812773342L; - public GeneralException(String message) { + public ApgGeneralException(String message) { super(message); } } @@ -202,15 +197,15 @@ public class PGPMain { } } - public static void initialize(Context context) { - if (mDatabase == null) { - mDatabase = new Database(context); - } - } - - public static Database getDatabase() { - return mDatabase; - } + // public static void initialize(Context context) { + // if (mDatabase == null) { + // mDatabase = new Database(context); + // } + // } + // + // public static Database getDatabase() { + // return mDatabase; + // } public static void setEditPassPhrase(String passPhrase) { mEditPassPhrase = passPhrase; @@ -248,16 +243,16 @@ public class PGPMain { * @throws NoSuchAlgorithmException * @throws PGPException * @throws NoSuchProviderException - * @throws GeneralException + * @throws ApgGeneralException * @throws InvalidAlgorithmParameterException */ public static PGPSecretKeyRing createKey(Context context, int algorithmChoice, int keySize, String passPhrase, PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException, - PGPException, NoSuchProviderException, GeneralException, + PGPException, NoSuchProviderException, ApgGeneralException, InvalidAlgorithmParameterException { if (keySize < 512) { - throw new GeneralException(context.getString(R.string.error_keySizeMinimum512bit)); + throw new ApgGeneralException(context.getString(R.string.error_keySizeMinimum512bit)); } if (passPhrase == null) { @@ -277,7 +272,7 @@ public class PGPMain { case Id.choice.algorithm.elgamal: { if (masterSecretKey == null) { - throw new GeneralException( + throw new ApgGeneralException( context.getString(R.string.error_masterKeyMustNotBeElGamal)); } keyGen = KeyPairGenerator.getInstance("ELGAMAL", BOUNCY_CASTLE_PROVIDER_NAME); @@ -300,7 +295,7 @@ public class PGPMain { } default: { - throw new GeneralException(context.getString(R.string.error_unknownAlgorithmChoice)); + throw new ApgGeneralException(context.getString(R.string.error_unknownAlgorithmChoice)); } } @@ -345,8 +340,8 @@ public class PGPMain { public static void buildSecretKey(Context context, ArrayList userIds, ArrayList keys, ArrayList keysUsages, long masterKeyId, String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress) - throws PGPMain.GeneralException, NoSuchProviderException, PGPException, - NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException { + throws ApgGeneralException, NoSuchProviderException, PGPException, + NoSuchAlgorithmException, SignatureException, IOException { updateProgress(progress, R.string.progress_buildingKey, 0, 100); @@ -526,7 +521,7 @@ public class PGPMain { } } catch (IOException e) { status = Id.return_value.error; - } catch (Database.GeneralException e) { + } catch (ApgGeneralException.GeneralException e) { status = Id.return_value.error; } @@ -558,7 +553,7 @@ public class PGPMain { } public static Bundle importKeyRings(Context context, int type, InputData data, - ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException, + ProgressDialogUpdater progress) throws ApgGeneralException, FileNotFoundException, PGPException, IOException { Bundle returnData = new Bundle(); @@ -571,7 +566,7 @@ public class PGPMain { } if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - throw new GeneralException(context.getString(R.string.error_externalStorageNotReady)); + throw new ApgGeneralException(context.getString(R.string.error_externalStorageNotReady)); } PositionAwareInputStream progressIn = new PositionAwareInputStream(data.getInputStream()); @@ -594,7 +589,7 @@ public class PGPMain { } if (status == Id.return_value.error) { - throw new GeneralException(context.getString(R.string.error_savingKeys)); + throw new ApgGeneralException(context.getString(R.string.error_savingKeys)); } // update the counts to display to the user at the end @@ -627,7 +622,7 @@ public class PGPMain { } public static Bundle exportKeyRings(Context context, Vector keyRingIds, - OutputStream outStream, ProgressDialogUpdater progress) throws GeneralException, + OutputStream outStream, ProgressDialogUpdater progress) throws ApgGeneralException, FileNotFoundException, PGPException, IOException { Bundle returnData = new Bundle(); @@ -638,7 +633,7 @@ public class PGPMain { } if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - throw new GeneralException(context.getString(R.string.error_externalStorageNotReady)); + throw new ApgGeneralException(context.getString(R.string.error_externalStorageNotReady)); } ArmoredOutputStream out = new ArmoredOutputStream(outStream); out.setHeader("Version", getFullVersion(context)); @@ -758,7 +753,7 @@ public class PGPMain { boolean armored, long encryptionKeyIds[], long signatureKeyId, String signaturePassPhrase, ProgressDialogUpdater progress, int symmetricAlgorithm, int hashAlgorithm, int compression, boolean forceV3Signature, String passPhrase) - throws IOException, GeneralException, PGPException, NoSuchProviderException, + throws IOException, ApgGeneralException, PGPException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException { if (encryptionKeyIds == null) { @@ -780,7 +775,7 @@ public class PGPMain { PGPPrivateKey signaturePrivateKey = null; if (encryptionKeyIds.length == 0 && passPhrase == null) { - throw new GeneralException( + throw new ApgGeneralException( context.getString(R.string.error_noEncryptionKeysOrPassPhrase)); } @@ -788,11 +783,12 @@ public class PGPMain { signingKeyRing = getSecretKeyRing(signatureKeyId); signingKey = PGPHelper.getSigningKey(signatureKeyId); if (signingKey == null) { - throw new GeneralException(context.getString(R.string.error_signatureFailed)); + throw new ApgGeneralException(context.getString(R.string.error_signatureFailed)); } if (signaturePassPhrase == null) { - throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); + throw new ApgGeneralException( + context.getString(R.string.error_noSignaturePassPhrase)); } if (progress != null) progress.setProgress(R.string.progress_extractingSignatureKey, 0, 100); @@ -800,7 +796,7 @@ public class PGPMain { BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray()); signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); if (signaturePrivateKey == null) { - throw new GeneralException( + throw new ApgGeneralException( context.getString(R.string.error_couldNotExtractPrivateKey)); } } @@ -922,7 +918,7 @@ public class PGPMain { public static void signText(Context context, InputData data, OutputStream outStream, long signatureKeyId, String signaturePassPhrase, int hashAlgorithm, - boolean forceV3Signature, ProgressDialogUpdater progress) throws GeneralException, + boolean forceV3Signature, ProgressDialogUpdater progress) throws ApgGeneralException, PGPException, IOException, NoSuchAlgorithmException, SignatureException { ArmoredOutputStream armorOut = new ArmoredOutputStream(outStream); @@ -934,26 +930,27 @@ public class PGPMain { if (signatureKeyId == 0) { armorOut.close(); - throw new GeneralException(context.getString(R.string.error_noSignatureKey)); + throw new ApgGeneralException(context.getString(R.string.error_noSignatureKey)); } signingKeyRing = getSecretKeyRing(signatureKeyId); signingKey = PGPHelper.getSigningKey(signatureKeyId); if (signingKey == null) { armorOut.close(); - throw new GeneralException(context.getString(R.string.error_signatureFailed)); + throw new ApgGeneralException(context.getString(R.string.error_signatureFailed)); } if (signaturePassPhrase == null) { armorOut.close(); - throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); + throw new ApgGeneralException(context.getString(R.string.error_noSignaturePassPhrase)); } PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray()); signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); if (signaturePrivateKey == null) { armorOut.close(); - throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); + throw new ApgGeneralException( + context.getString(R.string.error_couldNotExtractPrivateKey)); } updateProgress(progress, R.string.progress_preparingStreams, 0, 100); @@ -1029,7 +1026,7 @@ public class PGPMain { public static void generateSignature(Context context, InputData data, OutputStream outStream, boolean armored, boolean binary, long signatureKeyId, String signaturePassPhrase, int hashAlgorithm, boolean forceV3Signature, ProgressDialogUpdater progress) - throws GeneralException, PGPException, IOException, NoSuchAlgorithmException, + throws ApgGeneralException, PGPException, IOException, NoSuchAlgorithmException, SignatureException { OutputStream out = null; @@ -1049,24 +1046,25 @@ public class PGPMain { PGPPrivateKey signaturePrivateKey = null; if (signatureKeyId == 0) { - throw new GeneralException(context.getString(R.string.error_noSignatureKey)); + throw new ApgGeneralException(context.getString(R.string.error_noSignatureKey)); } signingKeyRing = getSecretKeyRing(signatureKeyId); signingKey = PGPHelper.getSigningKey(signatureKeyId); if (signingKey == null) { - throw new GeneralException(context.getString(R.string.error_signatureFailed)); + throw new ApgGeneralException(context.getString(R.string.error_signatureFailed)); } if (signaturePassPhrase == null) { - throw new GeneralException(context.getString(R.string.error_noSignaturePassPhrase)); + throw new ApgGeneralException(context.getString(R.string.error_noSignaturePassPhrase)); } PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( BOUNCY_CASTLE_PROVIDER_NAME).build(signaturePassPhrase.toCharArray()); signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); if (signaturePrivateKey == null) { - throw new GeneralException(context.getString(R.string.error_couldNotExtractPrivateKey)); + throw new ApgGeneralException( + context.getString(R.string.error_couldNotExtractPrivateKey)); } updateProgress(progress, R.string.progress_preparingStreams, 0, 100); @@ -1146,23 +1144,23 @@ public class PGPMain { } public static PGPPublicKeyRing signKey(Context context, long masterKeyId, long pubKeyId, - String passphrase) throws GeneralException, NoSuchAlgorithmException, + String passphrase) throws ApgGeneralException, NoSuchAlgorithmException, NoSuchProviderException, PGPException, SignatureException { if (passphrase == null || passphrase.length() <= 0) { - throw new GeneralException("Unable to obtain passphrase"); + throw new ApgGeneralException("Unable to obtain passphrase"); } else { PGPPublicKeyRing pubring = PGPMain.getPublicKeyRing(pubKeyId); PGPSecretKey signingKey = PGPHelper.getSigningKey(masterKeyId); if (signingKey == null) { - throw new GeneralException(context.getString(R.string.error_signatureFailed)); + throw new ApgGeneralException(context.getString(R.string.error_signatureFailed)); } PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); PGPPrivateKey signaturePrivateKey = signingKey.extractPrivateKey(keyDecryptor); if (signaturePrivateKey == null) { - throw new GeneralException( + throw new ApgGeneralException( context.getString(R.string.error_couldNotExtractPrivateKey)); } @@ -1190,7 +1188,7 @@ public class PGPMain { } public static long getDecryptionKeyId(Context context, InputStream inputStream) - throws GeneralException, NoAsymmetricEncryptionException, IOException { + throws ApgGeneralException, NoAsymmetricEncryptionException, IOException { InputStream in = PGPUtil.getDecoderStream(inputStream); PGPObjectFactory pgpF = new PGPObjectFactory(in); PGPEncryptedDataList enc; @@ -1204,7 +1202,7 @@ public class PGPMain { } if (enc == null) { - throw new GeneralException(context.getString(R.string.error_invalidData)); + throw new ApgGeneralException(context.getString(R.string.error_invalidData)); } // TODO: currently we always only look at the first known key @@ -1236,7 +1234,7 @@ public class PGPMain { } public static boolean hasSymmetricEncryption(Context context, InputStream inputStream) - throws GeneralException, IOException { + throws ApgGeneralException, IOException { InputStream in = PGPUtil.getDecoderStream(inputStream); PGPObjectFactory pgpF = new PGPObjectFactory(in); PGPEncryptedDataList enc; @@ -1250,7 +1248,7 @@ public class PGPMain { } if (enc == null) { - throw new GeneralException(context.getString(R.string.error_invalidData)); + throw new ApgGeneralException(context.getString(R.string.error_invalidData)); } Iterator it = enc.getEncryptedDataObjects(); @@ -1266,7 +1264,7 @@ public class PGPMain { public static Bundle decrypt(Context context, InputData data, OutputStream outStream, String passPhrase, ProgressDialogUpdater progress, boolean assumeSymmetric) - throws IOException, GeneralException, PGPException, SignatureException { + throws IOException, ApgGeneralException, PGPException, SignatureException { if (passPhrase == null) { passPhrase = ""; } @@ -1288,7 +1286,7 @@ public class PGPMain { } if (enc == null) { - throw new GeneralException(context.getString(R.string.error_invalidData)); + throw new ApgGeneralException(context.getString(R.string.error_invalidData)); } InputStream clear = null; @@ -1311,7 +1309,7 @@ public class PGPMain { } if (pbe == null) { - throw new GeneralException( + throw new ApgGeneralException( context.getString(R.string.error_noSymmetricEncryptionPacket)); } @@ -1347,7 +1345,7 @@ public class PGPMain { } if (secretKey == null) { - throw new GeneralException(context.getString(R.string.error_noSecretKeyFound)); + throw new ApgGeneralException(context.getString(R.string.error_noSecretKeyFound)); } currentProgress += 5; @@ -1361,7 +1359,7 @@ public class PGPMain { throw new PGPException(context.getString(R.string.error_wrongPassPhrase)); } if (privateKey == null) { - throw new GeneralException( + throw new ApgGeneralException( context.getString(R.string.error_couldNotExtractPrivateKey)); } currentProgress += 5; @@ -1511,7 +1509,7 @@ public class PGPMain { public static Bundle verifyText(Context context, InputData data, OutputStream outStream, boolean lookupUnknownKey, ProgressDialogUpdater progress) throws IOException, - GeneralException, PGPException, SignatureException { + ApgGeneralException, PGPException, SignatureException { Bundle returnData = new Bundle(); ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -1547,7 +1545,7 @@ public class PGPMain { PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); if (sigList == null) { - throw new GeneralException(context.getString(R.string.error_corruptData)); + throw new ApgGeneralException(context.getString(R.string.error_corruptData)); } PGPSignature signature = null; long signatureKeyId = 0; diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java b/org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java new file mode 100644 index 000000000..10f9fa05e --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2010 Thialfihar + * + * 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.thialfihar.android.apg.provider; + +import android.net.Uri; +import android.provider.BaseColumns; + +/** + * TODO: + * + * Breaking compatibility?: + * + * - change CONTENT_AUTHORITY + * + * - change type names + * + */ +public class ApgContract { + + interface KeyRingsColumns { + String MASTER_KEY_ID = "master_key_id"; // TODO: clarify + String TYPE = "type"; // see KeyTypes + String WHO_ID = "who_id"; + String KEY_RING_DATA = "key_ring_data"; // 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_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_id"; // foreign key to key_rings._ID + String KEY_DATA = "key_data"; + String RANK = "key_data"; // blob + } + + interface UserIdsColumns { + String KEY_ROW_ID = "key_id"; // foreign key to keys._ID + String USER_ID = "user_id"; // not a database id + String RANK = "rank"; + } + + public static final class KeyTypes { + public static final int PUBLIC = 0; + public static final int SECRET = 1; + } + + public static final String CONTENT_AUTHORITY = "org.thialfihar.android.apg.provider"; + // public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME; + + private static final Uri BASE_CONTENT_URI = 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_KEY_ID = "key_id"; + public static final String PATH_BY_EMAILS = "emails"; + + public static final String PATH_RANK = "#"; + + public static final String PATH_USER_IDS = "user_ids"; + public static final String PATH_KEYS = "keys"; + + public static class PublicKeyRings implements KeyRingsColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() + .appendPath(BASE_KEY_RINGS).appendPath(PATH_PUBLIC).build(); + + /** Use if multiple items get returned */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key_ring"; + + /** Use if a single item is returned */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.public.key_ring"; + + public static Uri buildPublicKeyRingsUri() { + return CONTENT_URI.buildUpon().build(); + } + + public static Uri buildPublicKeyRingsUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).build(); + } + + public static Uri buildPublicKeyRingsByKeyIdUri(String keyRowId) { + return CONTENT_URI.buildUpon().appendPath(PATH_BY_KEY_ID).appendPath(keyRowId).build(); + } + + public static Uri buildPublicKeyRingsByEmailsUri(String emails) { + return CONTENT_URI.buildUpon().appendPath(PATH_BY_EMAILS).appendPath(emails).build(); + } + } + + public static class SecretKeyRings implements KeyRingsColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() + .appendPath(BASE_KEY_RINGS).appendPath(PATH_SECRET).build(); + + /** Use if multiple items get returned */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.secret.key_ring"; + + /** Use if a single item is returned */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.secret.key_ring"; + + public static Uri buildSecretKeyRingsUri() { + return CONTENT_URI.buildUpon().build(); + } + + public static Uri buildSecretKeyRingsUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).build(); + } + + public static Uri buildSecretKeyRingsByKeyIdUri(String keyRowId) { + return CONTENT_URI.buildUpon().appendPath(PATH_BY_KEY_ID).appendPath(keyRowId).build(); + } + + public static Uri buildSecretKeyRingsByEmailsUri(String emails) { + return CONTENT_URI.buildUpon().appendPath(PATH_BY_EMAILS).appendPath(emails).build(); + } + } + + public static class PublicKeys implements KeysColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() + .appendPath(BASE_KEY_RINGS).appendPath(PATH_PUBLIC).build(); + + /** Use if multiple items get returned */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key"; + + /** Use if a single item is returned */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.public.key"; + + public static Uri buildPublicKeysUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_KEYS).build(); + } + + public static Uri buildPublicKeysRankUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_KEYS) + .appendPath(PATH_RANK).build(); + } + } + + public static class SecretKeys implements KeysColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() + .appendPath(BASE_KEY_RINGS).appendPath(PATH_SECRET).build(); + + /** Use if multiple items get returned */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.thialfihar.apg.secret.key"; + + /** Use if a single item is returned */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.thialfihar.apg.secret.key"; + + public static Uri buildSecretKeysUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_KEYS).build(); + } + + public static Uri buildSecretKeysRankUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_KEYS) + .appendPath(PATH_RANK).build(); + } + } + + public static class PublicUserIds implements UserIdsColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() + .appendPath(BASE_KEY_RINGS).appendPath(PATH_PUBLIC).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(keyRingRowId).appendPath(PATH_USER_IDS) + .build(); + } + + public static Uri buildPublicUserIdsRankUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_USER_IDS) + .appendPath(PATH_RANK).build(); + } + } + + public static class SecretUserIds implements UserIdsColumns, BaseColumns { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon() + .appendPath(BASE_KEY_RINGS).appendPath(PATH_SECRET).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 buildSecretUserIdsUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_USER_IDS) + .build(); + } + + public static Uri buildSecretUserIdsRankUri(String keyRingRowId) { + return CONTENT_URI.buildUpon().appendPath(keyRingRowId).appendPath(PATH_USER_IDS) + .appendPath(PATH_RANK).build(); + } + } + + public static class DataStream { + public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().appendPath(BASE_DATA) + .build(); + + public static Uri buildDataStreamUri(String streamFilename) { + return CONTENT_URI.buildUpon().appendPath(streamFilename).build(); + } + } + + private ApgContract() { + } +} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java b/org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java new file mode 100644 index 000000000..fdee2f101 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2010 Thialfihar + * + * 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.thialfihar.android.apg.provider; + +import org.thialfihar.android.apg.Constants; +import org.thialfihar.android.apg.provider.ApgContract.KeyRingsColumns; +import org.thialfihar.android.apg.provider.ApgContract.KeysColumns; +import org.thialfihar.android.apg.provider.ApgContract.UserIdsColumns; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.provider.BaseColumns; + +import org.thialfihar.android.apg.util.Log; + +public class ApgDatabase extends SQLiteOpenHelper { + private static final String DATABASE_NAME = "apg.db"; + // Last APG 1 db version was 2 + private static final int DATABASE_VERSION = 3; + + public interface Tables { + String KEY_RINGS = "key_rings"; + String KEYS = "keys"; + String USER_IDS = "user_ids"; + } + + private static final String CREATE_KEY_RINGS = "CREATE TABLE IF NOT EXISTS " + Tables.KEY_RINGS + + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY, " + KeyRingsColumns.MASTER_KEY_ID + + " INT64, " + KeyRingsColumns.TYPE + " INTEGER, " + KeyRingsColumns.WHO_ID + + " INTEGER, " + KeyRingsColumns.KEY_RING_DATA + " BLOB)"; + + private static final String CREATE_KEYS = "CREATE TABLE IF NOT EXISTS " + Tables.KEYS + " (" + + BaseColumns._ID + " INTEGER PRIMARY KEY, " + KeysColumns.KEY_ID + " INT64, " + + KeysColumns.TYPE + " INTEGER, " + KeysColumns.IS_MASTER_KEY + " INTEGER, " + + KeysColumns.ALGORITHM + " INTEGER, " + KeysColumns.KEY_SIZE + " INTEGER, " + + KeysColumns.CAN_SIGN + " INTEGER, " + KeysColumns.CAN_ENCRYPT + " INTEGER, " + + KeysColumns.IS_REVOKED + " INTEGER, " + KeysColumns.CREATION + " INTEGER, " + + KeysColumns.EXPIRY + " INTEGER, " + KeysColumns.KEY_RING_ROW_ID + + " INTEGER REFERENCES " + Tables.KEY_RINGS + " ON DELETE CASCADE, " + + KeysColumns.KEY_DATA + " BLOB," + KeysColumns.RANK + " INTEGER)"; + + private static final String CREATE_USER_IDS = "CREATE TABLE IF NOT EXISTS " + Tables.USER_IDS + + " (" + BaseColumns._ID + " INTEGER PRIMARY KEY, " + UserIdsColumns.KEY_ROW_ID + + " INTEGER REFERENCES " + Tables.KEYS + " ON DELETE CASCADE, " + + UserIdsColumns.USER_ID + " TEXT, " + UserIdsColumns.RANK + " INTEGER)"; + + ApgDatabase(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + // + // public static HashMap sKeyRingsProjection; + // public static HashMap sKeysProjection; + // public static HashMap sUserIdsProjection; + // + // private SQLiteDatabase mDb = null; + // private int mStatus = 0; + // + // static { + // sKeyRingsProjection = new HashMap(); + // sKeyRingsProjection.put(KeyRings._ID, KeyRings._ID); + // sKeyRingsProjection.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID); + // sKeyRingsProjection.put(KeyRings.TYPE, KeyRings.TYPE); + // sKeyRingsProjection.put(KeyRings.WHO_ID, KeyRings.WHO_ID); + // sKeyRingsProjection.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA); + // + // sKeysProjection = new HashMap(); + // sKeysProjection.put(Keys._ID, Keys._ID); + // sKeysProjection.put(Keys.KEY_ID, Keys.KEY_ID); + // sKeysProjection.put(Keys.TYPE, Keys.TYPE); + // sKeysProjection.put(Keys.IS_MASTER_KEY, Keys.IS_MASTER_KEY); + // sKeysProjection.put(Keys.ALGORITHM, Keys.ALGORITHM); + // sKeysProjection.put(Keys.KEY_SIZE, Keys.KEY_SIZE); + // sKeysProjection.put(Keys.CAN_SIGN, Keys.CAN_SIGN); + // sKeysProjection.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT); + // sKeysProjection.put(Keys.IS_REVOKED, Keys.IS_REVOKED); + // sKeysProjection.put(Keys.CREATION, Keys.CREATION); + // sKeysProjection.put(Keys.EXPIRY, Keys.EXPIRY); + // sKeysProjection.put(Keys.KEY_DATA, Keys.KEY_DATA); + // sKeysProjection.put(Keys.RANK, Keys.RANK); + // + // sUserIdsProjection = new HashMap(); + // sUserIdsProjection.put(UserIds._ID, UserIds._ID); + // sUserIdsProjection.put(UserIds.KEY_ID, UserIds.KEY_ID); + // sUserIdsProjection.put(UserIds.USER_ID, UserIds.USER_ID); + // sUserIdsProjection.put(UserIds.RANK, UserIds.RANK); + // } + + @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); + } + + @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 1: + + break; + + default: + break; + + } + } + } + +} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java b/org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java new file mode 100644 index 000000000..e25228434 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2012 Dominik Schürmann + * Copyright (C) 2010 Thialfihar + * + * 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.thialfihar.android.apg.provider; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.util.HashMap; + +import org.thialfihar.android.apg.Constants; +import org.thialfihar.android.apg.provider.ApgContract.KeyRingsColumns; +import org.thialfihar.android.apg.provider.ApgContract.KeyTypes; +import org.thialfihar.android.apg.provider.ApgContract.KeysColumns; +import org.thialfihar.android.apg.provider.ApgContract.PublicKeyRings; +import org.thialfihar.android.apg.provider.ApgContract.PublicKeys; +import org.thialfihar.android.apg.provider.ApgContract.PublicUserIds; +import org.thialfihar.android.apg.provider.ApgContract.SecretKeyRings; +import org.thialfihar.android.apg.provider.ApgContract.SecretKeys; +import org.thialfihar.android.apg.provider.ApgContract.SecretUserIds; +import org.thialfihar.android.apg.provider.ApgContract.UserIdsColumns; +import org.thialfihar.android.apg.provider.ApgDatabase.Tables; +import org.thialfihar.android.apg.util.Log; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.Context; +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.os.ParcelFileDescriptor; +import android.provider.BaseColumns; +import android.text.TextUtils; + +public class ApgProvider extends ContentProvider { + private static final UriMatcher sUriMatcher = buildUriMatcher(); + + private static final int PUBLIC_KEY_RING = 101; + private static final int PUBLIC_KEY_RING_ID = 102; + private static final int PUBLIC_KEY_RING_BY_KEY_ID = 103; + private static final int PUBLIC_KEY_RING_BY_EMAILS = 104; + private static final int PUBLIC_KEY_RING_KEY = 111; + private static final int PUBLIC_KEY_RING_KEY_RANK = 112; + private static final int PUBLIC_KEY_RING_USER_ID = 121; + private static final int PUBLIC_KEY_RING_USER_ID_RANK = 122; + + private static final int SECRET_KEY_RING = 201; + private static final int SECRET_KEY_RING_ID = 202; + private static final int SECRET_KEY_RING_BY_KEY_ID = 203; + private static final int SECRET_KEY_RING_BY_EMAILS = 204; + private static final int SECRET_KEY_RING_KEY = 211; + private static final int SECRET_KEY_RING_KEY_RANK = 212; + private static final int SECRET_KEY_RING_USER_ID = 221; + private static final int SECRET_KEY_RING_USER_ID_RANK = 222; + + private static final int DATA_STREAM = 301; + + /** + * Build and return a {@link UriMatcher} that catches all {@link Uri} variations supported by + * this {@link ContentProvider}. + */ + private static UriMatcher buildUriMatcher() { + final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); + final String authority = ApgContract.CONTENT_AUTHORITY; + + /** + * public key rings + * + *
+         * key_rings/public
+         * key_rings/public/_
+         * key_rings/public/key_id/_
+         * key_rings/public/emails/_
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC, + PUBLIC_KEY_RING); + matcher.addURI(authority, + ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + "/*", + PUBLIC_KEY_RING_ID); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + "/" + + ApgContract.PATH_BY_KEY_ID + "/*", PUBLIC_KEY_RING_BY_KEY_ID); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + "/" + + ApgContract.PATH_BY_EMAILS + "/*", PUBLIC_KEY_RING_BY_EMAILS); + + /** + * public keys + * + *
+         * key_rings/public/_/keys
+         * key_rings/public/_/keys/#
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + + "/*/" + ApgContract.PATH_KEYS, PUBLIC_KEY_RING_KEY); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + + "/*/" + ApgContract.PATH_KEYS + "/" + ApgContract.PATH_RANK, + PUBLIC_KEY_RING_KEY_RANK); + + /** + * public user ids + * + *
+         * key_rings/public/_/user_ids
+         * key_rings/public/_/user_ids/#
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + + "/*/" + ApgContract.PATH_USER_IDS, PUBLIC_KEY_RING_USER_ID); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_PUBLIC + + "/*/" + ApgContract.PATH_USER_IDS + "/" + ApgContract.PATH_RANK, + PUBLIC_KEY_RING_USER_ID_RANK); + + /** + * secret key rings + * + *
+         * key_rings/secret
+         * key_rings/secret/*
+         * key_rings/secret/key_id/*
+         * key_rings/secret/emails/*
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET, + SECRET_KEY_RING); + matcher.addURI(authority, + ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + "/*", + SECRET_KEY_RING_ID); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + "/" + + ApgContract.PATH_BY_KEY_ID + "/*", SECRET_KEY_RING_BY_KEY_ID); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + "/" + + ApgContract.PATH_BY_EMAILS + "/*", SECRET_KEY_RING_BY_EMAILS); + + /** + * secret keys + * + *
+         * key_rings/secret/_/keys
+         * key_rings/secret/_/keys/#
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + + "/*/" + ApgContract.PATH_KEYS, SECRET_KEY_RING_KEY); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + + "/*/" + ApgContract.PATH_KEYS + "/" + ApgContract.PATH_RANK, + SECRET_KEY_RING_KEY_RANK); + + /** + * secret user ids + * + *
+         * key_rings/secret/_/user_ids
+         * key_rings/secret/_/user_ids/#
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + + "/*/" + ApgContract.PATH_USER_IDS, SECRET_KEY_RING_USER_ID); + matcher.addURI(authority, ApgContract.BASE_KEY_RINGS + "/" + ApgContract.PATH_SECRET + + "/*/" + ApgContract.PATH_USER_IDS + "/" + ApgContract.PATH_RANK, + SECRET_KEY_RING_USER_ID_RANK); + + /** + * data stream + * + *
+         * data/*
+         * 
+ */ + matcher.addURI(authority, ApgContract.BASE_DATA + "/*", DATA_STREAM); + + return matcher; + } + + private ApgDatabase mApgDatabase; + + /** {@inheritDoc} */ + @Override + public boolean onCreate() { + final Context context = getContext(); + mApgDatabase = new ApgDatabase(context); + return true; + } + + /** {@inheritDoc} */ + @Override + public String getType(Uri uri) { + final int match = sUriMatcher.match(uri); + switch (match) { + case PUBLIC_KEY_RING: + case PUBLIC_KEY_RING_BY_EMAILS: + return PublicKeyRings.CONTENT_TYPE; + + case PUBLIC_KEY_RING_ID: + case PUBLIC_KEY_RING_BY_KEY_ID: + return PublicKeyRings.CONTENT_ITEM_TYPE; + + case PUBLIC_KEY_RING_KEY: + return PublicKeys.CONTENT_TYPE; + + case PUBLIC_KEY_RING_KEY_RANK: + return PublicKeys.CONTENT_ITEM_TYPE; + + case PUBLIC_KEY_RING_USER_ID: + return PublicUserIds.CONTENT_TYPE; + + case PUBLIC_KEY_RING_USER_ID_RANK: + return PublicUserIds.CONTENT_ITEM_TYPE; + + case SECRET_KEY_RING: + case SECRET_KEY_RING_BY_EMAILS: + return SecretKeyRings.CONTENT_TYPE; + + case SECRET_KEY_RING_ID: + case SECRET_KEY_RING_BY_KEY_ID: + return SecretKeyRings.CONTENT_ITEM_TYPE; + + case SECRET_KEY_RING_KEY: + return SecretKeys.CONTENT_TYPE; + + case SECRET_KEY_RING_KEY_RANK: + return SecretKeys.CONTENT_ITEM_TYPE; + + case SECRET_KEY_RING_USER_ID: + return SecretUserIds.CONTENT_TYPE; + + case SECRET_KEY_RING_USER_ID_RANK: + return SecretUserIds.CONTENT_ITEM_TYPE; + + default: + throw new UnsupportedOperationException("Unknown uri: " + uri); + } + } + + /** + * Returns weather the key is a public or secret one + * + * @param uri + * @return + */ + private int getKeyType(int match) { + int type; + switch (match) { + case PUBLIC_KEY_RING: + case PUBLIC_KEY_RING_ID: + case PUBLIC_KEY_RING_BY_KEY_ID: + case PUBLIC_KEY_RING_BY_EMAILS: + case PUBLIC_KEY_RING_KEY: + case PUBLIC_KEY_RING_KEY_RANK: + case PUBLIC_KEY_RING_USER_ID: + case PUBLIC_KEY_RING_USER_ID_RANK: + type = KeyTypes.PUBLIC; + break; + + case SECRET_KEY_RING: + case SECRET_KEY_RING_ID: + case SECRET_KEY_RING_BY_KEY_ID: + case SECRET_KEY_RING_BY_EMAILS: + case SECRET_KEY_RING_KEY: + case SECRET_KEY_RING_KEY_RANK: + case SECRET_KEY_RING_USER_ID: + case SECRET_KEY_RING_USER_ID_RANK: + type = KeyTypes.SECRET; + break; + + default: + throw new IllegalArgumentException("Unknown match " + match); + + } + + return type; + } + + /** {@inheritDoc} */ + @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(); + + HashMap projectionMap = new HashMap(); + + int match = sUriMatcher.match(uri); + + qb.appendWhere(Tables.KEY_RINGS + "." + KeyRingsColumns.TYPE + " = " + getKeyType(match)); + + switch (match) { + case PUBLIC_KEY_RING_ID: + case SECRET_KEY_RING_ID: + qb.appendWhere(" AND " + Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(2)); + + // break omitted intentionally + + case PUBLIC_KEY_RING: + case SECRET_KEY_RING: + qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" + + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." + + KeysColumns.KEY_RING_ID + " AND " + Tables.KEYS + "." + + KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + + Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = " + + Tables.USER_IDS + "." + UserIdsColumns.KEY_ID + " AND " + Tables.USER_IDS + + "." + UserIdsColumns.RANK + " = '0') "); + + projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); + projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + + KeyRingsColumns.MASTER_KEY_ID); + projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + + UserIdsColumns.USER_ID); + + 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.setTables(Tables.KEYS + " AS tmp INNER JOIN " + Tables.KEY_RINGS + " ON (" + + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + "tmp." + + KeysColumns.KEY_RING_ID + ")" + " INNER JOIN " + Tables.KEYS + " ON " + "(" + + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." + + KeysColumns.KEY_RING_ID + " AND " + Tables.KEYS + "." + + KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + + Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = " + + Tables.USER_IDS + "." + UserIdsColumns.KEY_ID + " AND " + Tables.USER_IDS + + "." + UserIdsColumns.RANK + " = '0') "); + + projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); + projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + + KeyRingsColumns.MASTER_KEY_ID); + projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + + UserIdsColumns.USER_ID); + + qb.appendWhere(" AND tmp." + KeysColumns.KEY_ID + " = "); + qb.appendWhereEscapeString(uri.getPathSegments().get(3)); + + break; + + case SECRET_KEY_RING_BY_EMAILS: + case PUBLIC_KEY_RING_BY_EMAILS: + qb.setTables(Tables.KEY_RINGS + " INNER JOIN " + Tables.KEYS + " ON " + "(" + + Tables.KEY_RINGS + "." + BaseColumns._ID + " = " + Tables.KEYS + "." + + KeysColumns.KEY_RING_ID + " AND " + Tables.KEYS + "." + + KeysColumns.IS_MASTER_KEY + " = '1'" + ") " + " INNER JOIN " + + Tables.USER_IDS + " ON " + "(" + Tables.KEYS + "." + BaseColumns._ID + " = " + + Tables.USER_IDS + "." + UserIdsColumns.KEY_ID + " AND " + Tables.USER_IDS + + "." + UserIdsColumns.RANK + " = '0') "); + + projectionMap.put(BaseColumns._ID, Tables.KEY_RINGS + "." + BaseColumns._ID); + projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + + KeyRingsColumns.MASTER_KEY_ID); + projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + + UserIdsColumns.USER_ID); + + String emails = uri.getPathSegments().get(3); + 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 '*', 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_ID + " = " + + Tables.KEYS + "." + BaseColumns._ID + " AND (" + emailWhere + "))"); + } + + break; + + default: + throw new IllegalArgumentException("Unknown URI " + uri); + + } + + qb.setProjectionMap(projectionMap); + + // If no sort order is specified use the default + String orderBy; + if (TextUtils.isEmpty(sortOrder)) { + orderBy = null; + } else { + orderBy = sortOrder; + } + + Log.d(Constants.TAG, + qb.buildQuery(projection, selection, selectionArgs, null, null, orderBy, null) + .replace("WHERE", "WHERE\n")); + 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); + 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; + try { + final int match = sUriMatcher.match(uri); + + switch (match) { + case PUBLIC_KEY_RING: + values.put(PublicKeyRings.TYPE, KeyTypes.PUBLIC); + + db.insertOrThrow(Tables.KEY_RINGS, null, values); + rowUri = PublicKeyRings.buildPublicKeyRingsUri(values + .getAsString(PublicKeyRings._ID)); + + break; + case PUBLIC_KEY_RING_KEY: + values.put(PublicKeys.TYPE, KeyTypes.PUBLIC); + + db.insertOrThrow(Tables.KEYS, null, values); + rowUri = PublicKeys.buildPublicKeysUri(values.getAsString(PublicKeys._ID)); + + break; + case PUBLIC_KEY_RING_USER_ID: + db.insertOrThrow(Tables.USER_IDS, null, values); + rowUri = PublicUserIds.buildPublicUserIdsUri(values.getAsString(PublicUserIds._ID)); + + break; + case SECRET_KEY_RING: + values.put(SecretKeyRings.TYPE, KeyTypes.SECRET); + + db.insertOrThrow(Tables.KEY_RINGS, null, values); + rowUri = SecretKeyRings.buildSecretKeyRingsUri(values + .getAsString(SecretKeyRings._ID)); + + break; + case SECRET_KEY_RING_KEY: + values.put(SecretKeys.TYPE, KeyTypes.SECRET); + + db.insertOrThrow(Tables.KEYS, null, values); + rowUri = SecretKeys.buildSecretKeysUri(values.getAsString(SecretKeys._ID)); + + break; + case SECRET_KEY_RING_USER_ID: + db.insertOrThrow(Tables.USER_IDS, null, values); + rowUri = SecretUserIds.buildSecretUserIdsUri(values.getAsString(SecretUserIds._ID)); + + break; + default: + throw new UnsupportedOperationException("Unknown uri: " + uri); + } + } catch (SQLiteConstraintException e) { + Log.e(Constants.TAG, "Constraint exception on insert! Entry already existing?"); + } + + // notify of changes in db + getContext().getContentResolver().notifyChange(uri, null); + + 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 = sUriMatcher.match(uri); + + switch (match) { + case PUBLIC_KEY_RING_ID: + // delete corresponding keys and userids + // db.delete(Tables.KEYS, whereClause, whereArgs) + // TODO + count = db.delete(Tables.KEY_RINGS, + buildDefaultSelection(uri, KeyTypes.PUBLIC, selection), selectionArgs); + break; + case SECRET_KEY_RING_ID: + // delete corresponding keys and userids + // TODO + count = db.delete(Tables.KEY_RINGS, + buildDefaultSelection(uri, KeyTypes.SECRET, 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(); + + int count = 0; + try { + final int match = sUriMatcher.match(uri); + switch (match) { + case PUBLIC_KEY_RING_ID: + count = db.update(Tables.KEY_RINGS, values, + buildDefaultSelection(uri, KeyTypes.PUBLIC, selection), selectionArgs); + break; + case SECRET_KEY_RING_ID: + count = db.update(Tables.KEY_RINGS, values, + buildDefaultSelection(uri, KeyTypes.PUBLIC, selection), selectionArgs); + break; + default: + throw new UnsupportedOperationException("Unknown uri: " + uri); + } + } catch (SQLiteConstraintException e) { + Log.e(Constants.TAG, "Constraint exception on update! Entry already existing?"); + } + + // notify of changes in db + getContext().getContentResolver().notifyChange(uri, null); + + return count; + } + + /** + * Build default selection statement. If no extra selection is specified only build where clause + * with rowId + * + * @param uri + * @param selection + * @return + */ + private String buildDefaultSelection(Uri uri, Integer keyType, String selection) { + String rowId = uri.getPathSegments().get(1); + String andWhere = ""; + if (!TextUtils.isEmpty(selection)) { + andWhere = " AND (" + selection + ")"; + } + + String andType = ""; + if (keyType != null) { + andType = " AND " + KeyRingsColumns.TYPE + "=" + keyType; + } + + return BaseColumns._ID + "=" + rowId + andType + andWhere; + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + int match = sUriMatcher.match(uri); + if (match != DATA_STREAM) { + throw new FileNotFoundException(); + } + String fileName = uri.getPathSegments().get(1); + File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName); + return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); + } +} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java b/org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java deleted file mode 100644 index 9cf083528..000000000 --- a/org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (C) 2010 Thialfihar - * - * 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.thialfihar.android.apg.provider; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.HashMap; - -import org.thialfihar.android.apg.Id; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.UriMatcher; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteQueryBuilder; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.text.TextUtils; - -public class DataProvider extends ContentProvider { - public static final String AUTHORITY = "org.thialfihar.android.apg.provider"; - - private static final int PUBLIC_KEY_RING = 101; - private static final int PUBLIC_KEY_RING_ID = 102; - private static final int PUBLIC_KEY_RING_BY_KEY_ID = 103; - private static final int PUBLIC_KEY_RING_BY_EMAILS = 104; - private static final int PUBLIC_KEY_RING_KEY = 111; - private static final int PUBLIC_KEY_RING_KEY_RANK = 112; - private static final int PUBLIC_KEY_RING_USER_ID = 121; - private static final int PUBLIC_KEY_RING_USER_ID_RANK = 122; - - private static final int SECRET_KEY_RING = 201; - private static final int SECRET_KEY_RING_ID = 202; - private static final int SECRET_KEY_RING_BY_KEY_ID = 203; - private static final int SECRET_KEY_RING_BY_EMAILS = 204; - private static final int SECRET_KEY_RING_KEY = 211; - private static final int SECRET_KEY_RING_KEY_RANK = 212; - private static final int SECRET_KEY_RING_USER_ID = 221; - private static final int SECRET_KEY_RING_USER_ID_RANK = 222; - - private static final int DATA_STREAM = 301; - - private static final String PUBLIC_KEY_RING_CONTENT_DIR_TYPE = - "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key_ring"; - private static final String PUBLIC_KEY_RING_CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/vnd.thialfihar.apg.public.key_ring"; - - private static final String PUBLIC_KEY_CONTENT_DIR_TYPE = - "vnd.android.cursor.dir/vnd.thialfihar.apg.public.key"; - private static final String PUBLIC_KEY_CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/vnd.thialfihar.apg.public.key"; - - private static final String SECRET_KEY_RING_CONTENT_DIR_TYPE = - "vnd.android.cursor.dir/vnd.thialfihar.apg.secret.key_ring"; - private static final String SECRET_KEY_RING_CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/vnd.thialfihar.apg.secret.key_ring"; - - private static final String SECRET_KEY_CONTENT_DIR_TYPE = - "vnd.android.cursor.dir/vnd.thialfihar.apg.secret.key"; - private static final String SECRET_KEY_CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/vnd.thialfihar.apg.secret.key"; - - private static final String USER_ID_CONTENT_DIR_TYPE = - "vnd.android.cursor.dir/vnd.thialfihar.apg.user_id"; - private static final String USER_ID_CONTENT_ITEM_TYPE = - "vnd.android.cursor.item/vnd.thialfihar.apg.user_id"; - - public static final String _ID = "_id"; - public static final String MASTER_KEY_ID = "master_key_id"; - public static final String KEY_ID = "key_id"; - public static final String USER_ID = "user_id"; - - private static final UriMatcher mUriMatcher; - - private Database mDb; - - static { - mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - mUriMatcher.addURI(AUTHORITY, "key_rings/public/key_id/*", PUBLIC_KEY_RING_BY_KEY_ID); - mUriMatcher.addURI(AUTHORITY, "key_rings/public/emails/*", PUBLIC_KEY_RING_BY_EMAILS); - - mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/keys", PUBLIC_KEY_RING_KEY); - mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/keys/#", PUBLIC_KEY_RING_KEY_RANK); - - mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/user_ids", PUBLIC_KEY_RING_USER_ID); - mUriMatcher.addURI(AUTHORITY, "key_rings/public/*/user_ids/#", PUBLIC_KEY_RING_USER_ID_RANK); - - mUriMatcher.addURI(AUTHORITY, "key_rings/public", PUBLIC_KEY_RING); - mUriMatcher.addURI(AUTHORITY, "key_rings/public/*", PUBLIC_KEY_RING_ID); - - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/key_id/*", SECRET_KEY_RING_BY_KEY_ID); - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/emails/*", SECRET_KEY_RING_BY_EMAILS); - - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/keys", SECRET_KEY_RING_KEY); - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/keys/#", SECRET_KEY_RING_KEY_RANK); - - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/user_ids", SECRET_KEY_RING_USER_ID); - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*/user_ids/#", SECRET_KEY_RING_USER_ID_RANK); - - mUriMatcher.addURI(AUTHORITY, "key_rings/secret", SECRET_KEY_RING); - mUriMatcher.addURI(AUTHORITY, "key_rings/secret/*", SECRET_KEY_RING_ID); - - mUriMatcher.addURI(AUTHORITY, "data/*", DATA_STREAM); - } - - @Override - public boolean onCreate() { - mDb = new Database(getContext()); - return true; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { - // TODO: implement the others, then use them for the lists - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - HashMap projectionMap = new HashMap(); - - int match = mUriMatcher.match(uri); - int type; - switch (match) { - case PUBLIC_KEY_RING: - case PUBLIC_KEY_RING_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_KEY: - case PUBLIC_KEY_RING_KEY_RANK: - case PUBLIC_KEY_RING_USER_ID: - case PUBLIC_KEY_RING_USER_ID_RANK: - type = Id.database.type_public; - break; - - case SECRET_KEY_RING: - case SECRET_KEY_RING_ID: - case SECRET_KEY_RING_BY_KEY_ID: - case SECRET_KEY_RING_BY_EMAILS: - case SECRET_KEY_RING_KEY: - case SECRET_KEY_RING_KEY_RANK: - case SECRET_KEY_RING_USER_ID: - case SECRET_KEY_RING_USER_ID_RANK: - type = Id.database.type_secret; - break; - - default: { - throw new IllegalArgumentException("Unknown URI " + uri); - } - } - - qb.appendWhere(KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = " + type); - - switch (match) { - case PUBLIC_KEY_RING_ID: - case SECRET_KEY_RING_ID: { - qb.appendWhere(" AND " + - KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(2)); - - // break omitted intentionally - } - - case PUBLIC_KEY_RING: - case SECRET_KEY_RING: { - qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + - "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + - Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + - Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + - ") " + - " INNER JOIN " + UserIds.TABLE_NAME + " ON " + - "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + - UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + - UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); - - projectionMap.put(_ID, - KeyRings.TABLE_NAME + "." + KeyRings._ID); - projectionMap.put(MASTER_KEY_ID, - KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID); - projectionMap.put(USER_ID, - UserIds.TABLE_NAME + "." + UserIds.USER_ID); - - if (TextUtils.isEmpty(sortOrder)) { - sortOrder = UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC"; - } - - break; - } - - case SECRET_KEY_RING_BY_KEY_ID: - case PUBLIC_KEY_RING_BY_KEY_ID: { - qb.setTables(Keys.TABLE_NAME + " AS tmp INNER JOIN " + - KeyRings.TABLE_NAME + " ON (" + - KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + - "tmp." + Keys.KEY_RING_ID + ")" + - " INNER JOIN " + Keys.TABLE_NAME + " ON " + - "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + - Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + - Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + - ") " + - " INNER JOIN " + UserIds.TABLE_NAME + " ON " + - "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + - UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + - UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); - - projectionMap.put(_ID, - KeyRings.TABLE_NAME + "." + KeyRings._ID); - projectionMap.put(MASTER_KEY_ID, - KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID); - projectionMap.put(USER_ID, - UserIds.TABLE_NAME + "." + UserIds.USER_ID); - - qb.appendWhere(" AND tmp." + Keys.KEY_ID + " = "); - qb.appendWhereEscapeString(uri.getPathSegments().get(3)); - - break; - } - - case SECRET_KEY_RING_BY_EMAILS: - case PUBLIC_KEY_RING_BY_EMAILS: { - qb.setTables(KeyRings.TABLE_NAME + " INNER JOIN " + Keys.TABLE_NAME + " ON " + - "(" + KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + - Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + " AND " + - Keys.TABLE_NAME + "." + Keys.IS_MASTER_KEY + " = '1'" + - ") " + - " INNER JOIN " + UserIds.TABLE_NAME + " ON " + - "(" + Keys.TABLE_NAME + "." + Keys._ID + " = " + - UserIds.TABLE_NAME + "." + UserIds.KEY_ID + " AND " + - UserIds.TABLE_NAME + "." + UserIds.RANK + " = '0') "); - - projectionMap.put(_ID, - KeyRings.TABLE_NAME + "." + KeyRings._ID); - projectionMap.put(MASTER_KEY_ID, - KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID); - projectionMap.put(USER_ID, - UserIds.TABLE_NAME + "." + UserIds.USER_ID); - - String emails = uri.getPathSegments().get(3); - 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." + UserIds.USER_ID + " LIKE "; - // match '*', 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." + UserIds._ID + - " FROM " + UserIds.TABLE_NAME + - " AS tmp WHERE tmp." + UserIds.KEY_ID + " = " + - Keys.TABLE_NAME + "." + Keys._ID + - " AND (" + emailWhere + "))"); - } - - break; - } - - default: { - throw new IllegalArgumentException("Unknown URI " + uri); - } - } - - qb.setProjectionMap(projectionMap); - - // If no sort order is specified use the default - String orderBy; - if (TextUtils.isEmpty(sortOrder)) { - orderBy = null; - } else { - orderBy = sortOrder; - } - - //System.out.println(qb.buildQuery(projection, selection, selectionArgs, null, null, sortOrder, null).replace("WHERE", "WHERE\n")); - Cursor c = qb.query(mDb.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); - return c; - } - - @Override - public String getType(Uri uri) { - switch (mUriMatcher.match(uri)) { - case PUBLIC_KEY_RING: - case PUBLIC_KEY_RING_BY_EMAILS: - return PUBLIC_KEY_RING_CONTENT_DIR_TYPE; - - case PUBLIC_KEY_RING_ID: - return PUBLIC_KEY_RING_CONTENT_ITEM_TYPE; - - case PUBLIC_KEY_RING_BY_KEY_ID: - return PUBLIC_KEY_RING_CONTENT_ITEM_TYPE; - - case PUBLIC_KEY_RING_KEY: - return PUBLIC_KEY_CONTENT_DIR_TYPE; - - case PUBLIC_KEY_RING_KEY_RANK: - return PUBLIC_KEY_CONTENT_ITEM_TYPE; - - case PUBLIC_KEY_RING_USER_ID: - return USER_ID_CONTENT_DIR_TYPE; - - case PUBLIC_KEY_RING_USER_ID_RANK: - return USER_ID_CONTENT_ITEM_TYPE; - - case SECRET_KEY_RING: - case SECRET_KEY_RING_BY_EMAILS: - return SECRET_KEY_RING_CONTENT_DIR_TYPE; - - case SECRET_KEY_RING_ID: - return SECRET_KEY_RING_CONTENT_ITEM_TYPE; - - case SECRET_KEY_RING_BY_KEY_ID: - return SECRET_KEY_RING_CONTENT_ITEM_TYPE; - - case SECRET_KEY_RING_KEY: - return SECRET_KEY_CONTENT_DIR_TYPE; - - case SECRET_KEY_RING_KEY_RANK: - return SECRET_KEY_CONTENT_ITEM_TYPE; - - case SECRET_KEY_RING_USER_ID: - return USER_ID_CONTENT_DIR_TYPE; - - case SECRET_KEY_RING_USER_ID_RANK: - return USER_ID_CONTENT_ITEM_TYPE; - - default: - throw new IllegalArgumentException("Unknown URI " + uri); - } - } - - @Override - public Uri insert(Uri uri, ContentValues initialValues) { - // not supported - return null; - } - - @Override - public int delete(Uri uri, String where, String[] whereArgs) { - // not supported - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { - // not supported - return 0; - } - - @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.getPathSegments().get(1); - File file = new File(getContext().getFilesDir().getAbsolutePath(), fileName); - return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); - } -} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/Database.java b/org_apg/src/org/thialfihar/android/apg/provider/Database.java deleted file mode 100644 index 0c14283c2..000000000 --- a/org_apg/src/org/thialfihar/android/apg/provider/Database.java +++ /dev/null @@ -1,617 +0,0 @@ -/* - * 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.thialfihar.android.apg.provider; - -import org.spongycastle.openpgp.PGPException; -import org.spongycastle.openpgp.PGPPublicKey; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.thialfihar.android.apg.Id; -import org.thialfihar.android.apg.helper.PGPHelper; -import org.thialfihar.android.apg.util.IterableIterator; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import org.thialfihar.android.apg.util.Log; - -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.Vector; - -public class Database extends SQLiteOpenHelper { - public static class GeneralException extends Exception { - static final long serialVersionUID = 0xf812773343L; - - public GeneralException(String message) { - super(message); - } - } - - private static final String DATABASE_NAME = "apg"; - private static final int DATABASE_VERSION = 2; - - public static final String AUTHORITY = "org.thialfihar.android.apg.database"; - - public static HashMap sKeyRingsProjection; - public static HashMap sKeysProjection; - public static HashMap sUserIdsProjection; - - private SQLiteDatabase mDb = null; - private int mStatus = 0; - - static { - sKeyRingsProjection = new HashMap(); - sKeyRingsProjection.put(KeyRings._ID, KeyRings._ID); - sKeyRingsProjection.put(KeyRings.MASTER_KEY_ID, KeyRings.MASTER_KEY_ID); - sKeyRingsProjection.put(KeyRings.TYPE, KeyRings.TYPE); - sKeyRingsProjection.put(KeyRings.WHO_ID, KeyRings.WHO_ID); - sKeyRingsProjection.put(KeyRings.KEY_RING_DATA, KeyRings.KEY_RING_DATA); - - sKeysProjection = new HashMap(); - sKeysProjection.put(Keys._ID, Keys._ID); - sKeysProjection.put(Keys.KEY_ID, Keys.KEY_ID); - sKeysProjection.put(Keys.TYPE, Keys.TYPE); - sKeysProjection.put(Keys.IS_MASTER_KEY, Keys.IS_MASTER_KEY); - sKeysProjection.put(Keys.ALGORITHM, Keys.ALGORITHM); - sKeysProjection.put(Keys.KEY_SIZE, Keys.KEY_SIZE); - sKeysProjection.put(Keys.CAN_SIGN, Keys.CAN_SIGN); - sKeysProjection.put(Keys.CAN_ENCRYPT, Keys.CAN_ENCRYPT); - sKeysProjection.put(Keys.IS_REVOKED, Keys.IS_REVOKED); - sKeysProjection.put(Keys.CREATION, Keys.CREATION); - sKeysProjection.put(Keys.EXPIRY, Keys.EXPIRY); - sKeysProjection.put(Keys.KEY_DATA, Keys.KEY_DATA); - sKeysProjection.put(Keys.RANK, Keys.RANK); - - sUserIdsProjection = new HashMap(); - sUserIdsProjection.put(UserIds._ID, UserIds._ID); - sUserIdsProjection.put(UserIds.KEY_ID, UserIds.KEY_ID); - sUserIdsProjection.put(UserIds.USER_ID, UserIds.USER_ID); - sUserIdsProjection.put(UserIds.RANK, UserIds.RANK); - } - - public Database(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - // force upgrade to test things - //onUpgrade(getWritableDatabase(), 1, 2); - mDb = getWritableDatabase(); - } - - @Override - protected void finalize() throws Throwable { - mDb.close(); - super.finalize(); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + KeyRings.TABLE_NAME + " (" + - KeyRings._ID + " " + KeyRings._ID_type + "," + - KeyRings.MASTER_KEY_ID + " " + KeyRings.MASTER_KEY_ID_type + ", " + - KeyRings.TYPE + " " + KeyRings.TYPE_type + ", " + - KeyRings.WHO_ID + " " + KeyRings.WHO_ID_type + ", " + - KeyRings.KEY_RING_DATA + " " + KeyRings.KEY_RING_DATA_type + ");"); - - db.execSQL("CREATE TABLE " + Keys.TABLE_NAME + " (" + - Keys._ID + " " + Keys._ID_type + "," + - Keys.KEY_ID + " " + Keys.KEY_ID_type + ", " + - Keys.TYPE + " " + Keys.TYPE_type + ", " + - Keys.IS_MASTER_KEY + " " + Keys.IS_MASTER_KEY_type + ", " + - Keys.ALGORITHM + " " + Keys.ALGORITHM_type + ", " + - Keys.KEY_SIZE + " " + Keys.KEY_SIZE_type + ", " + - Keys.CAN_SIGN + " " + Keys.CAN_SIGN_type + ", " + - Keys.CAN_ENCRYPT + " " + Keys.CAN_ENCRYPT_type + ", " + - Keys.IS_REVOKED + " " + Keys.IS_REVOKED_type + ", " + - Keys.CREATION + " " + Keys.CREATION_type + ", " + - Keys.EXPIRY + " " + Keys.EXPIRY_type + ", " + - Keys.KEY_RING_ID + " " + Keys.KEY_RING_ID_type + ", " + - Keys.KEY_DATA + " " + Keys.KEY_DATA_type + - Keys.RANK + " " + Keys.RANK_type + ");"); - - db.execSQL("CREATE TABLE " + UserIds.TABLE_NAME + " (" + - UserIds._ID + " " + UserIds._ID_type + "," + - UserIds.KEY_ID + " " + UserIds.KEY_ID_type + "," + - UserIds.USER_ID + " " + UserIds.USER_ID_type + "," + - UserIds.RANK + " " + UserIds.RANK_type + ");"); - - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - mDb = db; - for (int version = oldVersion; version < newVersion; ++version) { - switch (version) { - case 1: { // upgrade 1 to 2 - db.execSQL("DROP TABLE IF EXISTS " + KeyRings.TABLE_NAME + ";"); - db.execSQL("DROP TABLE IF EXISTS " + Keys.TABLE_NAME + ";"); - db.execSQL("DROP TABLE IF EXISTS " + UserIds.TABLE_NAME + ";"); - - db.execSQL("CREATE TABLE " + KeyRings.TABLE_NAME + " (" + - KeyRings._ID + " " + KeyRings._ID_type + "," + - KeyRings.MASTER_KEY_ID + " " + KeyRings.MASTER_KEY_ID_type + ", " + - KeyRings.TYPE + " " + KeyRings.TYPE_type + ", " + - KeyRings.WHO_ID + " " + KeyRings.WHO_ID_type + ", " + - KeyRings.KEY_RING_DATA + " " + KeyRings.KEY_RING_DATA_type + ");"); - - - db.execSQL("CREATE TABLE " + Keys.TABLE_NAME + " (" + - Keys._ID + " " + Keys._ID_type + "," + - Keys.KEY_ID + " " + Keys.KEY_ID_type + ", " + - Keys.TYPE + " " + Keys.TYPE_type + ", " + - Keys.IS_MASTER_KEY + " " + Keys.IS_MASTER_KEY_type + ", " + - Keys.ALGORITHM + " " + Keys.ALGORITHM_type + ", " + - Keys.KEY_SIZE + " " + Keys.KEY_SIZE_type + ", " + - Keys.CAN_SIGN + " " + Keys.CAN_SIGN_type + ", " + - Keys.CAN_ENCRYPT + " " + Keys.CAN_ENCRYPT_type + ", " + - Keys.IS_REVOKED + " " + Keys.IS_REVOKED_type + ", " + - Keys.CREATION + " " + Keys.CREATION_type + ", " + - Keys.EXPIRY + " " + Keys.EXPIRY_type + ", " + - Keys.KEY_RING_ID + " " + Keys.KEY_RING_ID_type + ", " + - Keys.KEY_DATA + " " + Keys.KEY_DATA_type + - Keys.RANK + " " + Keys.RANK_type + ");"); - - db.execSQL("CREATE TABLE " + UserIds.TABLE_NAME + " (" + - UserIds._ID + " " + UserIds._ID_type + "," + - UserIds.KEY_ID + " " + UserIds.KEY_ID_type + "," + - UserIds.USER_ID + " " + UserIds.USER_ID_type + "," + - UserIds.RANK + " " + UserIds.RANK_type + ");"); - - Cursor cursor = db.query("public_keys", new String[] { "c_key_data" }, - null, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - do { - byte[] data = cursor.getBlob(0); - try { - PGPPublicKeyRing keyRing = new PGPPublicKeyRing(data); - saveKeyRing(keyRing); - } catch (IOException e) { - Log.e("apg.db.upgrade", "key import failed: " + e); - } catch (GeneralException e) { - Log.e("apg.db.upgrade", "key import failed: " + e); - } - } while (cursor.moveToNext()); - } - - if (cursor != null) { - cursor.close(); - } - - cursor = db.query("secret_keys", new String[]{ "c_key_data" }, - null, null, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - do { - byte[] data = cursor.getBlob(0); - try { - PGPSecretKeyRing keyRing = new PGPSecretKeyRing(data); - saveKeyRing(keyRing); - } catch (IOException e) { - Log.e("apg.db.upgrade", "key import failed: " + e); - } catch (PGPException e) { - Log.e("apg.db.upgrade", "key import failed: " + e); - } catch (GeneralException e) { - Log.e("apg.db.upgrade", "key import failed: " + e); - } - } while (cursor.moveToNext()); - } - - if (cursor != null) { - cursor.close(); - } - - db.execSQL("DROP TABLE IF EXISTS public_keys;"); - db.execSQL("DROP TABLE IF EXISTS secret_keys;"); - - break; - } - - default: { - break; - } - } - } - mDb = null; - } - - public int saveKeyRing(PGPPublicKeyRing keyRing) throws IOException, GeneralException { - mDb.beginTransaction(); - ContentValues values = new ContentValues(); - PGPPublicKey masterKey = keyRing.getPublicKey(); - long masterKeyId = masterKey.getKeyID(); - - values.put(KeyRings.MASTER_KEY_ID, masterKeyId); - values.put(KeyRings.TYPE, Id.database.type_public); - values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); - - long rowId = insertOrUpdateKeyRing(values); - int returnValue = mStatus; - - if (rowId == -1) { - throw new GeneralException("saving public key ring " + masterKeyId + " failed"); - } - - Vector seenIds = new Vector(); - int rank = 0; - for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { - seenIds.add(saveKey(rowId, key, rank)); - ++rank; - } - - String seenIdsStr = ""; - for (Integer id : seenIds) { - if (seenIdsStr.length() > 0) { - seenIdsStr += ","; - } - seenIdsStr += id; - } - mDb.delete(Keys.TABLE_NAME, - Keys.KEY_RING_ID + " = ? AND " + - Keys._ID + " NOT IN (" + seenIdsStr + ")", - new String[] { "" + rowId }); - - mDb.setTransactionSuccessful(); - mDb.endTransaction(); - return returnValue; - } - - public int saveKeyRing(PGPSecretKeyRing keyRing) throws IOException, GeneralException { - mDb.beginTransaction(); - ContentValues values = new ContentValues(); - PGPSecretKey masterKey = keyRing.getSecretKey(); - long masterKeyId = masterKey.getKeyID(); - - values.put(KeyRings.MASTER_KEY_ID, masterKeyId); - values.put(KeyRings.TYPE, Id.database.type_secret); - values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); - - long rowId = insertOrUpdateKeyRing(values); - int returnValue = mStatus; - - if (rowId == -1) { - throw new GeneralException("saving secret key ring " + masterKeyId + " failed"); - } - - Vector seenIds = new Vector(); - int rank = 0; - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - seenIds.add(saveKey(rowId, key, rank)); - ++rank; - } - - String seenIdsStr = ""; - for (Integer id : seenIds) { - if (seenIdsStr.length() > 0) { - seenIdsStr += ","; - } - seenIdsStr += id; - } - mDb.delete(Keys.TABLE_NAME, - Keys.KEY_RING_ID + " = ? AND " + - Keys._ID + " NOT IN (" + seenIdsStr + ")", - new String[] { "" + rowId }); - - mDb.setTransactionSuccessful(); - mDb.endTransaction(); - return returnValue; - } - - private int saveKey(long keyRingId, PGPPublicKey key, int rank) - throws IOException, GeneralException { - ContentValues values = new ContentValues(); - - values.put(Keys.KEY_ID, key.getKeyID()); - values.put(Keys.TYPE, Id.database.type_public); - 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, PGPHelper.isSigningKey(key)); - values.put(Keys.CAN_ENCRYPT, PGPHelper.isEncryptionKey(key)); - values.put(Keys.IS_REVOKED, key.isRevoked()); - values.put(Keys.CREATION, PGPHelper.getCreationDate(key).getTime() / 1000); - Date expiryDate = PGPHelper.getExpiryDate(key); - if (expiryDate != null) { - values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); - } - values.put(Keys.KEY_RING_ID, keyRingId); - values.put(Keys.KEY_DATA, key.getEncoded()); - values.put(Keys.RANK, rank); - - long rowId = insertOrUpdateKey(values); - - if (rowId == -1) { - throw new GeneralException("saving public key " + key.getKeyID() + " failed"); - } - - Vector seenIds = new Vector(); - int userIdRank = 0; - for (String userId : new IterableIterator(key.getUserIDs())) { - seenIds.add(saveUserId(rowId, userId, userIdRank)); - ++userIdRank; - } - - String seenIdsStr = ""; - for (Integer id : seenIds) { - if (seenIdsStr.length() > 0) { - seenIdsStr += ","; - } - seenIdsStr += id; - } - mDb.delete(UserIds.TABLE_NAME, - UserIds.KEY_ID + " = ? AND " + - UserIds._ID + " NOT IN (" + seenIdsStr + ")", - new String[] { "" + rowId }); - - return (int)rowId; - } - - private int saveKey(long keyRingId, PGPSecretKey key, int rank) - throws IOException, GeneralException { - ContentValues values = new ContentValues(); - - values.put(Keys.KEY_ID, key.getPublicKey().getKeyID()); - values.put(Keys.TYPE, Id.database.type_secret); - 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_SIGN, PGPHelper.isSigningKey(key)); - values.put(Keys.CAN_ENCRYPT, PGPHelper.isEncryptionKey(key)); - values.put(Keys.IS_REVOKED, key.getPublicKey().isRevoked()); - values.put(Keys.CREATION, PGPHelper.getCreationDate(key).getTime() / 1000); - Date expiryDate = PGPHelper.getExpiryDate(key); - if (expiryDate != null) { - values.put(Keys.EXPIRY, expiryDate.getTime() / 1000); - } - values.put(Keys.KEY_RING_ID, keyRingId); - values.put(Keys.KEY_DATA, key.getEncoded()); - values.put(Keys.RANK, rank); - - long rowId = insertOrUpdateKey(values); - - if (rowId == -1) { - throw new GeneralException("saving secret key " + key.getPublicKey().getKeyID() + " failed"); - } - - Vector seenIds = new Vector(); - int userIdRank = 0; - for (String userId : new IterableIterator(key.getUserIDs())) { - seenIds.add(saveUserId(rowId, userId, userIdRank)); - ++userIdRank; - } - - String seenIdsStr = ""; - for (Integer id : seenIds) { - if (seenIdsStr.length() > 0) { - seenIdsStr += ","; - } - seenIdsStr += id; - } - mDb.delete(UserIds.TABLE_NAME, - UserIds.KEY_ID + " = ? AND " + - UserIds._ID + " NOT IN (" + seenIdsStr + ")", - new String[] { "" + rowId }); - - return (int)rowId; - } - - private int saveUserId(long keyId, String userId, int rank) throws GeneralException { - ContentValues values = new ContentValues(); - - values.put(UserIds.KEY_ID, keyId); - values.put(UserIds.USER_ID, userId); - values.put(UserIds.RANK, rank); - - long rowId = insertOrUpdateUserId(values); - - if (rowId == -1) { - throw new GeneralException("saving user id " + userId + " failed"); - } - - return (int)rowId; - } - - private long insertOrUpdateKeyRing(ContentValues values) { - Cursor c = mDb.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, - KeyRings.MASTER_KEY_ID + " = ? AND " + KeyRings.TYPE + " = ?", - new String[] { - values.getAsString(KeyRings.MASTER_KEY_ID), - values.getAsString(KeyRings.TYPE), - }, - null, null, null); - long rowId = -1; - if (c != null && c.moveToFirst()) { - rowId = c.getLong(0); - mDb.update(KeyRings.TABLE_NAME, values, - KeyRings._ID + " = ?", new String[] { "" + rowId }); - mStatus = Id.return_value.updated; - } else { - rowId = mDb.insert(KeyRings.TABLE_NAME, KeyRings.WHO_ID, values); - mStatus = Id.return_value.ok; - } - - if (c != null) { - c.close(); - } - - return rowId; - } - - private long insertOrUpdateKey(ContentValues values) { - Cursor c = mDb.query(Keys.TABLE_NAME, new String[] { Keys._ID }, - Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?", - new String[] { - values.getAsString(Keys.KEY_ID), - values.getAsString(Keys.TYPE), - }, - null, null, null); - long rowId = -1; - if (c != null && c.moveToFirst()) { - rowId = c.getLong(0); - mDb.update(Keys.TABLE_NAME, values, - Keys._ID + " = ?", new String[] { "" + rowId }); - } else { - rowId = mDb.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values); - } - - if (c != null) { - c.close(); - } - - return rowId; - } - - private long insertOrUpdateUserId(ContentValues values) { - Cursor c = mDb.query(UserIds.TABLE_NAME, new String[] { UserIds._ID }, - UserIds.KEY_ID + " = ? AND " + UserIds.USER_ID + " = ?", - new String[] { - values.getAsString(UserIds.KEY_ID), - values.getAsString(UserIds.USER_ID), - }, - null, null, null); - long rowId = -1; - if (c != null && c.moveToFirst()) { - rowId = c.getLong(0); - mDb.update(UserIds.TABLE_NAME, values, - UserIds._ID + " = ?", new String[] { "" + rowId }); - } else { - rowId = mDb.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values); - } - - if (c != null) { - c.close(); - } - - return rowId; - } - - public Object getKeyRing(int keyRingId) { - Cursor c = mDb.query(KeyRings.TABLE_NAME, - new String[] { KeyRings.KEY_RING_DATA, KeyRings.TYPE }, - KeyRings._ID + " = ?", - new String[] { - "" + keyRingId, - }, - null, null, null); - byte[] data = null; - Object keyRing = null; - if (c != null && c.moveToFirst()) { - data = c.getBlob(0); - if (data != null) { - try { - if (c.getInt(1) == Id.database.type_public) { - keyRing = new PGPPublicKeyRing(data); - } else { - keyRing = new PGPSecretKeyRing(data); - } - } catch (IOException e) { - // can't load it, then - } catch (PGPException e) { - // can't load it, then - } - } - } - - if (c != null) { - c.close(); - } - - return keyRing; - } - - public byte[] getKeyRingDataFromKeyId(int type, long keyId) { - Cursor c = mDb.query(Keys.TABLE_NAME + " INNER JOIN " + KeyRings.TABLE_NAME + " ON (" + - KeyRings.TABLE_NAME + "." + KeyRings._ID + " = " + - Keys.TABLE_NAME + "." + Keys.KEY_RING_ID + ")", - new String[] { KeyRings.TABLE_NAME + "." + KeyRings.KEY_RING_DATA }, - Keys.TABLE_NAME + "." + Keys.KEY_ID + " = ? AND " + - KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", - new String[] { - "" + keyId, - "" + type, - }, - null, null, null); - - byte[] data = null; - if (c != null && c.moveToFirst()) { - data = c.getBlob(0); - } - - if (c != null) { - c.close(); - } - - return data; - } - - public byte[] getKeyDataFromKeyId(int type, long keyId) { - Cursor c = mDb.query(Keys.TABLE_NAME, new String[] { Keys.KEY_DATA }, - Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?", - new String[] { - "" + keyId, - "" + type, - }, - null, null, null); - byte[] data = null; - if (c != null && c.moveToFirst()) { - data = c.getBlob(0); - } - - if (c != null) { - c.close(); - } - - return data; - } - - public void deleteKeyRing(int keyRingId) { - mDb.beginTransaction(); - mDb.delete(KeyRings.TABLE_NAME, - KeyRings._ID + " = ?", new String[] { "" + keyRingId }); - - Cursor c = mDb.query(Keys.TABLE_NAME, new String[] { Keys._ID }, - Keys.KEY_RING_ID + " = ?", - new String[] { - "" + keyRingId, - }, - null, null, null); - if (c != null && c.moveToFirst()) { - do { - int keyId = c.getInt(0); - deleteKey(keyId); - } while (c.moveToNext()); - } - - if (c != null) { - c.close(); - } - - mDb.setTransactionSuccessful(); - mDb.endTransaction(); - } - - private void deleteKey(int keyId) { - mDb.delete(Keys.TABLE_NAME, - Keys._ID + " = ?", new String[] { "" + keyId }); - - mDb.delete(UserIds.TABLE_NAME, - UserIds.KEY_ID + " = ?", new String[] { "" + keyId }); - } - - public SQLiteDatabase db() { - return mDb; - } -} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java b/org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java deleted file mode 100644 index 58e95eba6..000000000 --- a/org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2010 Thialfihar - * - * 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.thialfihar.android.apg.provider; - -import android.provider.BaseColumns; - -public class KeyRings implements BaseColumns { - public static final String TABLE_NAME = "key_rings"; - - public static final String _ID_type = "INTEGER PRIMARY KEY"; - public static final String MASTER_KEY_ID = "c_master_key_id"; - public static final String MASTER_KEY_ID_type = "INT64"; - public static final String TYPE = "c_type"; - public static final String TYPE_type = "INTEGER"; - public static final String WHO_ID = "c_who_id"; - public static final String WHO_ID_type = "INTEGER"; - public static final String KEY_RING_DATA = "c_key_ring_data"; - public static final String KEY_RING_DATA_type = "BLOB"; -} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/Keys.java b/org_apg/src/org/thialfihar/android/apg/provider/Keys.java deleted file mode 100644 index 618c5e920..000000000 --- a/org_apg/src/org/thialfihar/android/apg/provider/Keys.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 Thialfihar - * - * 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.thialfihar.android.apg.provider; - -import android.provider.BaseColumns; - -public class Keys implements BaseColumns { - public static final String TABLE_NAME = "keys"; - - public static final String _ID_type = "INTEGER PRIMARY KEY"; - public static final String KEY_ID = "c_key_id"; - public static final String KEY_ID_type = "INT64"; - public static final String TYPE = "c_type"; - public static final String TYPE_type = "INTEGER"; - public static final String IS_MASTER_KEY = "c_is_master_key"; - public static final String IS_MASTER_KEY_type = "INTEGER"; - public static final String ALGORITHM = "c_algorithm"; - public static final String ALGORITHM_type = "INTEGER"; - public static final String KEY_SIZE = "c_key_size"; - public static final String KEY_SIZE_type = "INTEGER"; - public static final String CAN_SIGN = "c_can_sign"; - public static final String CAN_SIGN_type = "INTEGER"; - public static final String CAN_ENCRYPT = "c_can_encrypt"; - public static final String CAN_ENCRYPT_type = "INTEGER"; - public static final String IS_REVOKED = "c_is_revoked"; - public static final String IS_REVOKED_type = "INTEGER"; - public static final String CREATION = "c_creation"; - public static final String CREATION_type = "INTEGER"; - public static final String EXPIRY = "c_expiry"; - public static final String EXPIRY_type = "INTEGER"; - public static final String KEY_RING_ID = "c_key_ring_id"; - public static final String KEY_RING_ID_type = "INTEGER"; - public static final String KEY_DATA = "c_key_data"; - public static final String KEY_DATA_type = "BLOB"; - public static final String RANK = "c_key_data"; - public static final String RANK_type = "INTEGER"; -} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java b/org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java new file mode 100644 index 000000000..234f96bd0 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java @@ -0,0 +1,79 @@ +package org.thialfihar.android.apg.provider; + +import java.io.IOException; + +import org.spongycastle.openpgp.PGPPublicKey; +import org.spongycastle.openpgp.PGPPublicKeyRing; +import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException; +import org.thialfihar.android.apg.provider.ApgContract.PublicKeyRings; +import org.thialfihar.android.apg.provider.ApgContract.PublicKeys; +import org.thialfihar.android.apg.provider.ApgContract.SecretKeys; + +import android.content.ContentValues; +import android.content.Context; + +public class ProviderHelper { + // public static void insertHostsSource(Context context, String url) { + // ContentValues values = new ContentValues(); + // values.put(HostsSources.URL, url); + // values.put(HostsSources.ENABLED, true); // default is enabled + // values.put(HostsSources.LAST_MODIFIED_LOCAL, 0); // last_modified_local starts at 0 + // values.put(HostsSources.LAST_MODIFIED_ONLINE, 0); // last_modified_onlinestarts at 0 + // context.getContentResolver().insert(HostsSources.CONTENT_URI, values); + // } + + // public int saveKeyRing(Context context, PGPPublicKeyRing keyRing) throws IOException, + // ApgGeneralException { + // // mDb.beginTransaction(); + // ContentValues values = new ContentValues(); + // PGPPublicKey masterKey = keyRing.getPublicKey(); + // long masterKeyId = masterKey.getKeyID(); + // + // values.put(PublicKeyRings.MASTER_KEY_ID, masterKeyId); + // // values.put(KeyRings.TYPE, Id.database.type_public); + // values.put(PublicKeyRings.KEY_RING_DATA, keyRing.getEncoded()); + // + // context.getContentResolver().insert(PublicKeyRings.CONTENT_URI, values); + // + // long rowId = insertOrUpdateKeyRing(values); + // int returnValue = mStatus; + // + // if (rowId == -1) { + // throw new ApgGeneralException("saving public key ring " + masterKeyId + " failed"); + // } + // + // Vector seenIds = new Vector(); + // int rank = 0; + // for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { + // seenIds.add(saveKey(rowId, key, rank)); + // ++rank; + // } + // + // String seenIdsStr = ""; + // for (Integer id : seenIds) { + // if (seenIdsStr.length() > 0) { + // seenIdsStr += ","; + // } + // seenIdsStr += id; + // } + // mDb.delete(Keys.TABLE_NAME, Keys.KEY_RING_ID + " = ? AND " + Keys._ID + " NOT IN (" + // + seenIdsStr + ")", new String[] { "" + rowId }); + // + // mDb.setTransactionSuccessful(); + // mDb.endTransaction(); + // return returnValue; + // } + + /** + * Deletes public and secret keys + * + * @param context + * @param rowId + */ + public static void deleteKey(Context context, long rowId) { + context.getContentResolver().delete(PublicKeys.buildPublicKeysUri(Long.toString(rowId)), + null, null); + context.getContentResolver().delete(SecretKeys.buildSecretKeysUri(Long.toString(rowId)), + null, null); + } +} diff --git a/org_apg/src/org/thialfihar/android/apg/provider/UserIds.java b/org_apg/src/org/thialfihar/android/apg/provider/UserIds.java deleted file mode 100644 index 2050ccf9c..000000000 --- a/org_apg/src/org/thialfihar/android/apg/provider/UserIds.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2010 Thialfihar - * - * 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.thialfihar.android.apg.provider; - -import android.provider.BaseColumns; - -public class UserIds implements BaseColumns { - public static final String TABLE_NAME = "user_ids"; - - public static final String _ID_type = "INTEGER PRIMARY KEY"; - public static final String KEY_ID = "c_key_id"; - public static final String KEY_ID_type = "INTEGER"; - public static final String USER_ID = "c_user_id"; - public static final String USER_ID_type = "TEXT"; - public static final String RANK = "c_rank"; - public static final String RANK_type = "INTEGER"; -} diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java index dbb0900e3..c324c4c62 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java @@ -35,13 +35,15 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; +import org.thialfihar.android.apg.deprecated.DataProvider; import org.thialfihar.android.apg.helper.FileHelper; import org.thialfihar.android.apg.helper.OtherHelper; import org.thialfihar.android.apg.helper.PGPMain; import org.thialfihar.android.apg.helper.Preferences; -import org.thialfihar.android.apg.helper.PGPMain.GeneralException; +import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException; import org.thialfihar.android.apg.helper.PGPConversionHelper; -import org.thialfihar.android.apg.provider.DataProvider; +import org.thialfihar.android.apg.provider.ApgContract.DataStream; +import org.thialfihar.android.apg.provider.ApgProvider; import org.thialfihar.android.apg.util.HkpKeyServer; import org.thialfihar.android.apg.util.InputData; import org.thialfihar.android.apg.util.KeyServer.KeyInfo; @@ -271,7 +273,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // check if storage is ready if (!FileHelper.isStorageMounted(inputFile) || !FileHelper.isStorageMounted(outputFile)) { - sendErrorToHandler(new GeneralException( + sendErrorToHandler(new ApgGeneralException( getString(R.string.error_externalStorageNotReady))); return; } @@ -298,7 +300,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { while (true) { streamFilename = PGPMain.generateRandomString(32); if (streamFilename == null) { - throw new PGPMain.GeneralException( + throw new PGPMain.ApgGeneralException( "couldn't generate random file name"); } openFileInput(streamFilename).close(); @@ -311,7 +313,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { break; default: - throw new PGPMain.GeneralException("No target choosen!"); + throw new PGPMain.ApgGeneralException("No target choosen!"); } @@ -372,7 +374,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { break; case TARGET_STREAM: - String uri = "content://" + DataProvider.AUTHORITY + "/data/" + streamFilename; + String uri = DataStream.buildDataStreamUri(streamFilename).toString(); resultData.putString(RESULT_URI, uri); break; @@ -422,7 +424,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // check if storage is ready if (!FileHelper.isStorageMounted(inputFile) || !FileHelper.isStorageMounted(outputFile)) { - sendErrorToHandler(new GeneralException( + sendErrorToHandler(new ApgGeneralException( getString(R.string.error_externalStorageNotReady))); return; } @@ -452,7 +454,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { while (true) { streamFilename = PGPMain.generateRandomString(32); if (streamFilename == null) { - throw new PGPMain.GeneralException( + throw new PGPMain.ApgGeneralException( "couldn't generate random file name"); } openFileInput(streamFilename).close(); @@ -465,7 +467,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { break; default: - throw new PGPMain.GeneralException("No target choosen!"); + throw new PGPMain.ApgGeneralException("No target choosen!"); } @@ -505,7 +507,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { break; case TARGET_STREAM: - String uri = "content://" + DataProvider.AUTHORITY + "/data/" + streamFilename; + String uri = DataStream.buildDataStreamUri(streamFilename).toString(); resultData.putString(RESULT_URI, uri); break; @@ -617,10 +619,10 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { try { PGPMain.deleteFileSecurely(this, new File(deleteFile), this); } catch (FileNotFoundException e) { - throw new PGPMain.GeneralException(getString(R.string.error_fileNotFound, + throw new PGPMain.ApgGeneralException(getString(R.string.error_fileNotFound, deleteFile)); } catch (IOException e) { - throw new PGPMain.GeneralException(getString(R.string.error_fileDeleteFailed, + throw new PGPMain.ApgGeneralException(getString(R.string.error_fileDeleteFailed, deleteFile)); } @@ -703,7 +705,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // check if storage is ready if (!FileHelper.isStorageMounted(outputFile)) { - sendErrorToHandler(new GeneralException( + sendErrorToHandler(new ApgGeneralException( getString(R.string.error_externalStorageNotReady))); return; } @@ -745,7 +747,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { boolean uploaded = PGPMain.uploadKeyRingToServer(server, (PGPPublicKeyRing) keyring); if (!uploaded) { - sendErrorToHandler(new GeneralException( + sendErrorToHandler(new ApgGeneralException( "Unable to export key to selected server")); return; } @@ -806,7 +808,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // store the signed key in our local cache int retval = PGPMain.storeKeyRingInCache(signedPubKeyRing); if (retval != Id.return_value.ok && retval != Id.return_value.updated) { - throw new GeneralException("Failed to store signed key in local cache"); + throw new ApgGeneralException("Failed to store signed key in local cache"); } sendMessageToHandler(ApgServiceHandler.MESSAGE_OKAY); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java index c41400f5a..7e7344c4e 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Dominik Schürmann * Copyright (C) 2010 Thialfihar * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -607,7 +608,7 @@ public class DecryptActivity extends SherlockFragmentActivity { messenger, mSecretKeyId); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PGPMain.GeneralException e) { + } catch (PGPMain.ApgGeneralException e) { Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); // send message to handler to start encryption directly returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); @@ -654,13 +655,13 @@ public class DecryptActivity extends SherlockFragmentActivity { try { setSecretKeyId(PGPMain.getDecryptionKeyId(this, inStream)); if (getSecretKeyId() == Id.key.none) { - throw new PGPMain.GeneralException(getString(R.string.error_noSecretKeyFound)); + throw new PGPMain.ApgGeneralException(getString(R.string.error_noSecretKeyFound)); } mAssumeSymmetricEncryption = false; } catch (PGPMain.NoAsymmetricEncryptionException e) { setSecretKeyId(Id.key.symmetric); if (!PGPMain.hasSymmetricEncryption(this, inStream)) { - throw new PGPMain.GeneralException( + throw new PGPMain.ApgGeneralException( getString(R.string.error_noKnownEncryptionFound)); } mAssumeSymmetricEncryption = true; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java index 60b108541..0d15014b7 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java @@ -407,7 +407,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { private void saveClicked() { try { if (!isPassphraseSet()) { - throw new PGPMain.GeneralException(this.getString(R.string.setAPassPhrase)); + throw new PGPMain.ApgGeneralException(this.getString(R.string.setAPassPhrase)); } // Send all information needed to service to edit key in other thread @@ -448,7 +448,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { // start service with intent startService(intent); - } catch (PGPMain.GeneralException e) { + } catch (PGPMain.ApgGeneralException e) { Toast.makeText(this, getString(R.string.errorMessage, e.getMessage()), Toast.LENGTH_SHORT).show(); } @@ -460,7 +460,7 @@ public class EditKeyActivity extends SherlockFragmentActivity { * @param userIdsView * @return */ - private ArrayList getUserIds(SectionView userIdsView) throws PGPMain.GeneralException { + private ArrayList getUserIds(SectionView userIdsView) throws PGPMain.ApgGeneralException { ArrayList userIds = new ArrayList(); ViewGroup userIdEditors = userIdsView.getEditors(); @@ -472,12 +472,12 @@ public class EditKeyActivity extends SherlockFragmentActivity { try { userId = editor.getValue(); } catch (UserIdEditor.NoNameException e) { - throw new PGPMain.GeneralException(this.getString(R.string.error_userIdNeedsAName)); + throw new PGPMain.ApgGeneralException(this.getString(R.string.error_userIdNeedsAName)); } catch (UserIdEditor.NoEmailException e) { - throw new PGPMain.GeneralException( + throw new PGPMain.ApgGeneralException( this.getString(R.string.error_userIdNeedsAnEmailAddress)); } catch (UserIdEditor.InvalidEmailException e) { - throw new PGPMain.GeneralException(e.getMessage()); + throw new PGPMain.ApgGeneralException(e.getMessage()); } if (userId.equals("")) { @@ -493,11 +493,11 @@ public class EditKeyActivity extends SherlockFragmentActivity { } if (userIds.size() == 0) { - throw new PGPMain.GeneralException(getString(R.string.error_keyNeedsAUserId)); + throw new PGPMain.ApgGeneralException(getString(R.string.error_keyNeedsAUserId)); } if (!gotMainUserId) { - throw new PGPMain.GeneralException(getString(R.string.error_mainUserIdMustNotBeEmpty)); + throw new PGPMain.ApgGeneralException(getString(R.string.error_mainUserIdMustNotBeEmpty)); } return userIds; @@ -509,13 +509,13 @@ public class EditKeyActivity extends SherlockFragmentActivity { * @param keysView * @return */ - private ArrayList getKeys(SectionView keysView) throws PGPMain.GeneralException { + private ArrayList getKeys(SectionView keysView) throws PGPMain.ApgGeneralException { ArrayList keys = new ArrayList(); ViewGroup keyEditors = keysView.getEditors(); if (keyEditors.getChildCount() == 0) { - throw new PGPMain.GeneralException(getString(R.string.error_keyNeedsMasterKey)); + throw new PGPMain.ApgGeneralException(getString(R.string.error_keyNeedsMasterKey)); } for (int i = 0; i < keyEditors.getChildCount(); ++i) { @@ -532,13 +532,13 @@ public class EditKeyActivity extends SherlockFragmentActivity { * @param keysView * @return */ - private ArrayList getKeysUsages(SectionView keysView) throws PGPMain.GeneralException { + private ArrayList getKeysUsages(SectionView keysView) throws PGPMain.ApgGeneralException { ArrayList getKeysUsages = new ArrayList(); ViewGroup keyEditors = keysView.getEditors(); if (keyEditors.getChildCount() == 0) { - throw new PGPMain.GeneralException(getString(R.string.error_keyNeedsMasterKey)); + throw new PGPMain.ApgGeneralException(getString(R.string.error_keyNeedsMasterKey)); } for (int i = 0; i < keyEditors.getChildCount(); ++i) { diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java index 0ed45d7f4..dfdfe4d5c 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EncryptActivity.java @@ -732,7 +732,7 @@ public class EncryptActivity extends SherlockFragmentActivity { EncryptActivity.this, messenger, mSecretKeyId); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PGPMain.GeneralException e) { + } catch (PGPMain.ApgGeneralException e) { Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); // send message to handler to start encryption directly returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java index de799e2ac..c06c68943 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java @@ -169,7 +169,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli SecretKeyListActivity.this, messenger, secretKeyId); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PGPMain.GeneralException e) { + } catch (PGPMain.ApgGeneralException e) { Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); // send message to handler to start encryption directly returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java index 2fa0e9c96..3311c320e 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/SignKeyActivity.java @@ -143,7 +143,7 @@ public class SignKeyActivity extends SherlockFragmentActivity { messenger, secretKeyId); passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog"); - } catch (PGPMain.GeneralException e) { + } catch (PGPMain.ApgGeneralException e) { Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); // send message to handler to start encryption directly returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java index e8ef76e50..230423715 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/PassphraseDialogFragment.java @@ -23,7 +23,7 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; import org.thialfihar.android.apg.helper.PGPHelper; import org.thialfihar.android.apg.helper.PGPMain; -import org.thialfihar.android.apg.helper.PGPMain.GeneralException; +import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.R; @@ -73,14 +73,14 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor * @param messenger * to communicate back after caching the passphrase * @return - * @throws GeneralException + * @throws ApgGeneralException */ public static PassphraseDialogFragment newInstance(Context context, Messenger messenger, - long secretKeyId) throws GeneralException { + long secretKeyId) throws ApgGeneralException { // check if secret key has a passphrase if (!(secretKeyId == Id.key.symmetric || secretKeyId == Id.key.none)) { if (!hasPassphrase(context, secretKeyId)) { - throw new PGPMain.GeneralException("No passphrase! No passphrase dialog needed!"); + throw new PGPMain.ApgGeneralException("No passphrase! No passphrase dialog needed!"); } } diff --git a/org_apg/src/org/thialfihar/android/apg/util/Compatibility.java b/org_apg/src/org/thialfihar/android/apg/util/Compatibility.java index e984362c3..1597a01f4 100644 --- a/org_apg/src/org/thialfihar/android/apg/util/Compatibility.java +++ b/org_apg/src/org/thialfihar/android/apg/util/Compatibility.java @@ -26,8 +26,7 @@ public class Compatibility { private static final String clipboardLabel = "APG"; /** - * Wrapper around ClipboardManager based on Android version using Reflection API, from - * http://www.projectsexception.com/blog/?p=87 + * Wrapper around ClipboardManager based on Android version using Reflection API * * @param context * @param text