aboutsummaryrefslogtreecommitdiffstats
path: root/org_apg/src/org/thialfihar/android/apg/provider
diff options
context:
space:
mode:
Diffstat (limited to 'org_apg/src/org/thialfihar/android/apg/provider')
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java235
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java143
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java589
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java381
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/Database.java617
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java33
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/Keys.java51
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java79
-rw-r--r--org_apg/src/org/thialfihar/android/apg/provider/UserIds.java31
9 files changed, 1046 insertions, 1113 deletions
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java b/org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java
new file mode 100644
index 000000000..10f9fa05e
--- /dev/null
+++ b/org_apg/src/org/thialfihar/android/apg/provider/ApgContract.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann <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() {
+ }
+}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java b/org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java
new file mode 100644
index 000000000..fdee2f101
--- /dev/null
+++ b/org_apg/src/org/thialfihar/android/apg/provider/ApgDatabase.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann <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;
+
+ }
+ }
+ }
+
+}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java b/org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java
new file mode 100644
index 000000000..e25228434
--- /dev/null
+++ b/org_apg/src/org/thialfihar/android/apg/provider/ApgProvider.java
@@ -0,0 +1,589 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann <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);
+ }
+}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java b/org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java
deleted file mode 100644
index 9cf083528..000000000
--- a/org_apg/src/org/thialfihar/android/apg/provider/DataProvider.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright (C) 2010 Thialfihar <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);
- }
-}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/Database.java b/org_apg/src/org/thialfihar/android/apg/provider/Database.java
deleted file mode 100644
index 0c14283c2..000000000
--- a/org_apg/src/org/thialfihar/android/apg/provider/Database.java
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.thialfihar.android.apg.provider;
-
-import org.spongycastle.openpgp.PGPException;
-import org.spongycastle.openpgp.PGPPublicKey;
-import org.spongycastle.openpgp.PGPPublicKeyRing;
-import org.spongycastle.openpgp.PGPSecretKey;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
-import org.thialfihar.android.apg.Id;
-import org.thialfihar.android.apg.helper.PGPHelper;
-import org.thialfihar.android.apg.util.IterableIterator;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteOpenHelper;
-import org.thialfihar.android.apg.util.Log;
-
-import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Vector;
-
-public class Database extends SQLiteOpenHelper {
- public static class GeneralException extends Exception {
- static final long serialVersionUID = 0xf812773343L;
-
- public GeneralException(String message) {
- super(message);
- }
- }
-
- private static final String DATABASE_NAME = "apg";
- private static final int DATABASE_VERSION = 2;
-
- public static final String AUTHORITY = "org.thialfihar.android.apg.database";
-
- public static HashMap<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;
- }
-}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java b/org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java
deleted file mode 100644
index 58e95eba6..000000000
--- a/org_apg/src/org/thialfihar/android/apg/provider/KeyRings.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010 Thialfihar <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";
-}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/Keys.java b/org_apg/src/org/thialfihar/android/apg/provider/Keys.java
deleted file mode 100644
index 618c5e920..000000000
--- a/org_apg/src/org/thialfihar/android/apg/provider/Keys.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2010 Thialfihar <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";
-}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java b/org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java
new file mode 100644
index 000000000..234f96bd0
--- /dev/null
+++ b/org_apg/src/org/thialfihar/android/apg/provider/ProviderHelper.java
@@ -0,0 +1,79 @@
+package org.thialfihar.android.apg.provider;
+
+import java.io.IOException;
+
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.thialfihar.android.apg.helper.PGPMain.ApgGeneralException;
+import org.thialfihar.android.apg.provider.ApgContract.PublicKeyRings;
+import org.thialfihar.android.apg.provider.ApgContract.PublicKeys;
+import org.thialfihar.android.apg.provider.ApgContract.SecretKeys;
+
+import android.content.ContentValues;
+import android.content.Context;
+
+public class ProviderHelper {
+ // public static void insertHostsSource(Context context, String url) {
+ // ContentValues values = new ContentValues();
+ // values.put(HostsSources.URL, url);
+ // values.put(HostsSources.ENABLED, true); // default is enabled
+ // values.put(HostsSources.LAST_MODIFIED_LOCAL, 0); // last_modified_local starts at 0
+ // values.put(HostsSources.LAST_MODIFIED_ONLINE, 0); // last_modified_onlinestarts at 0
+ // context.getContentResolver().insert(HostsSources.CONTENT_URI, values);
+ // }
+
+ // public int saveKeyRing(Context context, PGPPublicKeyRing keyRing) throws IOException,
+ // ApgGeneralException {
+ // // mDb.beginTransaction();
+ // ContentValues values = new ContentValues();
+ // PGPPublicKey masterKey = keyRing.getPublicKey();
+ // long masterKeyId = masterKey.getKeyID();
+ //
+ // values.put(PublicKeyRings.MASTER_KEY_ID, masterKeyId);
+ // // values.put(KeyRings.TYPE, Id.database.type_public);
+ // values.put(PublicKeyRings.KEY_RING_DATA, keyRing.getEncoded());
+ //
+ // context.getContentResolver().insert(PublicKeyRings.CONTENT_URI, values);
+ //
+ // long rowId = insertOrUpdateKeyRing(values);
+ // int returnValue = mStatus;
+ //
+ // if (rowId == -1) {
+ // throw new ApgGeneralException("saving public key ring " + masterKeyId + " failed");
+ // }
+ //
+ // Vector<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);
+ }
+}
diff --git a/org_apg/src/org/thialfihar/android/apg/provider/UserIds.java b/org_apg/src/org/thialfihar/android/apg/provider/UserIds.java
deleted file mode 100644
index 2050ccf9c..000000000
--- a/org_apg/src/org/thialfihar/android/apg/provider/UserIds.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2010 Thialfihar <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";
-}