started restructuring APGs Provider and Database

This commit is contained in:
Dominik 2012-09-18 18:35:14 +02:00
parent a507204b9e
commit fb49f9e9c8
22 changed files with 2163 additions and 1232 deletions

View File

@ -46,7 +46,7 @@
-->
<uses-sdk
android:minSdkVersion="7"
android:minSdkVersion="8"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.INTERNET" />
@ -339,7 +339,7 @@
<service android:name=".service.ApgService" />
<provider
android:name=".provider.DataProvider"
android:name=".deprecated.DataProvider"
android:authorities="org.thialfihar.android.apg.provider"
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS" />

View File

@ -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;

View File

@ -0,0 +1,381 @@
///*
// * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package org.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<String, String> projectionMap = new HashMap<String, String>();
//
// 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 '*<email>', so it has to be at the *end* of the user id
// emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">");
// gotCondition = true;
// }
//
// if (gotCondition) {
// qb.appendWhere(" AND EXISTS (SELECT tmp." + 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);
// }
//}

View File

@ -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<String, String> sKeyRingsProjection;
// public static HashMap<String, String> sKeysProjection;
// public static HashMap<String, String> sUserIdsProjection;
//
// private SQLiteDatabase mDb = null;
// private int mStatus = 0;
//
// static {
// sKeyRingsProjection = new HashMap<String, String>();
// 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<String, String>();
// 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<String, String>();
// 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<Integer> seenIds = new Vector<Integer>();
// int rank = 0;
// for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(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<Integer> seenIds = new Vector<Integer>();
// int rank = 0;
// for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(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<Integer> seenIds = new Vector<Integer>();
// int userIdRank = 0;
// for (String userId : new IterableIterator<String>(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<Integer> seenIds = new Vector<Integer>();
// int userIdRank = 0;
// for (String userId : new IterableIterator<String>(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;
// }
//}

View File

@ -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<String> userIds,
ArrayList<PGPSecretKey> keys, ArrayList<Integer> 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<Integer> 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;

View File

@ -0,0 +1,235 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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() {
}
}

View File

@ -0,0 +1,143 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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<String, String> sKeyRingsProjection;
// public static HashMap<String, String> sKeysProjection;
// public static HashMap<String, String> sUserIdsProjection;
//
// private SQLiteDatabase mDb = null;
// private int mStatus = 0;
//
// static {
// sKeyRingsProjection = new HashMap<String, String>();
// 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<String, String>();
// 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<String, String>();
// 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;
}
}
}
}

View File

@ -0,0 +1,589 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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
*
* <pre>
* key_rings/public
* key_rings/public/_
* key_rings/public/key_id/_
* key_rings/public/emails/_
* </pre>
*/
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
*
* <pre>
* key_rings/public/_/keys
* key_rings/public/_/keys/#
* </pre>
*/
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
*
* <pre>
* key_rings/public/_/user_ids
* key_rings/public/_/user_ids/#
* </pre>
*/
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
*
* <pre>
* key_rings/secret
* key_rings/secret/*
* key_rings/secret/key_id/*
* key_rings/secret/emails/*
* </pre>
*/
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
*
* <pre>
* key_rings/secret/_/keys
* key_rings/secret/_/keys/#
* </pre>
*/
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
*
* <pre>
* key_rings/secret/_/user_ids
* key_rings/secret/_/user_ids/#
* </pre>
*/
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
*
* <pre>
* data/*
* </pre>
*/
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<String, String> projectionMap = new HashMap<String, String>();
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 '*<email>', so it has to be at the *end* of the user id
emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">");
gotCondition = true;
}
if (gotCondition) {
qb.appendWhere(" AND EXISTS (SELECT tmp." + BaseColumns._ID + " FROM "
+ Tables.USER_IDS + " AS tmp WHERE tmp." + UserIdsColumns.KEY_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);
}
}

View File

@ -1,381 +0,0 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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<String, String> projectionMap = new HashMap<String, String>();
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 '*<email>', so it has to be at the *end* of the user id
emailWhere += DatabaseUtils.sqlEscapeString("%<" + chunks[i] + ">");
gotCondition = true;
}
if (gotCondition) {
qb.appendWhere(" AND EXISTS (SELECT tmp." + 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);
}
}

View File

@ -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<String, String> sKeyRingsProjection;
public static HashMap<String, String> sKeysProjection;
public static HashMap<String, String> sUserIdsProjection;
private SQLiteDatabase mDb = null;
private int mStatus = 0;
static {
sKeyRingsProjection = new HashMap<String, String>();
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<String, String>();
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<String, String>();
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<Integer> seenIds = new Vector<Integer>();
int rank = 0;
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(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<Integer> seenIds = new Vector<Integer>();
int rank = 0;
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(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<Integer> seenIds = new Vector<Integer>();
int userIdRank = 0;
for (String userId : new IterableIterator<String>(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<Integer> seenIds = new Vector<Integer>();
int userIdRank = 0;
for (String userId : new IterableIterator<String>(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;
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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";
}

View File

@ -1,51 +0,0 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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";
}

View File

@ -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<Integer> seenIds = new Vector<Integer>();
// int rank = 0;
// for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(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);
}
}

View File

@ -1,31 +0,0 @@
/*
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.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";
}

View File

@ -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);

View File

@ -1,4 +1,5 @@
/*
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* 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;

View File

@ -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<String> getUserIds(SectionView userIdsView) throws PGPMain.GeneralException {
private ArrayList<String> getUserIds(SectionView userIdsView) throws PGPMain.ApgGeneralException {
ArrayList<String> userIds = new ArrayList<String>();
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<PGPSecretKey> getKeys(SectionView keysView) throws PGPMain.GeneralException {
private ArrayList<PGPSecretKey> getKeys(SectionView keysView) throws PGPMain.ApgGeneralException {
ArrayList<PGPSecretKey> keys = new ArrayList<PGPSecretKey>();
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<Integer> getKeysUsages(SectionView keysView) throws PGPMain.GeneralException {
private ArrayList<Integer> getKeysUsages(SectionView keysView) throws PGPMain.ApgGeneralException {
ArrayList<Integer> getKeysUsages = new ArrayList<Integer>();
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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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!");
}
}

View File

@ -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