mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-11 03:25:05 -05:00
key lists somewhat wrapped into one, using the new database stuff, Apg cleaned up a bit, preparing to use the database there as well
This commit is contained in:
parent
e83f1e7b3a
commit
6f28f5ee4e
@ -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
|
||||
}
|
||||
}
|
||||
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<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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
633
src/org/thialfihar/android/apg/KeyListActivity.java
Normal file
633
src/org/thialfihar/android/apg/KeyListActivity.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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<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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user