From 6f28f5ee4e3200fbc36335f5670fe1084471afef Mon Sep 17 00:00:00 2001 From: Thialfihar Date: Wed, 26 May 2010 00:33:26 +0000 Subject: [PATCH] key lists somewhat wrapped into one, using the new database stuff, Apg cleaned up a bit, preparing to use the database there as well --- src/org/thialfihar/android/apg/Apg.java | 293 +------- .../apg/AskForSecretKeyPassPhrase.java | 46 +- .../thialfihar/android/apg/BaseActivity.java | 11 +- .../android/apg/EncryptActivity.java | 4 +- src/org/thialfihar/android/apg/Id.java | 10 +- .../android/apg/KeyListActivity.java | 633 ++++++++++++++++++ .../android/apg/PublicKeyListActivity.java | 535 +-------------- .../android/apg/SecretKeyListActivity.java | 495 +------------- .../android/apg/provider/DataProvider.java | 2 - .../android/apg/provider/Database.java | 33 +- .../android/apg/provider/KeyRings.java | 10 + .../thialfihar/android/apg/provider/Keys.java | 9 + .../android/apg/provider/UserIds.java | 11 + 13 files changed, 773 insertions(+), 1319 deletions(-) create mode 100644 src/org/thialfihar/android/apg/KeyListActivity.java diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index 1919191e7..518d94fbb 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -36,8 +36,6 @@ import java.security.SecureRandom; import java.security.Security; import java.security.SignatureException; import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; @@ -126,9 +124,6 @@ public class Apg { CompressionAlgorithmTags.BZIP2, CompressionAlgorithmTags.ZIP }; - protected static Vector mPublicKeyRings = new Vector(); - protected static Vector mSecretKeyRings = new Vector(); - public static Pattern PGP_MESSAGE = Pattern.compile(".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); @@ -137,13 +132,6 @@ public class Apg { Pattern.compile(".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*", Pattern.DOTALL); - protected static boolean mInitialized = false; - - protected static HashMap mSecretKeyIdToIdMap; - protected static HashMap mSecretKeyIdToKeyRingMap; - protected static HashMap mPublicKeyIdToIdMap; - protected static HashMap mPublicKeyIdToKeyRingMap; - public static final String PUBLIC_KEY_PROJECTION[] = new String[] { PublicKeys._ID, @@ -177,104 +165,6 @@ public class Apg { } } - static { - mPublicKeyRings = new Vector(); - mSecretKeyRings = new Vector(); - mSecretKeyIdToIdMap = new HashMap(); - mSecretKeyIdToKeyRingMap = new HashMap(); - mPublicKeyIdToIdMap = new HashMap(); - mPublicKeyIdToKeyRingMap = new HashMap(); - } - - public static void initialize(Activity context) { - if (mInitialized) { - return; - } - - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - File dir = new File(Constants.path.app_dir); - if (!dir.exists() && !dir.mkdirs()) { - // ignore this for now, it's not crucial - // that the directory doesn't exist at this point - } - } - - loadKeyRings(context, Id.type.public_key); - loadKeyRings(context, Id.type.secret_key); - - mInitialized = true; - } - - public static class PublicKeySorter implements Comparator { - @Override - public int compare(PGPPublicKeyRing object1, PGPPublicKeyRing object2) { - PGPPublicKey key1 = getMasterKey(object1); - PGPPublicKey key2 = getMasterKey(object2); - if (key1 == null && key2 == null) { - return 0; - } - - if (key1 == null) { - return -1; - } - - if (key2 == null) { - return 1; - } - - String uid1 = getMainUserId(key1); - String uid2 = getMainUserId(key2); - if (uid1 == null && uid2 == null) { - return 0; - } - - if (uid1 == null) { - return -1; - } - - if (uid2 == null) { - return 1; - } - - return uid1.compareTo(uid2); - } - } - - public static class SecretKeySorter implements Comparator { - @Override - public int compare(PGPSecretKeyRing object1, PGPSecretKeyRing object2) { - PGPSecretKey key1 = getMasterKey(object1); - PGPSecretKey key2 = getMasterKey(object2); - if (key1 == null && key2 == null) { - return 0; - } - - if (key1 == null) { - return -1; - } - - if (key2 == null) { - return 1; - } - - String uid1 = getMainUserId(key1); - String uid2 = getMainUserId(key2); - if (uid1 == null && uid2 == null) { - return 0; - } - - if (uid1 == null) { - return -1; - } - - if (uid2 == null) { - return 1; - } - - return uid1.compareTo(uid2); - } - } - public static void setEditPassPhrase(String passPhrase) { mEditPassPhrase = passPhrase; } @@ -290,7 +180,7 @@ public class Apg { public static String getCachedPassPhrase(long keyId) { long realId = keyId; if (realId != Id.key.symmetric) { - PGPSecretKeyRing keyRing = findSecretKeyRing(keyId); + PGPSecretKeyRing keyRing = getSecretKeyRing(keyId); if (keyRing == null) { return null; } @@ -623,8 +513,6 @@ public class Apg { saveKeyRing(context, secretKeyRing); saveKeyRing(context, publicKeyRing); - loadKeyRings(context, Id.type.public_key); - loadKeyRings(context, Id.type.secret_key); progress.setProgress(R.string.progress_done, 100, 100); } @@ -754,7 +642,6 @@ public class Apg { } progress.setProgress(R.string.progress_reloadingKeys, 100, 100); - loadKeyRings(context, type); returnData.putInt("added", newKeys); returnData.putInt("updated", oldKeys); @@ -808,61 +695,6 @@ public class Apg { return returnData; } - private static void loadKeyRings(Activity context, int type) { - Cursor cursor; - if (type == Id.type.secret_key) { - mSecretKeyRings.clear(); - mSecretKeyIdToIdMap.clear(); - mSecretKeyIdToKeyRingMap.clear(); - cursor = context.managedQuery(SecretKeys.CONTENT_URI, SECRET_KEY_PROJECTION, - null, null, null); - } else { - mPublicKeyRings.clear(); - mPublicKeyIdToIdMap.clear(); - mPublicKeyIdToKeyRingMap.clear(); - cursor = context.managedQuery(PublicKeys.CONTENT_URI, PUBLIC_KEY_PROJECTION, - null, null, null); - } - - for (int i = 0; i < cursor.getCount(); ++i) { - cursor.moveToPosition(i); - String sharedIdColumn = PublicKeys._ID; // same in both - String sharedKeyIdColumn = PublicKeys.KEY_ID; // same in both - String sharedKeyDataColumn = PublicKeys.KEY_DATA; // same in both - int idIndex = cursor.getColumnIndex(sharedIdColumn); - int keyIdIndex = cursor.getColumnIndex(sharedKeyIdColumn); - int keyDataIndex = cursor.getColumnIndex(sharedKeyDataColumn); - - byte keyData[] = cursor.getBlob(keyDataIndex); - int id = cursor.getInt(idIndex); - long keyId = cursor.getLong(keyIdIndex); - - try { - if (type == Id.type.secret_key) { - PGPSecretKeyRing key = new PGPSecretKeyRing(keyData); - mSecretKeyRings.add(key); - mSecretKeyIdToIdMap.put(keyId, id); - mSecretKeyIdToKeyRingMap.put(keyId, key); - } else { - PGPPublicKeyRing key = new PGPPublicKeyRing(keyData); - mPublicKeyRings.add(key); - mPublicKeyIdToIdMap.put(keyId, id); - mPublicKeyIdToKeyRingMap.put(keyId, key); - } - } catch (IOException e) { - // TODO: some error handling - } catch (PGPException e) { - // TODO: some error handling - } - } - - if (type == Id.type.secret_key) { - Collections.sort(mSecretKeyRings, new SecretKeySorter()); - } else { - Collections.sort(mPublicKeyRings, new PublicKeySorter()); - } - } - public static Date getCreationDate(PGPPublicKey key) { return key.getCreationTime(); } @@ -987,7 +819,7 @@ public class Apg { } public static PGPPublicKey getEncryptPublicKey(long masterKeyId) { - PGPPublicKeyRing keyRing = mPublicKeyIdToKeyRingMap.get(masterKeyId); + PGPPublicKeyRing keyRing = getPublicKeyRing(masterKeyId); if (keyRing == null) { return null; } @@ -999,7 +831,7 @@ public class Apg { } public static PGPSecretKey getSigningKey(long masterKeyId) { - PGPSecretKeyRing keyRing = mSecretKeyIdToKeyRingMap.get(masterKeyId); + PGPSecretKeyRing keyRing = getSecretKeyRing(masterKeyId); if (keyRing == null) { return null; } @@ -1040,14 +872,6 @@ public class Apg { return userId; } - public static PGPPublicKeyRing getPublicKeyRing(long keyId) { - return mPublicKeyIdToKeyRingMap.get(keyId); - } - - public static PGPSecretKeyRing getSecretKeyRing(long keyId) { - return mSecretKeyIdToKeyRingMap.get(keyId); - } - public static boolean isEncryptionKey(PGPPublicKey key) { if (!key.isEncryptionKey()) { return false; @@ -1127,9 +951,17 @@ public class Apg { } public static String getAlgorithmInfo(PGPPublicKey key) { + return getAlgorithmInfo(key.getAlgorithm(), key.getBitStrength()); + } + + public static String getAlgorithmInfo(PGPSecretKey key) { + return getAlgorithmInfo(key.getPublicKey()); + } + + public static String getAlgorithmInfo(int algorithm, int keySize) { String algorithmStr = null; - switch (key.getAlgorithm()) { + switch (algorithm) { case PGPPublicKey.RSA_ENCRYPT: case PGPPublicKey.RSA_GENERAL: case PGPPublicKey.RSA_SIGN: { @@ -1153,96 +985,38 @@ public class Apg { break; } } - return algorithmStr + ", " + key.getBitStrength() + "bit"; - } - - public static String getAlgorithmInfo(PGPSecretKey key) { - return getAlgorithmInfo(key.getPublicKey()); + 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); - loadKeyRings(context, Id.type.public_key); } 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); - loadKeyRings(context, Id.type.secret_key); } - public static PGPPublicKey findPublicKey(long keyId) { - PGPPublicKey key = null; - for (int i = 0; i < mPublicKeyRings.size(); ++i) { - PGPPublicKeyRing keyRing = mPublicKeyRings.get(i); - try { - key = keyRing.getPublicKey(keyId); - if (key != null) { - return key; - } - } catch (PGPException e) { - // just not found, can ignore this - } - } + public static PGPSecretKeyRing getSecretKeyRing(long keyId) { + // TODO return null; } - public static PGPSecretKey findSecretKey(long keyId) { - PGPSecretKey key = null; - for (int i = 0; i < mSecretKeyRings.size(); ++i) { - PGPSecretKeyRing keyRing = mSecretKeyRings.get(i); - key = keyRing.getSecretKey(keyId); - if (key != null) { - return key; - } - } + public static PGPPublicKeyRing getPublicKeyRing(long keyId) { + // TODO return null; } - public static PGPSecretKeyRing findSecretKeyRing(long keyId) { - for (int i = 0; i < mSecretKeyRings.size(); ++i) { - PGPSecretKeyRing keyRing = mSecretKeyRings.get(i); - PGPSecretKey key = null; - key = keyRing.getSecretKey(keyId); - if (key != null) { - return keyRing; - } - } + public static PGPSecretKey getSecretKey(long keyId) { + // TODO return null; } - public static PGPPublicKeyRing findPublicKeyRing(long keyId) { - for (int i = 0; i < mPublicKeyRings.size(); ++i) { - PGPPublicKeyRing keyRing = mPublicKeyRings.get(i); - PGPPublicKey key = null; - try { - key = keyRing.getPublicKey(keyId); - if (key != null) { - return keyRing; - } - } catch (PGPException e) { - // key not found - } - } - return null; - } - - public static PGPPublicKey getPublicMasterKey(long keyId) { - PGPPublicKey key = null; - for (int i = 0; i < mPublicKeyRings.size(); ++i) { - PGPPublicKeyRing keyRing = mPublicKeyRings.get(i); - try { - key = keyRing.getPublicKey(keyId); - if (key != null) { - return getMasterKey(keyRing); - } - } catch (PGPException e) { - // just not found, can ignore this - } - } + public static PGPPublicKey getPublicKey(long keyId) { + // TODO return null; } @@ -1282,7 +1056,7 @@ public class Apg { } if (signatureKeyId != 0) { - signingKeyRing = findSecretKeyRing(signatureKeyId); + signingKeyRing = getSecretKeyRing(signatureKeyId); signingKey = getSigningKey(signatureKeyId); if (signingKey == null) { throw new GeneralException(context.getString(R.string.error_signatureFailed)); @@ -1398,7 +1172,7 @@ public class Apg { throw new GeneralException(context.getString(R.string.error_noSignatureKey)); } - signingKeyRing = findSecretKeyRing(signatureKeyId); + signingKeyRing = getSecretKeyRing(signatureKeyId); signingKey = getSigningKey(signatureKeyId); if (signingKey == null) { throw new GeneralException(context.getString(R.string.error_signatureFailed)); @@ -1484,7 +1258,7 @@ public class Apg { if (obj instanceof PGPPublicKeyEncryptedData) { gotAsymmetricEncryption = true; PGPPublicKeyEncryptedData pbe = (PGPPublicKeyEncryptedData) obj; - secretKey = findSecretKey(pbe.getKeyID()); + secretKey = getSecretKey(pbe.getKeyID()); if (secretKey != null) { break; } @@ -1594,7 +1368,7 @@ public class Apg { Object obj = it.next(); if (obj instanceof PGPPublicKeyEncryptedData) { PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj; - secretKey = findSecretKey(encData.getKeyID()); + secretKey = getSecretKey(encData.getKeyID()); if (secretKey != null) { pbe = encData; break; @@ -1643,7 +1417,7 @@ public class Apg { PGPOnePassSignatureList sigList = (PGPOnePassSignatureList) dataChunk; for (int i = 0; i < sigList.size(); ++i) { signature = sigList.get(i); - signatureKey = findPublicKey(signature.getKeyID()); + signatureKey = getPublicKey(signature.getKeyID()); if (signatureKeyId == 0) { signatureKeyId = signature.getKeyID(); } @@ -1653,7 +1427,7 @@ public class Apg { signatureIndex = i; signatureKeyId = signature.getKeyID(); String userId = null; - PGPPublicKeyRing sigKeyRing = findPublicKeyRing(signatureKeyId); + PGPPublicKeyRing sigKeyRing = getPublicKeyRing(signatureKeyId); if (sigKeyRing != null) { userId = getMainUserId(getMasterKey(sigKeyRing)); } @@ -1788,7 +1562,7 @@ public class Apg { PGPPublicKey signatureKey = null; for (int i = 0; i < sigList.size(); ++i) { signature = sigList.get(i); - signatureKey = findPublicKey(signature.getKeyID()); + signatureKey = getPublicKey(signature.getKeyID()); if (signatureKeyId == 0) { signatureKeyId = signature.getKeyID(); } @@ -1797,7 +1571,7 @@ public class Apg { } else { signatureKeyId = signature.getKeyID(); String userId = null; - PGPPublicKeyRing sigKeyRing = findPublicKeyRing(signatureKeyId); + PGPPublicKeyRing sigKeyRing = getPublicKeyRing(signatureKeyId); if (sigKeyRing != null) { userId = getMainUserId(getMasterKey(sigKeyRing)); } @@ -1840,15 +1614,6 @@ public class Apg { return returnData; } - public static Vector getPublicKeyRings() { - return mPublicKeyRings; - } - - public static Vector getSecretKeyRings() { - return mSecretKeyRings; - } - - // taken from ClearSignedFileProcessor in BC private static int readInputLine(ByteArrayOutputStream bOut, InputStream fIn) throws IOException { diff --git a/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java b/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java index 67aad7529..2f3b6ed6f 100644 --- a/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java +++ b/src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java @@ -47,7 +47,7 @@ public class AskForSecretKeyPassPhrase { secretKey = null; alert.setMessage(context.getString(R.string.passPhraseForSymmetricEncryption)); } else { - secretKey = Apg.getMasterKey(Apg.findSecretKeyRing(secretKeyId)); + secretKey = Apg.getSecretKey(secretKeyId); if (secretKey == null) { return null; } @@ -67,28 +67,28 @@ public class AskForSecretKeyPassPhrase { final PassPhraseCallbackInterface cb = callback; final Activity activity = context; alert.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - activity.removeDialog(Id.dialog.pass_phrase); - String passPhrase = "" + input.getText(); - long keyId; - if (secretKey != null) { - try { - secretKey.extractPrivateKey(passPhrase.toCharArray(), - new BouncyCastleProvider()); - } catch (PGPException e) { - Toast.makeText(activity, - R.string.wrongPassPhrase, - Toast.LENGTH_SHORT).show(); - return; - } - keyId = secretKey.getKeyID(); - } else { - keyId = Id.key.symmetric; - } - cb.passPhraseCallback(keyId, passPhrase); - } - }); + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + activity.removeDialog(Id.dialog.pass_phrase); + String passPhrase = "" + input.getText(); + long keyId; + if (secretKey != null) { + try { + secretKey.extractPrivateKey(passPhrase.toCharArray(), + new BouncyCastleProvider()); + } catch (PGPException e) { + Toast.makeText(activity, + R.string.wrongPassPhrase, + Toast.LENGTH_SHORT).show(); + return; + } + keyId = secretKey.getKeyID(); + } else { + keyId = Id.key.symmetric; + } + cb.passPhraseCallback(keyId, passPhrase); + } + }); alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { diff --git a/src/org/thialfihar/android/apg/BaseActivity.java b/src/org/thialfihar/android/apg/BaseActivity.java index 8edb27a5e..fe5c0e682 100644 --- a/src/org/thialfihar/android/apg/BaseActivity.java +++ b/src/org/thialfihar/android/apg/BaseActivity.java @@ -32,6 +32,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; @@ -68,7 +69,15 @@ public class BaseActivity extends Activity if (mPreferences == null) { mPreferences = getPreferences(MODE_PRIVATE); } - Apg.initialize(this); + + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + File dir = new File(Constants.path.app_dir); + if (!dir.exists() && !dir.mkdirs()) { + // ignore this for now, it's not crucial + // that the directory doesn't exist at this point + } + } + if (mCacheTimer == null) { setPassPhraseCacheTimer(); } diff --git a/src/org/thialfihar/android/apg/EncryptActivity.java b/src/org/thialfihar/android/apg/EncryptActivity.java index d76b568a6..b31ba3468 100644 --- a/src/org/thialfihar/android/apg/EncryptActivity.java +++ b/src/org/thialfihar/android/apg/EncryptActivity.java @@ -279,7 +279,7 @@ public class EncryptActivity extends BaseActivity { long signatureKeyId = extras.getLong("signatureKeyId"); long encryptionKeyIds[] = extras.getLongArray("encryptionKeyIds"); if (signatureKeyId != 0) { - PGPSecretKeyRing keyRing = Apg.findSecretKeyRing(signatureKeyId); + PGPSecretKeyRing keyRing = Apg.getSecretKeyRing(signatureKeyId); PGPSecretKey masterKey = null; if (keyRing != null) { masterKey = Apg.getMasterKey(keyRing); @@ -295,7 +295,7 @@ public class EncryptActivity extends BaseActivity { if (encryptionKeyIds != null) { Vector goodIds = new Vector(); for (int i = 0; i < encryptionKeyIds.length; ++i) { - PGPPublicKeyRing keyRing = Apg.findPublicKeyRing(encryptionKeyIds[i]); + PGPPublicKeyRing keyRing = Apg.getPublicKeyRing(encryptionKeyIds[i]); PGPPublicKey masterKey = null; if (keyRing == null) { continue; diff --git a/src/org/thialfihar/android/apg/Id.java b/src/org/thialfihar/android/apg/Id.java index 1806de587..4567f937d 100644 --- a/src/org/thialfihar/android/apg/Id.java +++ b/src/org/thialfihar/android/apg/Id.java @@ -80,6 +80,11 @@ public final class Id { public static final int export_keys = 0x21070002; } + public static final class database { + public static final int type_public = 0; + public static final int type_secret = 1; + } + public static final class type { public static final int public_key = 0x21070001; public static final int secret_key = 0x21070002; @@ -87,11 +92,6 @@ public final class Id { public static final int key = 0x21070004; } - public static final class database { - public static final int type_public = 0; - public static final int type_secret = 1; - } - public static final class choice { public static final class algorithm { public static final int dsa = 0x21070001; diff --git a/src/org/thialfihar/android/apg/KeyListActivity.java b/src/org/thialfihar/android/apg/KeyListActivity.java new file mode 100644 index 000000000..da696398b --- /dev/null +++ b/src/org/thialfihar/android/apg/KeyListActivity.java @@ -0,0 +1,633 @@ +/* + * Copyright (C) 2010 Thialfihar + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thialfihar.android.apg; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Vector; + +import org.bouncycastle2.openpgp.PGPException; +import org.thialfihar.android.apg.provider.Database; +import org.thialfihar.android.apg.provider.KeyRings; +import org.thialfihar.android.apg.provider.Keys; +import org.thialfihar.android.apg.provider.UserIds; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Bundle; +import android.os.Message; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; +import android.widget.ExpandableListView; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.ExpandableListView.ExpandableListContextMenuInfo; + +public class KeyListActivity extends BaseActivity { + protected ExpandableListView mList; + + protected int mSelectedItem = -1; + protected int mTask = 0; + + protected String mImportFilename = Constants.path.app_dir + "/"; + protected String mExportFilename = Constants.path.app_dir + "/"; + + protected int mKeyType = Id.type.public_key; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.key_list); + + mList = (ExpandableListView) findViewById(R.id.list); + mList.setAdapter(new KeyListAdapter(this)); + registerForContextMenu(mList); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case Id.menu.option.import_keys: { + showDialog(Id.dialog.import_keys); + return true; + } + + case Id.menu.option.export_keys: { + showDialog(Id.dialog.export_keys); + return true; + } + + default: { + return super.onOptionsItemSelected(item); + } + } + } + + @Override + public boolean onContextItemSelected(MenuItem menuItem) { + ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo(); + int type = ExpandableListView.getPackedPositionType(info.packedPosition); + int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition); + + if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) { + return super.onContextItemSelected(menuItem); + } + + switch (menuItem.getItemId()) { + case Id.menu.export: { + mSelectedItem = groupPosition; + showDialog(Id.dialog.export_key); + return true; + } + + case Id.menu.delete: { + mSelectedItem = groupPosition; + showDialog(Id.dialog.delete_key); + return true; + } + + default: { + return super.onContextItemSelected(menuItem); + } + } + } + + @Override + protected Dialog onCreateDialog(int id) { + boolean singleKeyExport = false; + + 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"; + + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.warning); + builder.setMessage(getString(mKeyType == Id.type.public_key ? + R.string.keyDeletionConfirmation : + R.string.secretKeyDeletionConfirmation, userId)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setPositiveButton(R.string.btn_delete, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + deleteKey(keyId); + removeDialog(Id.dialog.delete_key); + } + }); + builder.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + removeDialog(Id.dialog.delete_key); + } + }); + return builder.create(); + } + + case Id.dialog.import_keys: { + return FileDialog.build(this, getString(R.string.title_importKeys), + getString(R.string.specifyFileToImportFrom), + mImportFilename, + new FileDialog.OnClickListener() { + + @Override + public void onOkClick(String filename) { + removeDialog(Id.dialog.import_keys); + mImportFilename = filename; + importKeys(); + } + + @Override + public void onCancelClick() { + removeDialog(Id.dialog.import_keys); + } + }, + getString(R.string.filemanager_titleOpen), + getString(R.string.filemanager_btnOpen), + Id.request.filename); + } + + case Id.dialog.export_key: { + singleKeyExport = true; + // break intentionally omitted, to use the Id.dialog.export_keys dialog + } + + case Id.dialog.export_keys: { + String title = (singleKeyExport ? + getString(R.string.title_exportKey) : + getString(R.string.title_exportKeys)); + + final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys); + + return FileDialog.build(this, title, + getString(R.string.specifyFileToExportTo), + mExportFilename, + new FileDialog.OnClickListener() { + @Override + public void onOkClick(String filename) { + removeDialog(thisDialogId); + mExportFilename = filename; + exportKeys(); + } + + @Override + public void onCancelClick() { + removeDialog(thisDialogId); + } + }, + getString(R.string.filemanager_titleSave), + getString(R.string.filemanager_btnSave), + Id.request.filename); + } + + default: { + return super.onCreateDialog(id); + } + } + } + + public void importKeys() { + showDialog(Id.dialog.importing); + mTask = Id.task.import_keys; + startThread(); + } + + public void exportKeys() { + showDialog(Id.dialog.exporting); + mTask = Id.task.export_keys; + startThread(); + } + + @Override + public void run() { + String error = null; + Bundle data = new Bundle(); + Message msg = new Message(); + + String filename = null; + if (mTask == Id.task.import_keys) { + filename = mImportFilename; + } else { + filename = mExportFilename; + } + + try { + if (mTask == Id.task.import_keys) { + data = Apg.importKeyRings(this, mKeyType, filename, this); + } else { + Vector keys = new Vector(); + // TODO + /* + if (mSelectedItem == -1) { + for (PGPSecretKeyRing key : Apg.getSecretKeyRings()) { + keys.add(key); + } + } else { + keys.add(Apg.getSecretKeyRings().get(mSelectedItem)); + } + 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); + } + } catch (FileNotFoundException e) { + error = getString(R.string.error_fileNotFound); + } catch (IOException e) { + error = "" + e; + } catch (PGPException e) { + error = "" + e; + } catch (Apg.GeneralException e) { + error = "" + e; + } + + if (mTask == Id.task.import_keys) { + data.putInt("type", Id.message.import_done); + } else { + data.putInt("type", Id.message.export_done); + } + + if (error != null) { + data.putString("error", error); + } + + msg.setData(data); + sendMessage(msg); + } + + protected void deleteKey(long keyId) { + // TODO + //PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(index); + //Apg.deleteKey(this, keyRing); + refreshList(); + } + + protected void refreshList() { + ((KeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged(); + } + + @Override + public void doneCallback(Message msg) { + super.doneCallback(msg); + + Bundle data = msg.getData(); + if (data != null) { + int type = data.getInt("type"); + switch (type) { + case Id.message.import_done: { + removeDialog(Id.dialog.importing); + + String error = data.getString("error"); + if (error != null) { + Toast.makeText(KeyListActivity.this, + getString(R.string.errorMessage, data.getString("error")), + Toast.LENGTH_SHORT).show(); + } else { + int added = data.getInt("added"); + int updated = data.getInt("updated"); + String message; + if (added > 0 && updated > 0) { + message = getString(R.string.keysAddedAndUpdated, added, updated); + } else if (added > 0) { + message = getString(R.string.keysAdded, added); + } else if (updated > 0) { + message = getString(R.string.keysUpdated, updated); + } else { + message = getString(R.string.noKeysAddedOrUpdated); + } + Toast.makeText(KeyListActivity.this, message, + Toast.LENGTH_SHORT).show(); + } + refreshList(); + break; + } + + case Id.message.export_done: { + removeDialog(Id.dialog.exporting); + + String error = data.getString("error"); + if (error != null) { + Toast.makeText(KeyListActivity.this, + getString(R.string.errorMessage, data.getString("error")), + Toast.LENGTH_SHORT).show(); + } else { + int exported = data.getInt("exported"); + String message; + if (exported == 1) { + message = getString(R.string.keyExported); + } else if (exported > 0) { + message = getString(R.string.keysExported); + } else{ + message = getString(R.string.noKeysExported); + } + Toast.makeText(KeyListActivity.this, message, + Toast.LENGTH_SHORT).show(); + } + break; + } + + default: { + break; + } + } + } + } + + protected class KeyListAdapter extends BaseExpandableListAdapter { + private LayoutInflater mInflater; + private Vector> mChildren; + private SQLiteDatabase mDatabase; + private Cursor mCursor; + + private class KeyChild { + public static final int KEY = 0; + public static final int USER_ID = 1; + + public int type; + public String userId; + public long keyId; + public boolean isMasterKey; + public int algorithm; + public int keySize; + public boolean canSign; + public boolean canEncrypt; + + public KeyChild(long keyId, boolean isMasterKey, int algorithm, int keySize, + boolean canSign, boolean canEncrypt) { + this.keyId = keyId; + this.isMasterKey = isMasterKey; + this.algorithm = algorithm; + this.keySize = keySize; + this.canSign = canSign; + this.canEncrypt = canEncrypt; + } + + public KeyChild(String userId) { + type = USER_ID; + this.userId = userId; + } + } + + public KeyListAdapter(Context context) { + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mDatabase = new Database(context).getReadableDatabase(); + mCursor = mDatabase.query( + 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') ", + new String[] { + KeyRings.TABLE_NAME + "." + KeyRings._ID, // 0 + KeyRings.TABLE_NAME + "." + KeyRings.MASTER_KEY_ID, // 1 + UserIds.TABLE_NAME + "." + UserIds.USER_ID, // 2 + }, + KeyRings.TABLE_NAME + "." + KeyRings.TYPE + " = ?", + new String[] { "" + (mKeyType == Id.type.public_key ? + Id.database.type_public : + Id.database.type_secret) }, + null, null, null); + + mChildren = new Vector>(); + for (int i = 0; i < mCursor.getCount(); ++i) { + mChildren.add(null); + } + } + + @Override + protected void finalize() throws Throwable { + mCursor.close(); + mDatabase.close(); + super.finalize(); + } + + protected Vector getChildrenOfGroup(int groupPosition) { + Vector children = mChildren.get(groupPosition); + if (children != null) { + return children; + } + + mCursor.moveToPosition(groupPosition); + children = new Vector(); + Cursor c = mDatabase.query(Keys.TABLE_NAME, + new String[] { + Keys._ID, // 0 + Keys.KEY_ID, // 1 + Keys.IS_MASTER_KEY, // 2 + Keys.ALGORITHM, // 3 + Keys.KEY_SIZE, // 4 + Keys.CAN_SIGN, // 5 + Keys.CAN_ENCRYPT, // 6 + }, + Keys.KEY_RING_ID + " = ?", + new String[] { mCursor.getString(0) }, + null, null, Keys.RANK + " ASC"); + + long masterKeyId = -1; + for (int i = 0; i < c.getCount(); ++i) { + c.moveToPosition(i); + children.add(new KeyChild(c.getLong(1), c.getInt(2) == 1, c.getInt(3), c.getInt(4), + c.getInt(5) == 1, c.getInt(6) == 1)); + if (i == 0) { + masterKeyId = c.getInt(0); + } + } + c.close(); + + if (masterKeyId != -1) { + c = mDatabase.query(UserIds.TABLE_NAME, + new String[] { + UserIds.USER_ID, // 0 + }, + UserIds.KEY_ID + " = ?", + new String[] { "" + masterKeyId }, + null, null, UserIds.RANK + " ASC"); + + for (int i = 0; i < c.getCount(); ++i) { + c.moveToPosition(i); + children.add(new KeyChild(c.getString(0))); + } + c.close(); + } + + mChildren.set(groupPosition, children); + return children; + } + + + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return true; + } + + public int getGroupCount() { + return mCursor.getCount(); + } + + public Object getChild(int groupPosition, int childPosition) { + return null; + } + + public long getChildId(int groupPosition, int childPosition) { + return childPosition; + } + + public int getChildrenCount(int groupPosition) { + return getChildrenOfGroup(groupPosition).size(); + } + + public Object getGroup(int position) { + return position; + } + + public long getGroupId(int position) { + mCursor.moveToPosition(position); + return mCursor.getLong(1); // MASTER_KEY_ID + } + + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, + ViewGroup parent) { + mCursor.moveToPosition(groupPosition); + + View view = mInflater.inflate(R.layout.key_list_group_item, null); + view.setBackgroundResource(android.R.drawable.list_selector_background); + + TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); + mainUserId.setText(""); + TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); + mainUserIdRest.setText(""); + + String userId = mCursor.getString(2); // USER_ID + if (userId != null) { + String chunks[] = userId.split(" <", 2); + userId = chunks[0]; + if (chunks.length > 1) { + mainUserIdRest.setText("<" + chunks[1]); + } + mainUserId.setText(userId); + } + + if (mainUserId.getText().length() == 0) { + mainUserId.setText(R.string.unknownUserId); + } + + if (mainUserIdRest.getText().length() == 0) { + mainUserIdRest.setVisibility(View.GONE); + } + return view; + } + + public View getChildView(int groupPosition, int childPosition, + boolean isLastChild, View convertView, + ViewGroup parent) { + mCursor.moveToPosition(groupPosition); + + Vector children = getChildrenOfGroup(groupPosition); + + KeyChild child = children.get(childPosition); + View view = null; + switch (child.type) { + case KeyChild.KEY: { + if (child.isMasterKey) { + view = mInflater.inflate(R.layout.key_list_child_item_master_key, null); + } else { + view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null); + } + + TextView keyId = (TextView) view.findViewById(R.id.keyId); + String keyIdStr = Long.toHexString(child.keyId & 0xffffffffL); + while (keyIdStr.length() < 8) { + keyIdStr = "0" + keyIdStr; + } + keyId.setText(keyIdStr); + TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails); + String algorithmStr = Apg.getAlgorithmInfo(child.algorithm, child.keySize); + keyDetails.setText("(" + algorithmStr + ")"); + + ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey); + if (!child.canEncrypt) { + encryptIcon.setVisibility(View.GONE); + } + + ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey); + if (!child.canSign) { + signIcon.setVisibility(View.GONE); + } + break; + } + + case KeyChild.USER_ID: { + view = mInflater.inflate(R.layout.key_list_child_item_user_id, null); + TextView userId = (TextView) view.findViewById(R.id.userId); + userId.setText(child.userId); + break; + } + } + return view; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + switch (requestCode) { + case Id.request.filename: { + if (resultCode == RESULT_OK && data != null) { + String filename = data.getDataString(); + if (filename != null) { + // Get rid of URI prefix: + if (filename.startsWith("file://")) { + filename = filename.substring(7); + } + // replace %20 and so on + filename = Uri.decode(filename); + + FileDialog.setFilename(filename); + } + } + return; + } + + default: { + break; + } + } + super.onActivityResult(requestCode, resultCode, data); + } +} diff --git a/src/org/thialfihar/android/apg/PublicKeyListActivity.java b/src/org/thialfihar/android/apg/PublicKeyListActivity.java index 4f4f49bba..4997f60b7 100644 --- a/src/org/thialfihar/android/apg/PublicKeyListActivity.java +++ b/src/org/thialfihar/android/apg/PublicKeyListActivity.java @@ -16,54 +16,19 @@ package org.thialfihar.android.apg; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Vector; - -import org.bouncycastle2.openpgp.PGPException; -import org.bouncycastle2.openpgp.PGPPublicKey; -import org.bouncycastle2.openpgp.PGPPublicKeyRing; -import org.thialfihar.android.apg.utils.IterableIterator; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; import android.os.Bundle; -import android.os.Message; import android.view.ContextMenu; -import android.view.LayoutInflater; import android.view.Menu; -import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; -import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; -import android.widget.ExpandableListView.ExpandableListContextMenuInfo; - -public class PublicKeyListActivity extends BaseActivity { - ExpandableListView mList; - - protected int mSelectedItem = -1; - protected int mTask = 0; - - private String mImportFilename = Constants.path.app_dir + "/"; - private String mExportFilename = Constants.path.app_dir + "/pubexport.asc"; +public class PublicKeyListActivity extends KeyListActivity { @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { + mExportFilename = Constants.path.app_dir + "/pubexport.asc"; + mKeyType = Id.type.public_key; super.onCreate(savedInstanceState); - setContentView(R.layout.key_list); - - mList = (ExpandableListView) findViewById(R.id.list); - mList.setAdapter(new PublicKeyListAdapter(this)); - registerForContextMenu(mList); } @Override @@ -79,507 +44,17 @@ public class PublicKeyListActivity extends BaseActivity { return true; } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case Id.menu.option.import_keys: { - showDialog(Id.dialog.import_keys); - return true; - } - - case Id.menu.option.export_keys: { - showDialog(Id.dialog.export_keys); - return true; - } - - default: { - return super.onOptionsItemSelected(item); - } - } - } - @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo; int type = ExpandableListView.getPackedPositionType(info.packedPosition); - int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition); if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { - PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition); - String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); - menu.setHeaderTitle(userId); + // TODO: user id? menu.setHeaderTitle("Key"); menu.add(0, Id.menu.export, 0, R.string.menu_exportKey); menu.add(0, Id.menu.delete, 1, R.string.menu_deleteKey); } } - - @Override - public boolean onContextItemSelected(MenuItem menuItem) { - ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuItem.getMenuInfo(); - int type = ExpandableListView.getPackedPositionType(info.packedPosition); - int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition); - - if (type != ExpandableListView.PACKED_POSITION_TYPE_GROUP) { - return super.onContextItemSelected(menuItem); - } - - switch (menuItem.getItemId()) { - case Id.menu.export: { - mSelectedItem = groupPosition; - showDialog(Id.dialog.export_key); - return true; - } - - case Id.menu.delete: { - mSelectedItem = groupPosition; - showDialog(Id.dialog.delete_key); - return true; - } - - default: { - return super.onContextItemSelected(menuItem); - } - } - } - - @Override - protected Dialog onCreateDialog(int id) { - boolean singleKeyExport = false; - - switch (id) { - case Id.dialog.delete_key: { - PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(mSelectedItem); - String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.warning); - builder.setMessage(getString(R.string.keyDeletionConfirmation, userId)); - builder.setIcon(android.R.drawable.ic_dialog_alert); - builder.setPositiveButton(R.string.btn_delete, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - deleteKey(mSelectedItem); - mSelectedItem = -1; - removeDialog(Id.dialog.delete_key); - } - }); - builder.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - mSelectedItem = -1; - removeDialog(Id.dialog.delete_key); - } - }); - return builder.create(); - } - - case Id.dialog.import_keys: { - return FileDialog.build(this, getString(R.string.title_importKeys), - getString(R.string.specifyFileToImportFrom), - mImportFilename, - new FileDialog.OnClickListener() { - - @Override - public void onOkClick(String filename) { - removeDialog(Id.dialog.import_keys); - mImportFilename = filename; - importKeys(); - } - - @Override - public void onCancelClick() { - removeDialog(Id.dialog.import_keys); - } - }, - getString(R.string.filemanager_titleOpen), - getString(R.string.filemanager_btnOpen), - Id.request.filename); - } - - case Id.dialog.export_key: { - singleKeyExport = true; - // break intentionally omitted, to use the Id.dialog.export_keys dialog - } - - case Id.dialog.export_keys: { - String title = (singleKeyExport ? - getString(R.string.title_exportKey) : - getString(R.string.title_exportKeys)); - - final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys); - - return FileDialog.build(this, title, - getString(R.string.specifyFileToExportTo), - mExportFilename, - new FileDialog.OnClickListener() { - - @Override - public void onOkClick(String filename) { - removeDialog(thisDialogId); - mExportFilename = filename; - exportKeys(); - } - - @Override - public void onCancelClick() { - removeDialog(thisDialogId); - } - }, - getString(R.string.filemanager_titleSave), - getString(R.string.filemanager_btnSave), - Id.request.filename); - } - - default: { - return super.onCreateDialog(id); - } - } - } - - public void importKeys() { - showDialog(Id.dialog.importing); - mTask = Id.task.import_keys; - startThread(); - } - - public void exportKeys() { - showDialog(Id.dialog.exporting); - mTask = Id.task.export_keys; - startThread(); - } - - @Override - public void run() { - String error = null; - Bundle data = new Bundle(); - Message msg = new Message(); - - String filename = null; - if (mTask == Id.task.import_keys) { - filename = mImportFilename; - } else { - filename = mExportFilename; - } - - try { - if (mTask == Id.task.import_keys) { - data = Apg.importKeyRings(this, Id.type.public_key, filename, this); - } else { - Vector keys = new Vector(); - 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); - } - } catch (FileNotFoundException e) { - error = getString(R.string.error_fileNotFound); - } catch (IOException e) { - error = "" + e; - } catch (PGPException e) { - error = "" + e; - } catch (Apg.GeneralException e) { - error = "" + e; - } - - if (mTask == Id.task.import_keys) { - data.putInt("type", Id.message.import_done); - } else { - data.putInt("type", Id.message.export_done); - } - - if (error != null) { - data.putString("error", error); - } - - msg.setData(data); - sendMessage(msg); - } - - private void deleteKey(int index) { - PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(index); - Apg.deleteKey(this, keyRing); - refreshList(); - } - - private void refreshList() { - ((PublicKeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged(); - } - - @Override - public void doneCallback(Message msg) { - super.doneCallback(msg); - - Bundle data = msg.getData(); - if (data != null) { - int type = data.getInt("type"); - switch (type) { - case Id.message.import_done: { - removeDialog(Id.dialog.importing); - - String error = data.getString("error"); - if (error != null) { - Toast.makeText(PublicKeyListActivity.this, - getString(R.string.errorMessage, data.getString("error")), - Toast.LENGTH_SHORT).show(); - } else { - int added = data.getInt("added"); - int updated = data.getInt("updated"); - String message; - if (added > 0 && updated > 0) { - message = getString(R.string.keysAddedAndUpdated, added, updated); - } else if (added > 0) { - message = getString(R.string.keysAdded, added); - } else if (updated > 0) { - message = getString(R.string.keysUpdated, updated); - } else { - message = getString(R.string.noKeysAddedOrUpdated); - } - Toast.makeText(PublicKeyListActivity.this, message, - Toast.LENGTH_SHORT).show(); - } - refreshList(); - break; - } - - case Id.message.export_done: { - removeDialog(Id.dialog.exporting); - - String error = data.getString("error"); - if (error != null) { - Toast.makeText(PublicKeyListActivity.this, - getString(R.string.errorMessage, data.getString("error")), - Toast.LENGTH_SHORT).show(); - } else { - int exported = data.getInt("exported"); - String message; - if (exported == 1) { - message = getString(R.string.keyExported); - } else if (exported > 0) { - message = getString(R.string.keysExported); - } else{ - message = getString(R.string.noKeysExported); - } - Toast.makeText(PublicKeyListActivity.this, message, - Toast.LENGTH_SHORT).show(); - } - break; - } - - default: { - break; - } - } - } - } - - private static class PublicKeyListAdapter extends BaseExpandableListAdapter { - private LayoutInflater mInflater; - - private class KeyChild { - public static final int KEY = 0; - public static final int USER_ID = 1; - - public int type; - public PGPPublicKey key; - public String userId; - - public KeyChild(PGPPublicKey key) { - type = KEY; - this.key = key; - } - - public KeyChild(String userId) { - type = USER_ID; - this.userId = userId; - } - } - - public PublicKeyListAdapter(Context context) { - mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - protected Vector getChildrenOfKeyRing(PGPPublicKeyRing keyRing) { - Vector children = new Vector(); - PGPPublicKey masterKey = null; - for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { - children.add(new KeyChild(key)); - if (key.isMasterKey()) { - masterKey = key; - } - } - - if (masterKey != null) { - boolean isFirst = true; - for (String userId : new IterableIterator(masterKey.getUserIDs())) { - if (isFirst) { - // ignore first, it's in the group already - isFirst = false; - continue; - } - children.add(new KeyChild(userId)); - } - } - - return children; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public boolean isChildSelectable(int groupPosition, int childPosition) { - return true; - } - - public int getGroupCount() { - return Apg.getPublicKeyRings().size(); - } - - public Object getChild(int groupPosition, int childPosition) { - PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition); - Vector children = getChildrenOfKeyRing(keyRing); - - KeyChild child = children.get(childPosition); - return child; - } - - public long getChildId(int groupPosition, int childPosition) { - return childPosition; - } - - public int getChildrenCount(int groupPosition) { - return getChildrenOfKeyRing(Apg.getPublicKeyRings().get(groupPosition)).size(); - } - - public Object getGroup(int position) { - return position; - } - - public long getGroupId(int position) { - return position; - } - - public View getGroupView(int groupPosition, boolean isExpanded, View convertView, - ViewGroup parent) { - PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition); - for (PGPPublicKey key : new IterableIterator(keyRing.getPublicKeys())) { - View view; - if (!key.isMasterKey()) { - continue; - } - view = mInflater.inflate(R.layout.key_list_group_item, null); - view.setBackgroundResource(android.R.drawable.list_selector_background); - - TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); - mainUserId.setText(""); - TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - mainUserIdRest.setText(""); - - String userId = Apg.getMainUserId(key); - if (userId != null) { - String chunks[] = userId.split(" <", 2); - userId = chunks[0]; - if (chunks.length > 1) { - mainUserIdRest.setText("<" + chunks[1]); - } - mainUserId.setText(userId); - } - - if (mainUserId.getText().length() == 0) { - mainUserId.setText(R.string.unknownUserId); - } - - if (mainUserIdRest.getText().length() == 0) { - mainUserIdRest.setVisibility(View.GONE); - } - return view; - } - return null; - } - - public View getChildView(int groupPosition, int childPosition, - boolean isLastChild, View convertView, - ViewGroup parent) { - PGPPublicKeyRing keyRing = Apg.getPublicKeyRings().get(groupPosition); - Vector children = getChildrenOfKeyRing(keyRing); - - KeyChild child = children.get(childPosition); - View view = null; - switch (child.type) { - case KeyChild.KEY: { - PGPPublicKey key = child.key; - if (key.isMasterKey()) { - view = mInflater.inflate(R.layout.key_list_child_item_master_key, null); - } else { - view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null); - } - - TextView keyId = (TextView) view.findViewById(R.id.keyId); - String keyIdStr = Long.toHexString(key.getKeyID() & 0xffffffffL); - while (keyIdStr.length() < 8) { - keyIdStr = "0" + keyIdStr; - } - keyId.setText(keyIdStr); - TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails); - String algorithmStr = Apg.getAlgorithmInfo(key); - keyDetails.setText("(" + algorithmStr + ")"); - - ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey); - if (!Apg.isEncryptionKey(key)) { - encryptIcon.setVisibility(View.GONE); - } - - ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey); - if (!Apg.isSigningKey(key)) { - signIcon.setVisibility(View.GONE); - } - break; - } - - case KeyChild.USER_ID: { - view = mInflater.inflate(R.layout.key_list_child_item_user_id, null); - TextView userId = (TextView) view.findViewById(R.id.userId); - userId.setText(child.userId); - break; - } - } - return view; - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case Id.request.filename: { - if (resultCode == RESULT_OK && data != null) { - String filename = data.getDataString(); - if (filename != null) { - // Get rid of URI prefix: - if (filename.startsWith("file://")) { - filename = filename.substring(7); - } - // replace %20 and so on - filename = Uri.decode(filename); - - FileDialog.setFilename(filename); - } - - } - return; - } - - default: { - break; - } - } - super.onActivityResult(requestCode, resultCode, data); - } } diff --git a/src/org/thialfihar/android/apg/SecretKeyListActivity.java b/src/org/thialfihar/android/apg/SecretKeyListActivity.java index 3612e73fc..3d46cee5c 100644 --- a/src/org/thialfihar/android/apg/SecretKeyListActivity.java +++ b/src/org/thialfihar/android/apg/SecretKeyListActivity.java @@ -16,55 +16,24 @@ package org.thialfihar.android.apg; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Vector; - -import org.bouncycastle2.openpgp.PGPException; -import org.bouncycastle2.openpgp.PGPSecretKey; -import org.bouncycastle2.openpgp.PGPSecretKeyRing; -import org.thialfihar.android.apg.utils.IterableIterator; - -import android.app.AlertDialog; import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; -import android.net.Uri; import android.os.Bundle; -import android.os.Message; import android.view.ContextMenu; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; -import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ExpandableListView.OnChildClickListener; -public class SecretKeyListActivity extends BaseActivity implements OnChildClickListener { - ExpandableListView mList; - - protected int mSelectedItem = -1; - protected int mTask = 0; - - private String mImportFilename = Constants.path.app_dir + "/"; - private String mExportFilename = Constants.path.app_dir + "/secexport.asc"; - +public class SecretKeyListActivity extends KeyListActivity implements OnChildClickListener { @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { + mExportFilename = Constants.path.app_dir + "/secexport.asc"; + mKeyType = Id.type.secret_key; super.onCreate(savedInstanceState); - setContentView(R.layout.key_list); - - mList = (ExpandableListView) findViewById(R.id.list); - mList.setAdapter(new SecretKeyListAdapter(this)); - registerForContextMenu(mList); mList.setOnChildClickListener(this); } @@ -86,16 +55,6 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case Id.menu.option.import_keys: { - showDialog(Id.dialog.import_keys); - return true; - } - - case Id.menu.option.export_keys: { - showDialog(Id.dialog.export_keys); - return true; - } - case Id.menu.option.create: { createKey(); return true; @@ -113,12 +72,9 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo; int type = ExpandableListView.getPackedPositionType(info.packedPosition); - int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition); if (type == ExpandableListView.PACKED_POSITION_TYPE_GROUP) { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition); - String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); - menu.setHeaderTitle(userId); + // TODO: user id? menu.setHeaderTitle("Key"); menu.add(0, Id.menu.edit, 0, R.string.menu_editKey); menu.add(0, Id.menu.export, 1, R.string.menu_exportKey); menu.add(0, Id.menu.delete, 2, R.string.menu_deleteKey); @@ -142,18 +98,6 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL return true; } - case Id.menu.export: { - mSelectedItem = groupPosition; - showDialog(Id.dialog.export_key); - return true; - } - - case Id.menu.delete: { - mSelectedItem = groupPosition; - showDialog(Id.dialog.delete_key); - return true; - } - default: { return super.onContextItemSelected(menuItem); } @@ -170,96 +114,9 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL @Override protected Dialog onCreateDialog(int id) { - boolean singleKeyExport = false; - switch (id) { - case Id.dialog.delete_key: { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem); - - String userId = Apg.getMainUserIdSafe(this, Apg.getMasterKey(keyRing)); - - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.warning); - builder.setMessage(getString(R.string.secretKeyDeletionConfirmation, userId)); - builder.setIcon(android.R.drawable.ic_dialog_alert); - builder.setPositiveButton(R.string.btn_delete, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - deleteKey(mSelectedItem); - mSelectedItem = -1; - removeDialog(Id.dialog.delete_key); - } - }); - builder.setNegativeButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - mSelectedItem = -1; - removeDialog(Id.dialog.delete_key); - } - }); - return builder.create(); - } - - case Id.dialog.import_keys: { - return FileDialog.build(this, getString(R.string.title_importKeys), - getString(R.string.specifyFileToImportFrom), - mImportFilename, - new FileDialog.OnClickListener() { - - @Override - public void onOkClick(String filename) { - removeDialog(Id.dialog.import_keys); - mImportFilename = filename; - importKeys(); - } - - @Override - public void onCancelClick() { - removeDialog(Id.dialog.import_keys); - } - }, - getString(R.string.filemanager_titleOpen), - getString(R.string.filemanager_btnOpen), - Id.request.filename); - } - - case Id.dialog.export_key: { - singleKeyExport = true; - // break intentionally omitted, to use the Id.dialog.export_keys dialog - } - - case Id.dialog.export_keys: { - String title = (singleKeyExport ? - getString(R.string.title_exportKey) : - getString(R.string.title_exportKeys)); - - final int thisDialogId = (singleKeyExport ? Id.dialog.export_key : Id.dialog.export_keys); - - return FileDialog.build(this, title, - getString(R.string.specifyFileToExportSecretKeysTo), - mExportFilename, - new FileDialog.OnClickListener() { - - @Override - public void onOkClick(String filename) { - removeDialog(thisDialogId); - mExportFilename = filename; - exportKeys(); - } - - @Override - public void onCancelClick() { - removeDialog(thisDialogId); - } - }, - getString(R.string.filemanager_titleSave), - getString(R.string.filemanager_btnSave), - Id.request.filename); - } - case Id.dialog.pass_phrase: { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem); - long keyId = keyRing.getSecretKey().getKeyID(); + long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); return AskForSecretKeyPassPhrase.createDialog(this, keyId, this); } @@ -270,8 +127,7 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL } public void checkPassPhraseAndEdit() { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem); - long keyId = keyRing.getSecretKey().getKeyID(); + long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); String passPhrase = Apg.getCachedPassPhrase(keyId); if (passPhrase == null) { showDialog(Id.dialog.pass_phrase); @@ -295,8 +151,7 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL } private void editKey() { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(mSelectedItem); - long keyId = keyRing.getSecretKey().getKeyID(); + long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem); Intent intent = new Intent(this, EditKeyActivity.class); intent.putExtra("keyId", keyId); startActivityForResult(intent, Id.message.edit_key); @@ -313,24 +168,6 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL break; } - case Id.request.filename: { - if (resultCode == RESULT_OK && data != null) { - String filename = data.getDataString(); - if (filename != null) { - // Get rid of URI prefix: - if (filename.startsWith("file://")) { - filename = filename.substring(7); - } - // replace %20 and so on - filename = Uri.decode(filename); - - FileDialog.setFilename(filename); - } - - } - return; - } - default: { break; } @@ -338,320 +175,4 @@ public class SecretKeyListActivity extends BaseActivity implements OnChildClickL super.onActivityResult(requestCode, resultCode, data); } - - public void importKeys() { - showDialog(Id.dialog.importing); - mTask = Id.task.import_keys; - startThread(); - } - - public void exportKeys() { - showDialog(Id.dialog.exporting); - mTask = Id.task.export_keys; - startThread(); - } - - @Override - public void run() { - String error = null; - Bundle data = new Bundle(); - Message msg = new Message(); - - String filename = null; - if (mTask == Id.task.import_keys) { - filename = mImportFilename; - } else { - filename = mExportFilename; - } - - try { - if (mTask == Id.task.import_keys) { - data = Apg.importKeyRings(this, Id.type.secret_key, filename, this); - } else { - Vector keys = new Vector(); - if (mSelectedItem == -1) { - for (PGPSecretKeyRing key : Apg.getSecretKeyRings()) { - keys.add(key); - } - } else { - keys.add(Apg.getSecretKeyRings().get(mSelectedItem)); - } - data = Apg.exportKeyRings(this, keys, filename, this); - } - } catch (FileNotFoundException e) { - error = getString(R.string.error_fileNotFound); - } catch (IOException e) { - error = "" + e; - } catch (PGPException e) { - error = "" + e; - } catch (Apg.GeneralException e) { - error = "" + e; - } - - if (mTask == Id.task.import_keys) { - data.putInt("type", Id.message.import_done); - } else { - data.putInt("type", Id.message.export_done); - } - - if (error != null) { - data.putString("error", error); - } - - msg.setData(data); - sendMessage(msg); - } - - private void deleteKey(int index) { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(index); - Apg.deleteKey(this, keyRing); - refreshList(); - } - - private void refreshList() { - ((SecretKeyListAdapter) mList.getExpandableListAdapter()).notifyDataSetChanged(); - } - - @Override - public void doneCallback(Message msg) { - super.doneCallback(msg); - - Bundle data = msg.getData(); - if (data != null) { - int type = data.getInt("type"); - switch (type) { - case Id.message.import_done: { - removeDialog(Id.dialog.importing); - - String error = data.getString("error"); - if (error != null) { - Toast.makeText(SecretKeyListActivity.this, - getString(R.string.errorMessage, data.getString("error")), - Toast.LENGTH_SHORT).show(); - } else { - int added = data.getInt("added"); - int updated = data.getInt("updated"); - String message; - if (added > 0 && updated > 0) { - message = getString(R.string.keysAddedAndUpdated, added, updated); - } else if (added > 0) { - message = getString(R.string.keysAdded, added); - } else if (updated > 0) { - message = getString(R.string.keysUpdated, updated); - } else { - message = getString(R.string.noKeysAddedOrUpdated); - } - Toast.makeText(SecretKeyListActivity.this, message, - Toast.LENGTH_SHORT).show(); - } - refreshList(); - break; - } - - case Id.message.export_done: { - removeDialog(Id.dialog.exporting); - - String error = data.getString("error"); - if (error != null) { - Toast.makeText(SecretKeyListActivity.this, - getString(R.string.errorMessage, data.getString("error")), - Toast.LENGTH_SHORT).show(); - } else { - int exported = data.getInt("exported"); - String message; - if (exported == 1) { - message = getString(R.string.keyExported); - } else if (exported > 0) { - message = getString(R.string.keysExported); - } else{ - message = getString(R.string.noKeysExported); - } - Toast.makeText(SecretKeyListActivity.this, message, - Toast.LENGTH_SHORT).show(); - } - break; - } - - default: { - break; - } - } - } - } - - private static class SecretKeyListAdapter extends BaseExpandableListAdapter { - private LayoutInflater mInflater; - - private class KeyChild { - static final int KEY = 0; - static final int USER_ID = 1; - - public int type; - public PGPSecretKey key; - public String userId; - - public KeyChild(PGPSecretKey key) { - type = KEY; - this.key = key; - } - - public KeyChild(String userId) { - type = USER_ID; - this.userId = userId; - } - } - - public SecretKeyListAdapter(Context context) { - mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - protected Vector getChildrenOfKeyRing(PGPSecretKeyRing keyRing) { - Vector children = new Vector(); - PGPSecretKey masterKey = null; - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - children.add(new KeyChild(key)); - if (key.isMasterKey()) { - masterKey = key; - } - } - - if (masterKey != null) { - boolean isFirst = true; - for (String userId : new IterableIterator(masterKey.getUserIDs())) { - if (isFirst) { - // ignore first, it's in the group already - isFirst = false; - continue; - } - children.add(new KeyChild(userId)); - } - } - - return children; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public boolean isChildSelectable(int groupPosition, int childPosition) { - return true; - } - - public int getGroupCount() { - return Apg.getSecretKeyRings().size(); - } - - public Object getChild(int groupPosition, int childPosition) { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition); - Vector children = getChildrenOfKeyRing(keyRing); - KeyChild child = children.get(childPosition); - return child; - } - - public long getChildId(int groupPosition, int childPosition) { - return childPosition; - } - - public int getChildrenCount(int groupPosition) { - return getChildrenOfKeyRing(Apg.getSecretKeyRings().get(groupPosition)).size(); - } - - public Object getGroup(int position) { - return position; - } - - public long getGroupId(int position) { - return position; - } - - public View getGroupView(int groupPosition, boolean isExpanded, - View convertView, ViewGroup parent) { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition); - for (PGPSecretKey key : new IterableIterator(keyRing.getSecretKeys())) { - View view; - if (!key.isMasterKey()) { - continue; - } - view = mInflater.inflate(R.layout.key_list_group_item, null); - view.setBackgroundResource(android.R.drawable.list_selector_background); - - TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); - mainUserId.setText(""); - TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - mainUserIdRest.setText(""); - - String userId = Apg.getMainUserId(key); - if (userId != null) { - String chunks[] = userId.split(" <", 2); - userId = chunks[0]; - if (chunks.length > 1) { - mainUserIdRest.setText("<" + chunks[1]); - } - mainUserId.setText(userId); - } - - if (mainUserId.getText().length() == 0) { - mainUserId.setText(R.string.unknownUserId); - } - - if (mainUserIdRest.getText().length() == 0) { - mainUserIdRest.setVisibility(View.GONE); - } - return view; - } - return null; - } - - public View getChildView(int groupPosition, int childPosition, - boolean isLastChild, View convertView, - ViewGroup parent) { - PGPSecretKeyRing keyRing = Apg.getSecretKeyRings().get(groupPosition); - Vector children = getChildrenOfKeyRing(keyRing); - - KeyChild child = children.get(childPosition); - View view = null; - switch (child.type) { - case KeyChild.KEY: { - PGPSecretKey key = child.key; - if (key.isMasterKey()) { - view = mInflater.inflate(R.layout.key_list_child_item_master_key, null); - } else { - view = mInflater.inflate(R.layout.key_list_child_item_sub_key, null); - } - - TextView keyId = (TextView) view.findViewById(R.id.keyId); - String keyIdStr = Long.toHexString(key.getKeyID() & 0xffffffffL); - while (keyIdStr.length() < 8) { - keyIdStr = "0" + keyIdStr; - } - keyId.setText(keyIdStr); - TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails); - String algorithmStr = Apg.getAlgorithmInfo(key); - keyDetails.setText("(" + algorithmStr + ")"); - - ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey); - if (!Apg.isEncryptionKey(key)) { - encryptIcon.setVisibility(View.GONE); - } - - ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey); - if (!Apg.isSigningKey(key)) { - signIcon.setVisibility(View.GONE); - } - break; - } - - case KeyChild.USER_ID: { - view = mInflater.inflate(R.layout.key_list_child_item_user_id, null); - TextView userId = (TextView) view.findViewById(R.id.userId); - userId.setText(child.userId); - break; - } - } - return view; - } - } } diff --git a/src/org/thialfihar/android/apg/provider/DataProvider.java b/src/org/thialfihar/android/apg/provider/DataProvider.java index 21d6b77c3..ee63d76f4 100644 --- a/src/org/thialfihar/android/apg/provider/DataProvider.java +++ b/src/org/thialfihar/android/apg/provider/DataProvider.java @@ -21,12 +21,10 @@ import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; -import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; diff --git a/src/org/thialfihar/android/apg/provider/Database.java b/src/org/thialfihar/android/apg/provider/Database.java index c77efcaba..716ff99ab 100644 --- a/src/org/thialfihar/android/apg/provider/Database.java +++ b/src/org/thialfihar/android/apg/provider/Database.java @@ -34,9 +34,9 @@ public class Database extends SQLiteOpenHelper { public static final String AUTHORITY = "org.thialfihar.android.apg.database"; - private static HashMap sKeyRingsProjection; - private static HashMap sKeysProjection; - private static HashMap sUserIdsProjection; + public static HashMap sKeyRingsProjection; + public static HashMap sKeysProjection; + public static HashMap sUserIdsProjection; private SQLiteDatabase mCurrentDb = null; @@ -67,11 +67,11 @@ public class Database extends SQLiteOpenHelper { sUserIdsProjection.put(UserIds.RANK, UserIds.RANK); } - Database(Context context) { + public Database(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); //getWritableDatabase(); // force upgrade to test things - onUpgrade(getWritableDatabase(), 1, 2); + //onUpgrade(getWritableDatabase(), 1, 2); } @Override @@ -161,6 +161,7 @@ public class Database extends SQLiteOpenHelper { } } while (cursor.moveToNext()); } + cursor.close(); cursor = db.query(SecretKeys.TABLE_NAME, new String[]{ @@ -182,6 +183,7 @@ public class Database extends SQLiteOpenHelper { } } while (cursor.moveToNext()); } + cursor.close(); break; } @@ -310,6 +312,7 @@ public class Database extends SQLiteOpenHelper { } private long insertOrUpdateKeyRing(ContentValues values) { + boolean grabbedNewDatabase = (mCurrentDb == null); SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); @@ -332,10 +335,17 @@ public class Database extends SQLiteOpenHelper { rowId = db.insert(KeyRings.TABLE_NAME, KeyRings.WHO_ID, values); } + c.close(); + + if (grabbedNewDatabase) { + db.close(); + } + return rowId; } private long insertOrUpdateKey(ContentValues values) { + boolean grabbedNewDatabase = (mCurrentDb == null); SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); @@ -358,10 +368,17 @@ public class Database extends SQLiteOpenHelper { rowId = db.insert(Keys.TABLE_NAME, Keys.KEY_DATA, values); } + c.close(); + + if (grabbedNewDatabase) { + db.close(); + } + return rowId; } private long insertOrUpdateUserId(ContentValues values) { + boolean grabbedNewDatabase = (mCurrentDb == null); SQLiteDatabase db = mCurrentDb != null ? mCurrentDb : getWritableDatabase(); SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); @@ -384,6 +401,12 @@ public class Database extends SQLiteOpenHelper { rowId = db.insert(UserIds.TABLE_NAME, UserIds.USER_ID, values); } + c.close(); + + if (grabbedNewDatabase) { + db.close(); + } + return rowId; } } diff --git a/src/org/thialfihar/android/apg/provider/KeyRings.java b/src/org/thialfihar/android/apg/provider/KeyRings.java index 1e496b3e3..567adaa3c 100644 --- a/src/org/thialfihar/android/apg/provider/KeyRings.java +++ b/src/org/thialfihar/android/apg/provider/KeyRings.java @@ -31,4 +31,14 @@ public class KeyRings implements BaseColumns { 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"; + + public static final Uri CONTENT_URI = + Uri.parse("content://" + DataProvider.AUTHORITY + "/key_ring"); + public static final Uri CONTENT_URI_BY_KEY_ID = + Uri.parse("content://" + DataProvider.AUTHORITY + "/key_ring/key_id"); + public static final String CONTENT_TYPE = + "vnd.android.cursor.dir/vnd.thialfihar.apg.key_ring"; + public static final String CONTENT_ITEM_TYPE = + "vnd.android.cursor.item/vnd.thialfihar.apg.key_ring"; + public static final String DEFAULT_SORT_ORDER = _ID + " DESC"; } diff --git a/src/org/thialfihar/android/apg/provider/Keys.java b/src/org/thialfihar/android/apg/provider/Keys.java index 57ccad6e3..c4c708a01 100644 --- a/src/org/thialfihar/android/apg/provider/Keys.java +++ b/src/org/thialfihar/android/apg/provider/Keys.java @@ -16,6 +16,7 @@ package org.thialfihar.android.apg.provider; +import android.net.Uri; import android.provider.BaseColumns; public class Keys implements BaseColumns { @@ -42,4 +43,12 @@ public class Keys implements BaseColumns { public static final String KEY_DATA_type = "BLOB"; public static final String RANK = "c_key_data"; public static final String RANK_type = "INTEGER"; + + public static final Uri CONTENT_URI = + Uri.parse("content://" + DataProvider.AUTHORITY + "/keys"); + public static final String CONTENT_TYPE = + "vnd.android.cursor.dir/vnd.thialfihar.apg.key"; + public static final String CONTENT_ITEM_TYPE = + "vnd.android.cursor.item/vnd.thialfihar.apg.key"; + public static final String DEFAULT_SORT_ORDER = _ID + " DESC"; } diff --git a/src/org/thialfihar/android/apg/provider/UserIds.java b/src/org/thialfihar/android/apg/provider/UserIds.java index 2b1162beb..3bd1f1668 100644 --- a/src/org/thialfihar/android/apg/provider/UserIds.java +++ b/src/org/thialfihar/android/apg/provider/UserIds.java @@ -16,6 +16,7 @@ package org.thialfihar.android.apg.provider; +import android.net.Uri; import android.provider.BaseColumns; public class UserIds implements BaseColumns { @@ -28,4 +29,14 @@ public class UserIds implements BaseColumns { public static final String USER_ID_type = "TEXT"; public static final String RANK = "c_rank"; public static final String RANK_type = "INTEGER"; + + public static final Uri CONTENT_URI = + Uri.parse("content://" + DataProvider.AUTHORITY + "/user_ids"); + public static final Uri CONTENT_URI_BY_KEY_ID = + Uri.parse("content://" + DataProvider.AUTHORITY + "/user_ids/key_id"); + public static final String CONTENT_TYPE = + "vnd.android.cursor.dir/vnd.thialfihar.apg.user_id"; + public static final String CONTENT_ITEM_TYPE = + "vnd.android.cursor.item/vnd.thialfihar.apg.user_id"; + public static final String DEFAULT_SORT_ORDER = _ID + " DESC"; }