diff options
Diffstat (limited to 'src/org')
-rw-r--r-- | src/org/thialfihar/android/apg/Apg.java | 293 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/AskForSecretKeyPassPhrase.java | 46 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/BaseActivity.java | 11 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/EncryptActivity.java | 4 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/Id.java | 10 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/KeyListActivity.java | 633 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/PublicKeyListActivity.java | 535 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/SecretKeyListActivity.java | 495 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/provider/DataProvider.java | 2 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/provider/Database.java | 33 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/provider/KeyRings.java | 10 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/provider/Keys.java | 9 | ||||
-rw-r--r-- | src/org/thialfihar/android/apg/provider/UserIds.java | 11 |
13 files changed, 773 insertions, 1319 deletions
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<PGPPublicKeyRing> mPublicKeyRings = new Vector<PGPPublicKeyRing>();
- protected static Vector<PGPSecretKeyRing> mSecretKeyRings = new Vector<PGPSecretKeyRing>();
-
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<Long, Integer> mSecretKeyIdToIdMap;
- protected static HashMap<Long, PGPSecretKeyRing> mSecretKeyIdToKeyRingMap;
- protected static HashMap<Long, Integer> mPublicKeyIdToIdMap;
- protected static HashMap<Long, PGPPublicKeyRing> mPublicKeyIdToKeyRingMap;
-
public static final String PUBLIC_KEY_PROJECTION[] =
new String[] {
PublicKeys._ID,
@@ -177,104 +165,6 @@ public class Apg { }
}
- static {
- mPublicKeyRings = new Vector<PGPPublicKeyRing>();
- mSecretKeyRings = new Vector<PGPSecretKeyRing>();
- mSecretKeyIdToIdMap = new HashMap<Long, Integer>();
- mSecretKeyIdToKeyRingMap = new HashMap<Long, PGPSecretKeyRing>();
- mPublicKeyIdToIdMap = new HashMap<Long, Integer>();
- mPublicKeyIdToKeyRingMap = new HashMap<Long, PGPPublicKeyRing>();
- }
-
- 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<PGPPublicKeyRing> {
- @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<PGPSecretKeyRing> {
- @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
- }
- }
- 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 PGPSecretKeyRing getSecretKeyRing(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 PGPPublicKeyRing getPublicKeyRing(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
- }
- }
+ public static PGPSecretKey getSecretKey(long keyId) {
+ // TODO
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<PGPPublicKeyRing> getPublicKeyRings() {
- return mPublicKeyRings;
- }
-
- public static Vector<PGPSecretKeyRing> 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<Long> goodIds = new Vector<Long>(); 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 <thi@thialfihar.org>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.thialfihar.android.apg;
+
+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<Object> keys = new Vector<Object>();
+ // 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<Vector<KeyChild>> 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<Vector<KeyChild>>();
+ 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<KeyChild> getChildrenOfGroup(int groupPosition) {
+ Vector<KeyChild> children = mChildren.get(groupPosition);
+ if (children != null) {
+ return children;
+ }
+
+ mCursor.moveToPosition(groupPosition);
+ children = new Vector<KeyChild>();
+ 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<KeyChild> 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
@@ -80,506 +45,16 @@ public class PublicKeyListActivity extends BaseActivity { }
@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<Object> keys = new Vector<Object>();
- 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<KeyChild> getChildrenOfKeyRing(PGPPublicKeyRing keyRing) {
- Vector<KeyChild> children = new Vector<KeyChild>();
- PGPPublicKey masterKey = null;
- for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(keyRing.getPublicKeys())) {
- children.add(new KeyChild(key));
- if (key.isMasterKey()) {
- masterKey = key;
- }
- }
-
- if (masterKey != null) {
- boolean isFirst = true;
- for (String userId : new IterableIterator<String>(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<KeyChild> 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<PGPPublicKey>(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<KeyChild> 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<Object> keys = new Vector<Object>();
- 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<KeyChild> getChildrenOfKeyRing(PGPSecretKeyRing keyRing) {
- Vector<KeyChild> children = new Vector<KeyChild>();
- PGPSecretKey masterKey = null;
- for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
- children.add(new KeyChild(key));
- if (key.isMasterKey()) {
- masterKey = key;
- }
- }
-
- if (masterKey != null) {
- boolean isFirst = true;
- for (String userId : new IterableIterator<String>(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<KeyChild> 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<PGPSecretKey>(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<KeyChild> 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<String, String> sKeyRingsProjection;
- private static HashMap<String, String> sKeysProjection;
- private static HashMap<String, String> sUserIdsProjection;
+ public static HashMap<String, String> sKeyRingsProjection;
+ public static HashMap<String, String> sKeysProjection;
+ public static HashMap<String, String> 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";
}
|