import/export/delete/save keyrings working with new database stuff

This commit is contained in:
Thialfihar 2010-05-26 15:25:14 +00:00
parent 6f28f5ee4e
commit fa99a70a49
7 changed files with 439 additions and 137 deletions

View File

@ -79,6 +79,8 @@ import org.bouncycastle2.openpgp.PGPSignatureList;
import org.bouncycastle2.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle2.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle2.openpgp.PGPSignatureSubpacketVector; import org.bouncycastle2.openpgp.PGPSignatureSubpacketVector;
import org.bouncycastle2.openpgp.PGPUtil; 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.PublicKeys;
import org.thialfihar.android.apg.provider.SecretKeys; import org.thialfihar.android.apg.provider.SecretKeys;
import org.thialfihar.android.apg.ui.widget.KeyEditor; import org.thialfihar.android.apg.ui.widget.KeyEditor;
@ -90,6 +92,7 @@ import android.app.Activity;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
@ -149,6 +152,8 @@ public class Apg {
new HashMap<Long, CachedPassPhrase>(); new HashMap<Long, CachedPassPhrase>();
private static String mEditPassPhrase = null; private static String mEditPassPhrase = null;
private static Database mDatabase = null;
public static class GeneralException extends Exception { public static class GeneralException extends Exception {
static final long serialVersionUID = 0xf812773342L; 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) { public static void setEditPassPhrase(String passPhrase) {
mEditPassPhrase = passPhrase; mEditPassPhrase = passPhrase;
} }
@ -325,7 +336,7 @@ public class Apg {
String oldPassPhrase, String newPassPhrase, String oldPassPhrase, String newPassPhrase,
ProgressDialogUpdater progress) ProgressDialogUpdater progress)
throws Apg.GeneralException, NoSuchProviderException, PGPException, throws Apg.GeneralException, NoSuchProviderException, PGPException,
NoSuchAlgorithmException, SignatureException { NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException {
progress.setProgress(R.string.progress_buildingKey, 0, 100); progress.setProgress(R.string.progress_buildingKey, 0, 100);
@ -510,8 +521,8 @@ public class Apg {
PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing(); PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
progress.setProgress(R.string.progress_savingKeyRing, 90, 100); progress.setProgress(R.string.progress_savingKeyRing, 90, 100);
saveKeyRing(context, secretKeyRing); mDatabase.saveKeyRing(secretKeyRing);
saveKeyRing(context, publicKeyRing); mDatabase.saveKeyRing(publicKeyRing);
progress.setProgress(R.string.progress_done, 100, 100); 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, public static Bundle importKeyRings(Activity context, int type, String filename,
ProgressDialogUpdater progress) ProgressDialogUpdater progress)
throws GeneralException, FileNotFoundException, PGPException, IOException { throws GeneralException, FileNotFoundException, PGPException, IOException {
@ -616,12 +597,18 @@ public class Apg {
// saveKeyRing is never called // saveKeyRing is never called
int retValue = 2107; int retValue = 2107;
if (type == Id.type.secret_key && obj instanceof PGPSecretKeyRing) { try {
secretKeyRing = (PGPSecretKeyRing) obj; if (type == Id.type.secret_key && obj instanceof PGPSecretKeyRing) {
retValue = saveKeyRing(context, secretKeyRing); secretKeyRing = (PGPSecretKeyRing) obj;
} else if (type == Id.type.public_key && obj instanceof PGPPublicKeyRing) { retValue = mDatabase.saveKeyRing(secretKeyRing);
publicKeyRing = (PGPPublicKeyRing) obj; } else if (type == Id.type.public_key && obj instanceof PGPPublicKeyRing) {
retValue = saveKeyRing(context, publicKeyRing); 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) { if (retValue == Id.return_value.error) {
@ -641,8 +628,6 @@ public class Apg {
// nothing to do, we are done // nothing to do, we are done
} }
progress.setProgress(R.string.progress_reloadingKeys, 100, 100);
returnData.putInt("added", newKeys); returnData.putInt("added", newKeys);
returnData.putInt("updated", oldKeys); returnData.putInt("updated", oldKeys);
@ -651,12 +636,13 @@ public class Apg {
return returnData; return returnData;
} }
public static Bundle exportKeyRings(Activity context, Vector<Object> keys, String filename, public static Bundle exportKeyRings(Activity context, Vector<Integer> keyRingIds,
String filename,
ProgressDialogUpdater progress) ProgressDialogUpdater progress)
throws GeneralException, FileNotFoundException, PGPException, IOException { throws GeneralException, FileNotFoundException, PGPException, IOException {
Bundle returnData = new Bundle(); Bundle returnData = new Bundle();
if (keys.size() == 1) { if (keyRingIds.size() == 1) {
progress.setProgress(R.string.progress_exportingKey, 0, 100); progress.setProgress(R.string.progress_exportingKey, 0, 100);
} else { } else {
progress.setProgress(R.string.progress_exportingKeys, 0, 100); progress.setProgress(R.string.progress_exportingKeys, 0, 100);
@ -669,9 +655,9 @@ public class Apg {
ArmoredOutputStream out = new ArmoredOutputStream(fileOut); ArmoredOutputStream out = new ArmoredOutputStream(fileOut);
int numKeys = 0; int numKeys = 0;
for (int i = 0; i < keys.size(); ++i) { for (int i = 0; i < keyRingIds.size(); ++i) {
progress.setProgress(i * 100 / keys.size(), 100); progress.setProgress(i * 100 / keyRingIds.size(), 100);
Object obj = keys.get(i); Object obj = mDatabase.getKeyRing(keyRingIds.get(i));
PGPPublicKeyRing publicKeyRing; PGPPublicKeyRing publicKeyRing;
PGPSecretKeyRing secretKeyRing; PGPSecretKeyRing secretKeyRing;
@ -988,36 +974,70 @@ public class Apg {
return algorithmStr + ", " + keySize + "bit"; return algorithmStr + ", " + keySize + "bit";
} }
public static void deleteKey(Activity context, PGPPublicKeyRing keyRing) { public static void deleteKey(int keyRingId) {
PGPPublicKey masterKey = getMasterKey(keyRing); mDatabase.deleteKeyRing(keyRingId);
Uri uri = Uri.withAppendedPath(PublicKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID());
context.getContentResolver().delete(uri, null, null);
} }
public static void deleteKey(Activity context, PGPSecretKeyRing keyRing) { public static Object getKeyRing(int keyRingId) {
PGPSecretKey masterKey = getMasterKey(keyRing); return mDatabase.getKeyRing(keyRingId);
Uri uri = Uri.withAppendedPath(SecretKeys.CONTENT_URI_BY_KEY_ID, "" + masterKey.getKeyID());
context.getContentResolver().delete(uri, null, null);
} }
public static PGPSecretKeyRing getSecretKeyRing(long keyId) { 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; return null;
} }
public static PGPPublicKeyRing getPublicKeyRing(long keyId) { 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; return null;
} }
public static PGPSecretKey getSecretKey(long keyId) { public static PGPSecretKey getSecretKey(long keyId) {
// TODO PGPSecretKeyRing keyRing = getSecretKeyRing(keyId);
return null; return keyRing.getSecretKey(keyId);
} }
public static PGPPublicKey getPublicKey(long keyId) { public static PGPPublicKey getPublicKey(long keyId) {
// TODO PGPPublicKeyRing keyRing = getPublicKeyRing(keyId);
return null; try {
return keyRing.getPublicKey(keyId);
} catch (PGPException e) {
return null;
}
}
public static Vector<Integer> getKeyRingIds(int type) {
SQLiteDatabase db = mDatabase.getReadableDatabase();
Vector<Integer> keyIds = new Vector<Integer>();
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, public static void encrypt(Context context,

View File

@ -66,6 +66,8 @@ public class BaseActivity extends Activity
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Apg.initialize(this);
if (mPreferences == null) { if (mPreferences == null) {
mPreferences = getPreferences(MODE_PRIVATE); mPreferences = getPreferences(MODE_PRIVATE);
} }

View File

@ -16,6 +16,7 @@
package org.thialfihar.android.apg; package org.thialfihar.android.apg;
import java.io.IOException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.security.SignatureException; import java.security.SignatureException;
@ -24,6 +25,7 @@ import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPSecretKey; import org.bouncycastle2.openpgp.PGPSecretKey;
import org.bouncycastle2.openpgp.PGPSecretKeyRing; 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.KeyEditor;
import org.thialfihar.android.apg.ui.widget.SectionView; import org.thialfihar.android.apg.ui.widget.SectionView;
import org.thialfihar.android.apg.utils.IterableIterator; import org.thialfihar.android.apg.utils.IterableIterator;
@ -254,6 +256,10 @@ public class EditKeyActivity extends BaseActivity implements OnClickListener {
error = "" + e; error = "" + e;
} catch (Apg.GeneralException e) { } catch (Apg.GeneralException e) {
error = "" + e; error = "" + e;
} catch (Database.GeneralException e) {
error = "" + e;
} catch (IOException e) {
error = "" + e;
} }
data.putInt("type", Id.message.done); data.putInt("type", Id.message.done);

View File

@ -21,6 +21,8 @@ import java.io.IOException;
import java.util.Vector; import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException; 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.Database;
import org.thialfihar.android.apg.provider.KeyRings; import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys; import org.thialfihar.android.apg.provider.Keys;
@ -122,9 +124,18 @@ public class KeyListActivity extends BaseActivity {
switch (id) { switch (id) {
case Id.dialog.delete_key: { case Id.dialog.delete_key: {
final long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); final int keyRingId = ((KeyListAdapter) mList.getExpandableListAdapter()).getKeyRingId(mSelectedItem);
// TODO: String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); mSelectedItem = -1;
String userId = "SOME KEY"; // TODO: better way to do this?
String userId = "<unknown>";
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); AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.warning); builder.setTitle(R.string.warning);
@ -135,7 +146,7 @@ public class KeyListActivity extends BaseActivity {
builder.setPositiveButton(R.string.btn_delete, builder.setPositiveButton(R.string.btn_delete,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) { public void onClick(DialogInterface dialog, int id) {
deleteKey(keyId); deleteKey(keyRingId);
removeDialog(Id.dialog.delete_key); 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); final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys);
return FileDialog.build(this, title, return FileDialog.build(this, title,
getString(R.string.specifyFileToExportTo), getString(mKeyType == Id.type.public_key ?
R.string.specifyFileToExportTo :
R.string.specifyFileToExportSecretKeysTo),
mExportFilename, mExportFilename,
new FileDialog.OnClickListener() { new FileDialog.OnClickListener() {
@Override @Override
@ -239,24 +252,17 @@ public class KeyListActivity extends BaseActivity {
if (mTask == Id.task.import_keys) { if (mTask == Id.task.import_keys) {
data = Apg.importKeyRings(this, mKeyType, filename, this); data = Apg.importKeyRings(this, mKeyType, filename, this);
} else { } else {
Vector<Object> keys = new Vector<Object>(); Vector<Integer> keyRingIds = new Vector<Integer>();
// TODO
/*
if (mSelectedItem == -1) { if (mSelectedItem == -1) {
for (PGPSecretKeyRing key : Apg.getSecretKeyRings()) { keyRingIds = Apg.getKeyRingIds(mKeyType == Id.type.public_key ?
keys.add(key); Id.database.type_public :
} Id.database.type_secret);
} else { } else {
keys.add(Apg.getSecretKeyRings().get(mSelectedItem)); int keyRingId = ((KeyListAdapter) mList.getExpandableListAdapter()).getKeyRingId(mSelectedItem);
keyRingIds.add(keyRingId);
mSelectedItem = -1;
} }
if (mSelectedItem == -1) { data = Apg.exportKeyRings(this, keyRingIds, filename, this);
for (PGPPublicKeyRing key : Apg.getPublicKeyRings()) {
keys.add(key);
}
} else {
keys.add(Apg.getPublicKeyRings().get(mSelectedItem));
}*/
data = Apg.exportKeyRings(this, keys, filename, this);
} }
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
error = getString(R.string.error_fileNotFound); error = getString(R.string.error_fileNotFound);
@ -282,14 +288,13 @@ public class KeyListActivity extends BaseActivity {
sendMessage(msg); sendMessage(msg);
} }
protected void deleteKey(long keyId) { protected void deleteKey(int keyRingId) {
// TODO Apg.deleteKey(keyRingId);
//PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(index);
//Apg.deleteKey(this, keyRing);
refreshList(); refreshList();
} }
protected void refreshList() { protected void refreshList() {
((KeyListAdapter) mList.getExpandableListAdapter()).rebuild(true);
((KeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged(); ((KeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged();
} }
@ -343,7 +348,7 @@ public class KeyListActivity extends BaseActivity {
if (exported == 1) { if (exported == 1) {
message = getString(R.string.keyExported); message = getString(R.string.keyExported);
} else if (exported > 0) { } else if (exported > 0) {
message = getString(R.string.keysExported); message = getString(R.string.keysExported, exported);
} else{ } else{
message = getString(R.string.noKeysExported); message = getString(R.string.noKeysExported);
} }
@ -417,8 +422,15 @@ public class KeyListActivity extends BaseActivity {
new String[] { "" + (mKeyType == Id.type.public_key ? new String[] { "" + (mKeyType == Id.type.public_key ?
Id.database.type_public : Id.database.type_public :
Id.database.type_secret) }, 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<Vector<KeyChild>>(); mChildren = new Vector<Vector<KeyChild>>();
for (int i = 0; i < mCursor.getCount(); ++i) { for (int i = 0; i < mCursor.getCount(); ++i) {
mChildren.add(null); mChildren.add(null);
@ -522,6 +534,11 @@ public class KeyListActivity extends BaseActivity {
return mCursor.getLong(1); // MASTER_KEY_ID 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, public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
ViewGroup parent) { ViewGroup parent) {
mCursor.moveToPosition(groupPosition); mCursor.moveToPosition(groupPosition);

View File

@ -49,9 +49,9 @@ public class SelectPublicKeyListActivity extends BaseActivity {
// needed in Android 1.5, where the XML attribute gets ignored // needed in Android 1.5, where the XML attribute gets ignored
mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Vector<PGPPublicKeyRing> keyRings = Vector<PGPPublicKeyRing> keyRings = new Vector<PGPPublicKeyRing>();
(Vector<PGPPublicKeyRing>) Apg.getPublicKeyRings().clone(); //(Vector<PGPPublicKeyRing>) Apg.getPublicKeyRings().clone();
Collections.sort(keyRings, new Apg.PublicKeySorter()); //Collections.sort(keyRings, new Apg.PublicKeySorter());
mList.setAdapter(new SelectPublicKeyListAdapter(mList, keyRings)); mList.setAdapter(new SelectPublicKeyListAdapter(mList, keyRings));
if (selectedKeyIds != null) { if (selectedKeyIds != null) {

View File

@ -54,8 +54,9 @@ public class SelectSecretKeyListActivity extends BaseActivity {
// fill things // fill things
mIntent = getIntent(); mIntent = getIntent();
mKeyRings = (Vector<PGPSecretKeyRing>) Apg.getSecretKeyRings().clone(); mKeyRings = new Vector<PGPSecretKeyRing>();
Collections.sort(mKeyRings, new Apg.SecretKeySorter()); //(Vector<PGPSecretKeyRing>) Apg.getSecretKeyRings().clone();
//Collections.sort(mKeyRings, new Apg.SecretKeySorter());
setContentView(R.layout.select_secret_key); setContentView(R.layout.select_secret_key);

View File

@ -2,6 +2,7 @@ package org.thialfihar.android.apg.provider;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Vector;
import org.bouncycastle2.openpgp.PGPException; import org.bouncycastle2.openpgp.PGPException;
import org.bouncycastle2.openpgp.PGPPublicKey; import org.bouncycastle2.openpgp.PGPPublicKey;
@ -39,6 +40,7 @@ public class Database extends SQLiteOpenHelper {
public static HashMap<String, String> sUserIdsProjection; public static HashMap<String, String> sUserIdsProjection;
private SQLiteDatabase mCurrentDb = null; private SQLiteDatabase mCurrentDb = null;
private int mStatus = 0;
static { static {
sKeyRingsProjection = new HashMap<String, String>(); sKeyRingsProjection = new HashMap<String, String>();
@ -196,7 +198,13 @@ public class Database extends SQLiteOpenHelper {
mCurrentDb = null; 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(); ContentValues values = new ContentValues();
PGPPublicKey masterKey = keyRing.getPublicKey(); PGPPublicKey masterKey = keyRing.getPublicKey();
long masterKeyId = masterKey.getKeyID(); long masterKeyId = masterKey.getKeyID();
@ -206,19 +214,46 @@ public class Database extends SQLiteOpenHelper {
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
long rowId = insertOrUpdateKeyRing(values); long rowId = insertOrUpdateKeyRing(values);
int returnValue = mStatus;
if (rowId == -1) { if (rowId == -1) {
throw new GeneralException("saving public key ring " + masterKeyId + " failed"); throw new GeneralException("saving public key ring " + masterKeyId + " failed");
} }
Vector<Integer> seenIds = new Vector<Integer>();
int rank = 0; int rank = 0;
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) { for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
saveKey(rowId, key, rank); seenIds.add(saveKey(rowId, key, rank));
++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(); ContentValues values = new ContentValues();
PGPSecretKey masterKey = keyRing.getSecretKey(); PGPSecretKey masterKey = keyRing.getSecretKey();
long masterKeyId = masterKey.getKeyID(); long masterKeyId = masterKey.getKeyID();
@ -228,21 +263,47 @@ public class Database extends SQLiteOpenHelper {
values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded()); values.put(KeyRings.KEY_RING_DATA, keyRing.getEncoded());
long rowId = insertOrUpdateKeyRing(values); long rowId = insertOrUpdateKeyRing(values);
int returnValue = mStatus;
if (rowId == -1) { if (rowId == -1) {
throw new GeneralException("saving secret key ring " + masterKeyId + " failed"); throw new GeneralException("saving secret key ring " + masterKeyId + " failed");
} }
// TODO: delete every related key not saved now Vector<Integer> seenIds = new Vector<Integer>();
int rank = 0; int rank = 0;
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) { for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
saveKey(rowId, key, rank); seenIds.add(saveKey(rowId, key, rank));
++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 { throws IOException, GeneralException {
boolean grabbedNewDatabase = false;
if (mCurrentDb == null) {
mCurrentDb = getWritableDatabase();
grabbedNewDatabase = true;
}
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Keys.KEY_ID, key.getKeyID()); 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"); throw new GeneralException("saving public key " + key.getKeyID() + " failed");
} }
Vector<Integer> seenIds = new Vector<Integer>();
int userIdRank = 0; int userIdRank = 0;
for (String userId : new IterableIterator<String>(key.getUserIDs())) { for (String userId : new IterableIterator<String>(key.getUserIDs())) {
saveUserId(rowId, userId, userIdRank); seenIds.add(saveUserId(rowId, userId, userIdRank));
++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 { throws IOException, GeneralException {
boolean grabbedNewDatabase = false;
if (mCurrentDb == null) {
mCurrentDb = getWritableDatabase();
grabbedNewDatabase = true;
}
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Keys.KEY_ID, key.getPublicKey().getKeyID()); 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"); throw new GeneralException("saving secret key " + key.getPublicKey().getKeyID() + " failed");
} }
Vector<Integer> seenIds = new Vector<Integer>();
int userIdRank = 0; int userIdRank = 0;
for (String userId : new IterableIterator<String>(key.getUserIDs())) { for (String userId : new IterableIterator<String>(key.getUserIDs())) {
saveUserId(rowId, userId, userIdRank); seenIds.add(saveUserId(rowId, userId, userIdRank));
++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(); ContentValues values = new ContentValues();
values.put(UserIds.KEY_ID, keyId); values.put(UserIds.KEY_ID, keyId);
@ -309,17 +416,17 @@ public class Database extends SQLiteOpenHelper {
if (rowId == -1) { if (rowId == -1) {
throw new GeneralException("saving user id " + userId + " failed"); throw new GeneralException("saving user id " + userId + " failed");
} }
return (int)rowId;
} }
private long insertOrUpdateKeyRing(ContentValues values) { private long insertOrUpdateKeyRing(ContentValues values) {
boolean grabbedNewDatabase = (mCurrentDb == null); boolean grabbedNewDatabase = false;
SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); if (mCurrentDb == null) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); mCurrentDb = getWritableDatabase();
grabbedNewDatabase = true;
qb.setTables(KeyRings.TABLE_NAME); }
qb.setProjectionMap(sKeyRingsProjection); Cursor c = mCurrentDb.query(KeyRings.TABLE_NAME, new String[] { KeyRings._ID },
Cursor c = qb.query(db, new String[] { KeyRings._ID },
KeyRings.MASTER_KEY_ID + " = ? AND " + KeyRings.TYPE + " = ?", KeyRings.MASTER_KEY_ID + " = ? AND " + KeyRings.TYPE + " = ?",
new String[] { new String[] {
values.getAsString(KeyRings.MASTER_KEY_ID), values.getAsString(KeyRings.MASTER_KEY_ID),
@ -329,30 +436,31 @@ public class Database extends SQLiteOpenHelper {
long rowId = -1; long rowId = -1;
if (c != null && c.moveToFirst()) { if (c != null && c.moveToFirst()) {
rowId = c.getLong(0); rowId = c.getLong(0);
db.update(KeyRings.TABLE_NAME, values, mCurrentDb.update(KeyRings.TABLE_NAME, values,
KeyRings._ID + " = ?", new String[] { "" + rowId }); KeyRings._ID + " = ?", new String[] { "" + rowId });
mStatus = Id.return_value.updated;
} else { } 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(); c.close();
if (grabbedNewDatabase) { if (grabbedNewDatabase) {
db.close(); mCurrentDb.close();
mCurrentDb = null;
} }
return rowId; return rowId;
} }
private long insertOrUpdateKey(ContentValues values) { private long insertOrUpdateKey(ContentValues values) {
boolean grabbedNewDatabase = (mCurrentDb == null); boolean grabbedNewDatabase = false;
SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); if (mCurrentDb == null) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); mCurrentDb = getWritableDatabase();
grabbedNewDatabase = true;
qb.setTables(Keys.TABLE_NAME); }
qb.setProjectionMap(sKeysProjection); Cursor c = mCurrentDb.query(Keys.TABLE_NAME, new String[] { Keys._ID },
Cursor c = qb.query(db, new String[] { Keys._ID },
Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?", Keys.KEY_ID + " = ? AND " + Keys.TYPE + " = ?",
new String[] { new String[] {
values.getAsString(Keys.KEY_ID), values.getAsString(Keys.KEY_ID),
@ -362,30 +470,29 @@ public class Database extends SQLiteOpenHelper {
long rowId = -1; long rowId = -1;
if (c != null && c.moveToFirst()) { if (c != null && c.moveToFirst()) {
rowId = c.getLong(0); rowId = c.getLong(0);
db.update(Keys.TABLE_NAME, values, mCurrentDb.update(Keys.TABLE_NAME, values,
Keys._ID + " = ?", new String[] { "" + rowId }); Keys._ID + " = ?", new String[] { "" + rowId });
} else { } else {
rowId = db.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values); rowId = mCurrentDb.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values);
} }
c.close(); c.close();
if (grabbedNewDatabase) { if (grabbedNewDatabase) {
db.close(); mCurrentDb.close();
mCurrentDb = null;
} }
return rowId; return rowId;
} }
private long insertOrUpdateUserId(ContentValues values) { private long insertOrUpdateUserId(ContentValues values) {
boolean grabbedNewDatabase = (mCurrentDb == null); boolean grabbedNewDatabase = false;
SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); if (mCurrentDb == null) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); mCurrentDb = getWritableDatabase();
grabbedNewDatabase = true;
qb.setTables(UserIds.TABLE_NAME); }
qb.setProjectionMap(sUserIdsProjection); Cursor c = mCurrentDb.query(UserIds.TABLE_NAME, new String[] { UserIds._ID },
Cursor c = qb.query(db, new String[] { UserIds._ID },
UserIds.KEY_ID + " = ? AND " + UserIds.USER_ID + " = ?", UserIds.KEY_ID + " = ? AND " + UserIds.USER_ID + " = ?",
new String[] { new String[] {
values.getAsString(UserIds.KEY_ID), values.getAsString(UserIds.KEY_ID),
@ -395,18 +502,167 @@ public class Database extends SQLiteOpenHelper {
long rowId = -1; long rowId = -1;
if (c != null && c.moveToFirst()) { if (c != null && c.moveToFirst()) {
rowId = c.getLong(0); rowId = c.getLong(0);
db.update(UserIds.TABLE_NAME, values, mCurrentDb.update(UserIds.TABLE_NAME, values,
UserIds._ID + " = ?", new String[] { "" + rowId }); UserIds._ID + " = ?", new String[] { "" + rowId });
} else { } else {
rowId = db.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values); rowId = mCurrentDb.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values);
} }
c.close(); c.close();
if (grabbedNewDatabase) { if (grabbedNewDatabase) {
db.close(); mCurrentDb.close();
mCurrentDb = null;
} }
return rowId; 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;
}
}
} }