From fa99a70a492c4e8238ea99a73cb63cbec6e40927 Mon Sep 17 00:00:00 2001 From: Thialfihar Date: Wed, 26 May 2010 15:25:14 +0000 Subject: import/export/delete/save keyrings working with new database stuff --- src/org/thialfihar/android/apg/Apg.java | 140 +++++---- src/org/thialfihar/android/apg/BaseActivity.java | 2 + .../thialfihar/android/apg/EditKeyActivity.java | 6 + .../thialfihar/android/apg/KeyListActivity.java | 69 ++-- .../android/apg/SelectPublicKeyListActivity.java | 6 +- .../android/apg/SelectSecretKeyListActivity.java | 5 +- .../thialfihar/android/apg/provider/Database.java | 348 ++++++++++++++++++--- 7 files changed, 439 insertions(+), 137 deletions(-) (limited to 'src') diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index 518d94fbb..1e0a7852f 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -79,6 +79,8 @@ import org.bouncycastle2.openpgp.PGPSignatureList; import org.bouncycastle2.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle2.openpgp.PGPSignatureSubpacketVector; import org.bouncycastle2.openpgp.PGPUtil; +import org.thialfihar.android.apg.provider.Database; +import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.PublicKeys; import org.thialfihar.android.apg.provider.SecretKeys; import org.thialfihar.android.apg.ui.widget.KeyEditor; @@ -90,6 +92,7 @@ import android.app.Activity; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Bundle; import android.os.Environment; @@ -149,6 +152,8 @@ public class Apg { new HashMap(); private static String mEditPassPhrase = null; + private static Database mDatabase = null; + public static class GeneralException extends Exception { static final long serialVersionUID = 0xf812773342L; @@ -165,6 +170,12 @@ public class Apg { } } + public static void initialize(Context context) { + if (mDatabase == null) { + mDatabase = new Database(context); + } + } + public static void setEditPassPhrase(String passPhrase) { mEditPassPhrase = passPhrase; } @@ -325,7 +336,7 @@ public class Apg { String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress) throws Apg.GeneralException, NoSuchProviderException, PGPException, - NoSuchAlgorithmException, SignatureException { + NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException { progress.setProgress(R.string.progress_buildingKey, 0, 100); @@ -510,8 +521,8 @@ public class Apg { PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing(); progress.setProgress(R.string.progress_savingKeyRing, 90, 100); - saveKeyRing(context, secretKeyRing); - saveKeyRing(context, publicKeyRing); + mDatabase.saveKeyRing(secretKeyRing); + mDatabase.saveKeyRing(publicKeyRing); progress.setProgress(R.string.progress_done, 100, 100); } @@ -546,36 +557,6 @@ public class Apg { } } - private static int saveKeyRing(Activity context, PGPSecretKeyRing keyRing) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ContentValues values = new ContentValues(); - - PGPSecretKey masterKey = getMasterKey(keyRing); - if (masterKey == null) { - return Id.return_value.no_master_key; - } - - try { - keyRing.encode(out); - out.close(); - } catch (IOException e) { - return Id.return_value.error; - } - - values.put(SecretKeys.KEY_ID, masterKey.getKeyID()); - values.put(SecretKeys.KEY_DATA, out.toByteArray()); - - Uri uri = Uri.withAppendedPath(SecretKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID()); - Cursor cursor = context.managedQuery(uri, SECRET_KEY_PROJECTION, null, null, null); - if (cursor != null && cursor.getCount() > 0) { - context.getContentResolver().update(uri, values, null, null); - return Id.return_value.updated; - } else { - context.getContentResolver().insert(SecretKeys.CONTENT_URI, values); - return Id.return_value.ok; - } - } - public static Bundle importKeyRings(Activity context, int type, String filename, ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException, PGPException, IOException { @@ -616,12 +597,18 @@ public class Apg { // saveKeyRing is never called int retValue = 2107; - if (type == Id.type.secret_key && obj instanceof PGPSecretKeyRing) { - secretKeyRing = (PGPSecretKeyRing) obj; - retValue = saveKeyRing(context, secretKeyRing); - } else if (type == Id.type.public_key && obj instanceof PGPPublicKeyRing) { - publicKeyRing = (PGPPublicKeyRing) obj; - retValue = saveKeyRing(context, publicKeyRing); + try { + if (type == Id.type.secret_key && obj instanceof PGPSecretKeyRing) { + secretKeyRing = (PGPSecretKeyRing) obj; + retValue = mDatabase.saveKeyRing(secretKeyRing); + } else if (type == Id.type.public_key && obj instanceof PGPPublicKeyRing) { + publicKeyRing = (PGPPublicKeyRing) obj; + retValue = mDatabase.saveKeyRing(publicKeyRing); + } + } catch (IOException e) { + retValue = Id.return_value.error; + } catch (Database.GeneralException e) { + retValue = Id.return_value.error; } if (retValue == Id.return_value.error) { @@ -641,8 +628,6 @@ public class Apg { // nothing to do, we are done } - progress.setProgress(R.string.progress_reloadingKeys, 100, 100); - returnData.putInt("added", newKeys); returnData.putInt("updated", oldKeys); @@ -651,12 +636,13 @@ public class Apg { return returnData; } - public static Bundle exportKeyRings(Activity context, Vector keys, String filename, + public static Bundle exportKeyRings(Activity context, Vector keyRingIds, + String filename, ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException, PGPException, IOException { Bundle returnData = new Bundle(); - if (keys.size() == 1) { + if (keyRingIds.size() == 1) { progress.setProgress(R.string.progress_exportingKey, 0, 100); } else { progress.setProgress(R.string.progress_exportingKeys, 0, 100); @@ -669,9 +655,9 @@ public class Apg { ArmoredOutputStream out = new ArmoredOutputStream(fileOut); int numKeys = 0; - for (int i = 0; i < keys.size(); ++i) { - progress.setProgress(i * 100 / keys.size(), 100); - Object obj = keys.get(i); + for (int i = 0; i < keyRingIds.size(); ++i) { + progress.setProgress(i * 100 / keyRingIds.size(), 100); + Object obj = mDatabase.getKeyRing(keyRingIds.get(i)); PGPPublicKeyRing publicKeyRing; PGPSecretKeyRing secretKeyRing; @@ -988,36 +974,70 @@ public class Apg { return algorithmStr + ", " + keySize + "bit"; } - public static void deleteKey(Activity context, PGPPublicKeyRing keyRing) { - PGPPublicKey masterKey = getMasterKey(keyRing); - Uri uri = Uri.withAppendedPath(PublicKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID()); - context.getContentResolver().delete(uri, null, null); + public static void deleteKey(int keyRingId) { + mDatabase.deleteKeyRing(keyRingId); } - public static void deleteKey(Activity context, PGPSecretKeyRing keyRing) { - PGPSecretKey masterKey = getMasterKey(keyRing); - Uri uri = Uri.withAppendedPath(SecretKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID()); - context.getContentResolver().delete(uri, null, null); + public static Object getKeyRing(int keyRingId) { + return mDatabase.getKeyRing(keyRingId); } public static PGPSecretKeyRing getSecretKeyRing(long keyId) { - // TODO + byte[] data = mDatabase.getKeyRingDataFromKeyId(Id.database.type_secret, keyId); + if (data == null) { + return null; + } + try { + return new PGPSecretKeyRing(data); + } catch (IOException e) { + // no good way to handle this, return null + } catch (PGPException e) { + // no good way to handle this, return null + } return null; } public static PGPPublicKeyRing getPublicKeyRing(long keyId) { - // TODO + byte[] data = mDatabase.getKeyRingDataFromKeyId(Id.database.type_public, keyId); + if (data == null) { + return null; + } + try { + return new PGPPublicKeyRing(data); + } catch (IOException e) { + // no good way to handle this, return null + } return null; } public static PGPSecretKey getSecretKey(long keyId) { - // TODO - return null; + PGPSecretKeyRing keyRing = getSecretKeyRing(keyId); + return keyRing.getSecretKey(keyId); } public static PGPPublicKey getPublicKey(long keyId) { - // TODO - return null; + PGPPublicKeyRing keyRing = getPublicKeyRing(keyId); + try { + return keyRing.getPublicKey(keyId); + } catch (PGPException e) { + return null; + } + } + + public static Vector getKeyRingIds(int type) { + SQLiteDatabase db = mDatabase.getReadableDatabase(); + Vector keyIds = new Vector(); + Cursor c = db.query(KeyRings.TABLE_NAME, + new String[] { KeyRings._ID }, + KeyRings.TYPE + " = ?", new String[] { "" + type }, + null, null, null); + if (c != null && c.moveToFirst()) { + do { + keyIds.add(c.getInt(0)); + } while (c.moveToNext()); + } + db.close(); + return keyIds; } public static void encrypt(Context context, diff --git a/src/org/thialfihar/android/apg/BaseActivity.java b/src/org/thialfihar/android/apg/BaseActivity.java index fe5c0e682..375658db5 100644 --- a/src/org/thialfihar/android/apg/BaseActivity.java +++ b/src/org/thialfihar/android/apg/BaseActivity.java @@ -66,6 +66,8 @@ public class BaseActivity extends Activity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + Apg.initialize(this); + if (mPreferences == null) { mPreferences = getPreferences(MODE_PRIVATE); } diff --git a/src/org/thialfihar/android/apg/EditKeyActivity.java b/src/org/thialfihar/android/apg/EditKeyActivity.java index dfd4f4f46..6c8842fcc 100644 --- a/src/org/thialfihar/android/apg/EditKeyActivity.java +++ b/src/org/thialfihar/android/apg/EditKeyActivity.java @@ -16,6 +16,7 @@ package org.thialfihar.android.apg; +import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SignatureException; @@ -24,6 +25,7 @@ import java.util.Vector; import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKeyRing; +import org.thialfihar.android.apg.provider.Database; import org.thialfihar.android.apg.ui.widget.KeyEditor; import org.thialfihar.android.apg.ui.widget.SectionView; import org.thialfihar.android.apg.utils.IterableIterator; @@ -254,6 +256,10 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener { error = "" + e; } catch (Apg.GeneralException e) { error = "" + e; + } catch (Database.GeneralException e) { + error = "" + e; + } catch (IOException e) { + error = "" + e; } data.putInt("type", Id.message.done); diff --git a/src/org/thialfihar/android/apg/KeyListActivity.java b/src/org/thialfihar/android/apg/KeyListActivity.java index da696398b..023cd0f6c 100644 --- a/src/org/thialfihar/android/apg/KeyListActivity.java +++ b/src/org/thialfihar/android/apg/KeyListActivity.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.util.Vector; import org.bouncycastle2.openpgp.PGPException; +import org.bouncycastle2.openpgp.PGPPublicKeyRing; +import org.bouncycastle2.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.provider.Database; import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.Keys; @@ -122,9 +124,18 @@ public class KeyListActivity extends BaseActivity { switch (id) { case Id.dialog.delete_key: { - final long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); - // TODO: String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); - String userId = "SOME KEY"; + final int keyRingId = ((KeyListAdapter) mList.getExpandableListAdapter()).getKeyRingId(mSelectedItem); + mSelectedItem = -1; + // TODO: better way to do this? + String userId = ""; + Object keyRing = Apg.getKeyRing(keyRingId); + if (keyRing != null) { + if (keyRing instanceof PGPPublicKeyRing) { + userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey((PGPPublicKeyRing) keyRing)); + } else { + userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey((PGPSecretKeyRing) keyRing)); + } + } AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.warning); @@ -135,7 +146,7 @@ public class KeyListActivity extends BaseActivity { builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - deleteKey(keyId); + deleteKey(keyRingId); removeDialog(Id.dialog.delete_key); } }); @@ -184,7 +195,9 @@ public class KeyListActivity extends BaseActivity { final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys); return FileDialog.build(this, title, - getString(R.string.specifyFileToExportTo), + getString(mKeyType == Id.type.public_key ? + R.string.specifyFileToExportTo : + R.string.specifyFileToExportSecretKeysTo), mExportFilename, new FileDialog.OnClickListener() { @Override @@ -239,24 +252,17 @@ public class KeyListActivity extends BaseActivity { if (mTask == Id.task.import_keys) { data = Apg.importKeyRings(this, mKeyType, filename, this); } else { - Vector keys = new Vector(); - // TODO - /* + Vector keyRingIds = new Vector(); if (mSelectedItem == -1) { - for (PGPSecretKeyRing key : Apg.getSecretKeyRings()) { - keys.add(key); - } + keyRingIds = Apg.getKeyRingIds(mKeyType == Id.type.public_key ? + Id.database.type_public : + Id.database.type_secret); } else { - keys.add(Apg.getSecretKeyRings().get(mSelectedItem)); + int keyRingId = ((KeyListAdapter) mList.getExpandableListAdapter()).getKeyRingId(mSelectedItem); + keyRingIds.add(keyRingId); + mSelectedItem = -1; } - if (mSelectedItem == -1) { - for (PGPPublicKeyRing key : Apg.getPublicKeyRings()) { - keys.add(key); - } - } else { - keys.add(Apg.getPublicKeyRings().get(mSelectedItem)); - }*/ - data = Apg.exportKeyRings(this, keys, filename, this); + data = Apg.exportKeyRings(this, keyRingIds, filename, this); } } catch (FileNotFoundException e) { error = getString(R.string.error_fileNotFound); @@ -282,14 +288,13 @@ public class KeyListActivity extends BaseActivity { sendMessage(msg); } - protected void deleteKey(long keyId) { - // TODO - //PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(index); - //Apg.deleteKey(this, keyRing); + protected void deleteKey(int keyRingId) { + Apg.deleteKey(keyRingId); refreshList(); } protected void refreshList() { + ((KeyListAdapter) mList.getExpandableListAdapter()).rebuild(true); ((KeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged(); } @@ -343,7 +348,7 @@ public class KeyListActivity extends BaseActivity { if (exported == 1) { message = getString(R.string.keyExported); } else if (exported > 0) { - message = getString(R.string.keysExported); + message = getString(R.string.keysExported, exported); } else{ message = getString(R.string.noKeysExported); } @@ -417,8 +422,15 @@ public class KeyListActivity extends BaseActivity { new String[] { "" + (mKeyType == Id.type.public_key ? Id.database.type_public : Id.database.type_secret) }, - null, null, null); + null, null, UserIds.TABLE_NAME + "." + UserIds.USER_ID + " ASC"); + rebuild(false); + } + + public void rebuild(boolean requery) { + if (requery) { + mCursor.requery(); + } mChildren = new Vector>(); for (int i = 0; i < mCursor.getCount(); ++i) { mChildren.add(null); @@ -522,6 +534,11 @@ public class KeyListActivity extends BaseActivity { return mCursor.getLong(1); // MASTER_KEY_ID } + public int getKeyRingId(int position) { + mCursor.moveToPosition(position); + return mCursor.getInt(0); // _ID + } + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { mCursor.moveToPosition(groupPosition); diff --git a/src/org/thialfihar/android/apg/SelectPublicKeyListActivity.java b/src/org/thialfihar/android/apg/SelectPublicKeyListActivity.java index fbb0b6fe0..1ddc92b14 100644 --- a/src/org/thialfihar/android/apg/SelectPublicKeyListActivity.java +++ b/src/org/thialfihar/android/apg/SelectPublicKeyListActivity.java @@ -49,9 +49,9 @@ public class SelectPublicKeyListActivity extends BaseActivity { // needed in Android 1.5, where the XML attribute gets ignored mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - Vector keyRings = - (Vector) Apg.getPublicKeyRings().clone(); - Collections.sort(keyRings, new Apg.PublicKeySorter()); + Vector keyRings = new Vector(); + //(Vector) Apg.getPublicKeyRings().clone(); + //Collections.sort(keyRings, new Apg.PublicKeySorter()); mList.setAdapter(new SelectPublicKeyListAdapter(mList, keyRings)); if (selectedKeyIds != null) { diff --git a/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java b/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java index b6811d6e3..53a5bd5a9 100644 --- a/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java +++ b/src/org/thialfihar/android/apg/SelectSecretKeyListActivity.java @@ -54,8 +54,9 @@ public class SelectSecretKeyListActivity extends BaseActivity { // fill things mIntent = getIntent(); - mKeyRings = (Vector) Apg.getSecretKeyRings().clone(); - Collections.sort(mKeyRings, new Apg.SecretKeySorter()); + mKeyRings = new Vector(); + //(Vector) Apg.getSecretKeyRings().clone(); + //Collections.sort(mKeyRings, new Apg.SecretKeySorter()); setContentView(R.layout.select_secret_key); diff --git a/src/org/thialfihar/android/apg/provider/Database.java b/src/org/thialfihar/android/apg/provider/Database.java index 716ff99ab..2481072dd 100644 --- a/src/org/thialfihar/android/apg/provider/Database.java +++ b/src/org/thialfihar/android/apg/provider/Database.java @@ -2,6 +2,7 @@ package org.thialfihar.android.apg.provider; import java.io.IOException; import java.util.HashMap; +import java.util.Vector; import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPPublicKey; @@ -39,6 +40,7 @@ public class Database extends SQLiteOpenHelper { public static HashMap sUserIdsProjection; private SQLiteDatabase mCurrentDb = null; + private int mStatus = 0; static { sKeyRingsProjection = new HashMap(); @@ -196,7 +198,13 @@ public class Database extends SQLiteOpenHelper { mCurrentDb = null; } - public void saveKeyRing(PGPPublicKeyRing keyRing) throws IOException, GeneralException { + public int saveKeyRing(PGPPublicKeyRing keyRing) throws IOException, GeneralException { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + ContentValues values = new ContentValues(); PGPPublicKey masterKey = keyRing.getPublicKey(); long masterKeyId = masterKey.getKeyID(); @@ -206,19 +214,46 @@ public class Database extends SQLiteOpenHelper { values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); long rowId = insertOrUpdateKeyRing(values); + int returnValue = mStatus; if (rowId == -1) { throw new GeneralException("saving public key ring " + masterKeyId + " failed"); } + Vector seenIds = new Vector(); int rank = 0; for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { - saveKey(rowId, key, rank); + seenIds.add(saveKey(rowId, key, rank)); ++rank; } + + String seenIdsStr = ""; + for (Integer id : seenIds) { + if (seenIdsStr.length() > 0) { + seenIdsStr += ","; + } + seenIdsStr += id; + } + mCurrentDb.delete(Keys.TABLE_NAME, + Keys.KEY_RING_ID + " = ? AND " + + Keys._ID + " NOT IN (" + seenIdsStr + ")", + new String[] { "" + rowId }); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return returnValue; } - public void saveKeyRing(PGPSecretKeyRing keyRing) throws IOException, GeneralException { + public int saveKeyRing(PGPSecretKeyRing keyRing) throws IOException, GeneralException { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + ContentValues values = new ContentValues(); PGPSecretKey masterKey = keyRing.getSecretKey(); long masterKeyId = masterKey.getKeyID(); @@ -228,21 +263,47 @@ public class Database extends SQLiteOpenHelper { 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"); } - // TODO: delete every related key not saved now + Vector seenIds = new Vector(); int rank = 0; for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - saveKey(rowId, key, rank); + seenIds.add(saveKey(rowId, key, rank)); ++rank; } + + String seenIdsStr = ""; + for (Integer id : seenIds) { + if (seenIdsStr.length() > 0) { + seenIdsStr += ","; + } + seenIdsStr += id; + } + mCurrentDb.delete(Keys.TABLE_NAME, + Keys.KEY_RING_ID + " = ? AND " + + Keys._ID + " NOT IN (" + seenIdsStr + ")", + new String[] { "" + rowId }); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return returnValue; } - private void saveKey(long keyRingId, PGPPublicKey key, int rank) + private int saveKey(long keyRingId, PGPPublicKey key, int rank) throws IOException, GeneralException { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + ContentValues values = new ContentValues(); values.put(Keys.KEY_ID, key.getKeyID()); @@ -262,15 +323,41 @@ public class Database extends SQLiteOpenHelper { throw new GeneralException("saving public key " + key.getKeyID() + " failed"); } + Vector seenIds = new Vector(); int userIdRank = 0; for (String userId : new IterableIterator(key.getUserIDs())) { - saveUserId(rowId, userId, userIdRank); + seenIds.add(saveUserId(rowId, userId, userIdRank)); ++userIdRank; } + + String seenIdsStr = ""; + for (Integer id : seenIds) { + if (seenIdsStr.length() > 0) { + seenIdsStr += ","; + } + seenIdsStr += id; + } + mCurrentDb.delete(UserIds.TABLE_NAME, + UserIds.KEY_ID + " = ? AND " + + UserIds._ID + " NOT IN (" + seenIdsStr + ")", + new String[] { "" + rowId }); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return (int)rowId; } - private void saveKey(long keyRingId, PGPSecretKey key, int rank) + private int saveKey(long keyRingId, PGPSecretKey key, int rank) throws IOException, GeneralException { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + ContentValues values = new ContentValues(); values.put(Keys.KEY_ID, key.getPublicKey().getKeyID()); @@ -290,14 +377,34 @@ public class Database extends SQLiteOpenHelper { throw new GeneralException("saving secret key " + key.getPublicKey().getKeyID() + " failed"); } + Vector seenIds = new Vector(); int userIdRank = 0; for (String userId : new IterableIterator(key.getUserIDs())) { - saveUserId(rowId, userId, userIdRank); + seenIds.add(saveUserId(rowId, userId, userIdRank)); ++userIdRank; } + + String seenIdsStr = ""; + for (Integer id : seenIds) { + if (seenIdsStr.length() > 0) { + seenIdsStr += ","; + } + seenIdsStr += id; + } + mCurrentDb.delete(UserIds.TABLE_NAME, + UserIds.KEY_ID + " = ? AND " + + UserIds._ID + " NOT IN (" + seenIdsStr + ")", + new String[] { "" + rowId }); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return (int)rowId; } - private void saveUserId(long keyId, String userId, int rank) throws GeneralException { + private int saveUserId(long keyId, String userId, int rank) throws GeneralException { ContentValues values = new ContentValues(); values.put(UserIds.KEY_ID, keyId); @@ -309,17 +416,17 @@ public class Database extends SQLiteOpenHelper { if (rowId == -1) { throw new GeneralException("saving user id " + userId + " failed"); } + + return (int)rowId; } private long insertOrUpdateKeyRing(ContentValues values) { - boolean grabbedNewDatabase = (mCurrentDb == null); - SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - qb.setTables(KeyRings.TABLE_NAME); - qb.setProjectionMap(sKeyRingsProjection); - - Cursor c = qb.query(db, new String[] { KeyRings._ID }, + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + Cursor c = mCurrentDb.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID }, KeyRings.MASTER_KEY_ID + " = ? AND " + KeyRings.TYPE + " = ?", new String[] { values.getAsString(KeyRings.MASTER_KEY_ID), @@ -329,30 +436,31 @@ public class Database extends SQLiteOpenHelper { long rowId = -1; if (c != null && c.moveToFirst()) { rowId = c.getLong(0); - db.update(KeyRings.TABLE_NAME, values, - KeyRings._ID + " = ?", new String[] { "" + rowId }); + mCurrentDb.update(KeyRings.TABLE_NAME, values, + KeyRings._ID + " = ?", new String[] { "" + rowId }); + mStatus = Id.return_value.updated; } else { - rowId = db.insert(KeyRings.TABLE_NAME, KeyRings.WHO_ID, values); + rowId = mCurrentDb.insert(KeyRings.TABLE_NAME, KeyRings.WHO_ID, values); + mStatus = Id.return_value.ok; } c.close(); if (grabbedNewDatabase) { - db.close(); + mCurrentDb.close(); + mCurrentDb = null; } return rowId; } private long insertOrUpdateKey(ContentValues values) { - boolean grabbedNewDatabase = (mCurrentDb == null); - SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - qb.setTables(Keys.TABLE_NAME); - qb.setProjectionMap(sKeysProjection); - - Cursor c = qb.query(db, new String[] { Keys._ID }, + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + Cursor c = mCurrentDb.query(Keys.TABLE_NAME, new String[] { Keys._ID }, Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?", new String[] { values.getAsString(Keys.KEY_ID), @@ -362,30 +470,29 @@ public class Database extends SQLiteOpenHelper { long rowId = -1; if (c != null && c.moveToFirst()) { rowId = c.getLong(0); - db.update(Keys.TABLE_NAME, values, - Keys._ID + " = ?", new String[] { "" + rowId }); + mCurrentDb.update(Keys.TABLE_NAME, values, + Keys._ID + " = ?", new String[] { "" + rowId }); } else { - rowId = db.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values); + rowId = mCurrentDb.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values); } c.close(); if (grabbedNewDatabase) { - db.close(); + mCurrentDb.close(); + mCurrentDb = null; } return rowId; } private long insertOrUpdateUserId(ContentValues values) { - boolean grabbedNewDatabase = (mCurrentDb == null); - SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); - SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); - - qb.setTables(UserIds.TABLE_NAME); - qb.setProjectionMap(sUserIdsProjection); - - Cursor c = qb.query(db, new String[] { UserIds._ID }, + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + Cursor c = mCurrentDb.query(UserIds.TABLE_NAME, new String[] { UserIds._ID }, UserIds.KEY_ID + " = ? AND " + UserIds.USER_ID + " = ?", new String[] { values.getAsString(UserIds.KEY_ID), @@ -395,18 +502,167 @@ public class Database extends SQLiteOpenHelper { long rowId = -1; if (c != null && c.moveToFirst()) { rowId = c.getLong(0); - db.update(UserIds.TABLE_NAME, values, - UserIds._ID + " = ?", new String[] { "" + rowId }); + mCurrentDb.update(UserIds.TABLE_NAME, values, + UserIds._ID + " = ?", new String[] { "" + rowId }); } else { - rowId = db.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values); + rowId = mCurrentDb.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values); } c.close(); if (grabbedNewDatabase) { - db.close(); + mCurrentDb.close(); + mCurrentDb = null; } return rowId; } + + public Object getKeyRing(int keyRingId) { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + Cursor c = mCurrentDb.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 + } + } + } + + c.close(); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return keyRing; + } + + public byte[] getKeyRingDataFromKeyId(int type, long keyId) { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getReadableDatabase(); + grabbedNewDatabase = true; + } + Cursor c = mCurrentDb.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); + } + + c.close(); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return data; + } + + public byte[] getKeyDataFromKeyId(int type, long keyId) { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getReadableDatabase(); + grabbedNewDatabase = true; + } + Cursor c = mCurrentDb.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); + } + + c.close(); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + + return data; + } + + public void deleteKeyRing(int keyRingId) { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + mCurrentDb.delete(KeyRings.TABLE_NAME, + KeyRings._ID + " = ?", new String[] { "" + keyRingId }); + + Cursor c = mCurrentDb.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 (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + } + + public void deleteKey(int keyId) { + boolean grabbedNewDatabase = false; + if (mCurrentDb == null) { + mCurrentDb = getWritableDatabase(); + grabbedNewDatabase = true; + } + mCurrentDb.delete(Keys.TABLE_NAME, + Keys._ID + " = ?", new String[] { "" + keyId }); + + mCurrentDb.delete(UserIds.TABLE_NAME, + UserIds.KEY_ID + " = ?", new String[] { "" + keyId }); + + if (grabbedNewDatabase) { + mCurrentDb.close(); + mCurrentDb = null; + } + } } -- cgit v1.2.3