diff --git a/org_apg/res/layout/import_from_qr_code.xml b/org_apg/res/layout/import_from_qr_code.xml
new file mode 100644
index 000000000..54f4355b3
--- /dev/null
+++ b/org_apg/res/layout/import_from_qr_code.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/org_apg/res/values/strings.xml b/org_apg/res/values/strings.xml
index 25cf6d190..46cb781f7 100644
--- a/org_apg/res/values/strings.xml
+++ b/org_apg/res/values/strings.xml
@@ -34,7 +34,7 @@
Key Server Preference
Change Passphrase
Set Passphrase
- "Send Mail..."
+ "Send Mail…"
Encrypt To File
Decrypt To File
Import Keys
@@ -100,7 +100,7 @@
Key Server
Update
Export To Server
- Share with QR Code
+ Share public key with QR Code
Scan QR Code
Sign Key
@@ -173,10 +173,10 @@
DSA
ElGamal
RSA
- Open...
- Save As...
- Select File To Encrypt...
- Select File To Decrypt...
+ Open…
+ Save As…
+ Select File To Encrypt…
+ Select File To Decrypt…
Open
Save
Warning
@@ -260,41 +260,41 @@
error saving some key(s)
could not extract private key
-
+
done.
- initializing...
- saving...
- importing...
- exporting...
- generating key, this can take a while...
- building key...
- preparing master key...
- certifying master key...
- building master key ring...
- adding sub keys...
- saving key ring...
- importing secret keys...
- importing public keys...
- reloading keys...
- exporting key...
- exporting keys...
- extracting signature key...
- extracting key...
- preparing streams...
- encrypting data...
- decrypting data...
- preparing signature...
- generating signature...
- processing signature...
- verifying signature...
- signing...
- reading data...
- finding key...
- decompressing data...
- verifying integrity...
- deleting \'%s\' securely...
- querying...
- querying %s...
+ initializing…
+ saving…
+ importing…
+ exporting…
+ generating key, this can take a while…
+ building key…
+ preparing master key…
+ certifying master key…
+ building master key ring…
+ adding sub keys…
+ saving key ring…
+ importing secret keys…
+ importing public keys…
+ reloading keys…
+ exporting key…
+ exporting keys…
+ extracting signature key…
+ extracting key…
+ preparing streams…
+ encrypting data…
+ decrypting data…
+ preparing signature…
+ generating signature…
+ processing signature…
+ verifying signature…
+ signing…
+ reading data…
+ finding key…
+ decompressing data…
+ verifying integrity…
+ deleting \'%s\' securely…
+ querying…
+ querying %s…
Read key details from APG.
@@ -316,7 +316,7 @@
slow
very slow
-
+
@@ -333,4 +333,11 @@
About
Version:
+
+
+ Import key (only locally)
+ Import, Sign, and upload key
+ Scan qr code again
+ Finish
+
\ No newline at end of file
diff --git a/org_apg/src/org/thialfihar/android/apg/ApgApplication.java b/org_apg/src/org/thialfihar/android/apg/ApgApplication.java
index 9a77efb74..ba9c9f08d 100644
--- a/org_apg/src/org/thialfihar/android/apg/ApgApplication.java
+++ b/org_apg/src/org/thialfihar/android/apg/ApgApplication.java
@@ -16,6 +16,9 @@
package org.thialfihar.android.apg;
+import java.security.Security;
+
+import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.service.PassphraseCacheService;
@@ -23,6 +26,10 @@ import android.app.Application;
public class ApgApplication extends Application {
+ static {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
@Override
public void onCreate() {
super.onCreate();
diff --git a/org_apg/src/org/thialfihar/android/apg/Id.java b/org_apg/src/org/thialfihar/android/apg/Id.java
index bc40f59e6..4c83437a1 100644
--- a/org_apg/src/org/thialfihar/android/apg/Id.java
+++ b/org_apg/src/org/thialfihar/android/apg/Id.java
@@ -35,7 +35,7 @@ public final class Id {
public static final int edit = 0x21070003;
public static final int update = 0x21070004;
public static final int exportToServer = 0x21070005;
- public static final int share = 0x21070006;
+ public static final int share_qr_code = 0x21070006;
public static final int signKey = 0x21070007;
public static final class option {
diff --git a/org_apg/src/org/thialfihar/android/apg/helper/OtherHelper.java b/org_apg/src/org/thialfihar/android/apg/helper/OtherHelper.java
index 67b4d9c9f..516d7fccb 100644
--- a/org_apg/src/org/thialfihar/android/apg/helper/OtherHelper.java
+++ b/org_apg/src/org/thialfihar/android/apg/helper/OtherHelper.java
@@ -86,22 +86,26 @@ public class OtherHelper {
*/
public static void logDebugBundle(Bundle bundle, String bundleName) {
if (Constants.DEBUG) {
- Set ks = bundle.keySet();
- Iterator iterator = ks.iterator();
+ if (bundle != null) {
+ Set ks = bundle.keySet();
+ Iterator iterator = ks.iterator();
- Log.d(Constants.TAG, "Bundle " + bundleName + ":");
- Log.d(Constants.TAG, "------------------------------");
- while (iterator.hasNext()) {
- String key = iterator.next();
- Object value = bundle.get(key);
+ Log.d(Constants.TAG, "Bundle " + bundleName + ":");
+ Log.d(Constants.TAG, "------------------------------");
+ while (iterator.hasNext()) {
+ String key = iterator.next();
+ Object value = bundle.get(key);
- if (value != null) {
- Log.d(Constants.TAG, key + " : " + value.toString());
- } else {
- Log.d(Constants.TAG, key + " : null");
+ if (value != null) {
+ Log.d(Constants.TAG, key + " : " + value.toString());
+ } else {
+ Log.d(Constants.TAG, key + " : null");
+ }
}
+ Log.d(Constants.TAG, "------------------------------");
+ } else {
+ Log.d(Constants.TAG, "Bundle " + bundleName + ": null");
}
- Log.d(Constants.TAG, "------------------------------");
}
}
}
diff --git a/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java
index 0b6191f67..6d5a07f56 100644
--- a/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java
+++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java
@@ -17,6 +17,7 @@
package org.thialfihar.android.apg.helper;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
@@ -24,6 +25,7 @@ import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Vector;
+import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.PGPKeyRing;
import org.spongycastle.openpgp.PGPObjectFactory;
@@ -34,8 +36,10 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.PGPUtil;
+import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.util.IterableIterator;
+import org.thialfihar.android.apg.util.Log;
import android.content.Context;
@@ -186,7 +190,7 @@ public class PGPHelper {
}
public static PGPPublicKey getEncryptPublicKey(long masterKeyId) {
- //TODO: externalize getSecretKeyRing from PGPWrapper into a DatabaseHelper
+ // TODO: externalize getSecretKeyRing from PGPWrapper into a DatabaseHelper
PGPPublicKeyRing keyRing = PGPMain.getPublicKeyRing(masterKeyId);
if (keyRing == null) {
return null;
@@ -199,7 +203,7 @@ public class PGPHelper {
}
public static PGPSecretKey getSigningKey(long masterKeyId) {
- //TODO: externalize getSecretKeyRing from PGPWrapper into a DatabaseHelper
+ // TODO: externalize getSecretKeyRing from PGPWrapper into a DatabaseHelper
PGPSecretKeyRing keyRing = PGPMain.getSecretKeyRing(masterKeyId);
if (keyRing == null) {
return null;
@@ -380,12 +384,42 @@ public class PGPHelper {
}
+ public static String getPubkeyAsArmoredString(long keyId) {
+ PGPPublicKey key = PGPMain.getPublicKey(keyId);
+ // if it is no public key get it from your own keys...
+ if (key == null) {
+ PGPSecretKey secretKey = PGPMain.getSecretKey(keyId);
+ if (secretKey == null) {
+ Log.e(Constants.TAG, "Key could not be found!");
+ return null;
+ }
+ key = secretKey.getPublicKey();
+ }
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ArmoredOutputStream aos = new ArmoredOutputStream(bos);
+ String armouredKey = null;
+ try {
+ aos.write(key.getEncoded());
+ aos.close();
+
+ armouredKey = bos.toString("UTF-8");
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "Problems while encoding key as armored string", e);
+ }
+
+ Log.d(Constants.TAG, "key:" + armouredKey);
+
+ return armouredKey;
+ }
+
public static String getFingerPrint(long keyId) {
PGPPublicKey key = PGPMain.getPublicKey(keyId);
if (key == null) {
PGPSecretKey secretKey = PGPMain.getSecretKey(keyId);
if (secretKey == null) {
- return "";
+ Log.e(Constants.TAG, "Key could not be found!");
+ return null;
}
key = secretKey.getPublicKey();
}
diff --git a/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java
index 00e9e707d..3fcbeb7a7 100644
--- a/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java
+++ b/org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java
@@ -662,7 +662,7 @@ public class PGPMain {
}
}
- public static Bundle importKeyRings(Activity context, int type, InputData data,
+ public static Bundle importKeyRings(Context context, int type, InputData data,
ProgressDialogUpdater progress) throws GeneralException, FileNotFoundException,
PGPException, IOException {
Bundle returnData = new Bundle();
@@ -733,7 +733,7 @@ public class PGPMain {
return returnData;
}
- public static Bundle exportKeyRings(Activity context, Vector keyRingIds,
+ public static Bundle exportKeyRings(Context context, Vector keyRingIds,
OutputStream outStream, ProgressDialogUpdater progress) throws GeneralException,
FileNotFoundException, PGPException, IOException {
Bundle returnData = new Bundle();
diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java
index b6811d2ee..901097bbc 100644
--- a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java
+++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java
@@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Vector;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPSecretKeyRing;
@@ -66,7 +67,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
/* keys for data bundle */
- // encrypt and decrypt
+ // encrypt, decrypt, import export
public static final String TARGET = "target";
// possible targets:
public static final int TARGET_BYTES = 1;
@@ -91,7 +92,7 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
public static final String RETURN_BYTES = "returnBinary";
public static final String CIPHERTEXT_BYTES = "ciphertextBytes";
public static final String ASSUME_SYMMETRIC = "assumeSymmetric";
- public static final String LOOKUP_UNKNOWN_KEY = "lookup_unknown_key";
+ public static final String LOOKUP_UNKNOWN_KEY = "lookupUnknownKey";
// edit keys
public static final String NEW_PASSPHRASE = "newPassphrase";
@@ -103,13 +104,26 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
// generate key
public static final String ALGORITHM = "algorithm";
- public static final String KEY_SIZE = "key_size";
+ public static final String KEY_SIZE = "keySize";
public static final String SYMMETRIC_PASSPHRASE = "passphrase";
public static final String MASTER_KEY = "masterKey";
// delete file securely
public static final String DELETE_FILE = "deleteFile";
+ // import key
+ public static final String IMPORT_INPUT_STREAM = "importInputStream";
+ public static final String IMPORT_FILENAME = "importFilename";
+ public static final String IMPORT_BYTES = "importBytes";
+ public static final String IMPORT_KEY_TYPE = "importKeyType";
+
+ // export key
+ public static final String EXPORT_OUTPUT_STREAM = "exportOutputStream";
+ public static final String EXPORT_FILENAME = "exportFilename";
+ public static final String EXPORT_KEY_TYPE = "exportKeyType";
+ public static final String EXPORT_ALL = "exportAll";
+ public static final String EXPORT_KEY_RING_ID = "exportKeyRingId";
+
/* possible EXTRA_ACTIONs */
public static final int ACTION_ENCRYPT_SIGN = 10;
@@ -121,6 +135,9 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
public static final int ACTION_DELETE_FILE_SECURELY = 40;
+ public static final int ACTION_IMPORT_KEY = 50;
+ public static final int ACTION_EXPORT_KEY = 51;
+
/* possible data keys as result send over messenger */
// keys
public static final String RESULT_NEW_KEY = "newKey";
@@ -580,6 +597,104 @@ public class ApgService extends IntentService implements ProgressDialogUpdater {
break;
+ case ACTION_IMPORT_KEY:
+ try {
+
+ /* Input */
+ int target = data.getInt(TARGET);
+
+ int keyType = Id.type.public_key;
+ if (data.containsKey(IMPORT_KEY_TYPE)) {
+ keyType = data.getInt(IMPORT_KEY_TYPE);
+ }
+
+ /* Operation */
+ InputStream inStream = null;
+ long inLength = -1;
+ InputData inputData = null;
+ switch (target) {
+ case TARGET_BYTES: /* import key from bytes directly */
+ byte[] bytes = data.getByteArray(IMPORT_BYTES);
+
+ inStream = new ByteArrayInputStream(bytes);
+ inLength = bytes.length;
+
+ inputData = new InputData(inStream, inLength);
+
+ break;
+ case TARGET_FILE: /* import key from file */
+ String inputFile = data.getString(IMPORT_FILENAME);
+
+ inStream = new FileInputStream(inputFile);
+ File file = new File(inputFile);
+ inLength = file.length();
+ inputData = new InputData(inStream, inLength);
+
+ break;
+
+ case TARGET_STREAM:
+ // TODO: not implemented
+ break;
+ }
+
+ Bundle resultData = new Bundle();
+ resultData = PGPMain.importKeyRings(this, keyType, inputData, this);
+
+ sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData);
+ } catch (Exception e) {
+ sendErrorToHandler(e);
+ }
+
+ break;
+
+ case ACTION_EXPORT_KEY:
+ try {
+
+ /* Input */
+ int keyType = Id.type.public_key;
+ if (data.containsKey(EXPORT_KEY_TYPE)) {
+ keyType = data.getInt(EXPORT_KEY_TYPE);
+ }
+
+ String outputFile = data.getString(EXPORT_FILENAME);
+
+ boolean exportAll = data.getBoolean(EXPORT_ALL);
+ int keyRingId = -1;
+ if (!exportAll) {
+ keyRingId = data.getInt(EXPORT_KEY_RING_ID);
+ }
+
+ /* Operation */
+
+ // check if storage is ready
+ if (!FileHelper.isStorageMounted(outputFile)) {
+ sendErrorToHandler(new GeneralException(
+ getString(R.string.error_externalStorageNotReady)));
+ return;
+ }
+
+ // OutputStream
+ FileOutputStream outStream = new FileOutputStream(outputFile);
+
+ Vector keyRingIds = new Vector();
+ if (exportAll) {
+ keyRingIds = PGPMain
+ .getKeyRingIds(keyType == Id.type.public_key ? Id.database.type_public
+ : Id.database.type_secret);
+ } else {
+ keyRingIds.add(keyRingId);
+ }
+
+ Bundle resultData = new Bundle();
+ resultData = PGPMain.exportKeyRings(this, keyRingIds, outStream, this);
+
+ sendMessageToHandler(ApgHandler.MESSAGE_OKAY, resultData);
+ } catch (Exception e) {
+ sendErrorToHandler(e);
+ }
+
+ break;
+
default:
break;
}
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java
index ee6ad5af8..53b0ed029 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java
@@ -693,7 +693,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
private void decryptStart() {
Log.d(Constants.TAG, "decryptStart");
- // Send all information needed to service to edit key in other thread
+ // Send all information needed to service to decrypt in other thread
Intent intent = new Intent(this, ApgService.class);
// fill values for this action
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java
index 5d70e6924..0b751f66c 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java
@@ -33,6 +33,8 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import org.thialfihar.android.apg.util.Log;
+
+import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
@@ -61,86 +63,98 @@ public class ImportFromQRCodeActivity extends BaseActivity {
new IntentIntegrator(this).initiateScan();
}
+ // private void importAndSignOld(final long keyId, final String expectedFingerprint) {
+ // if (expectedFingerprint != null && expectedFingerprint.length() > 0) {
+ //
+ // Thread t = new Thread() {
+ // @Override
+ // public void run() {
+ // try {
+ // // TODO: display some sort of spinner here while the user waits
+ //
+ // // TODO: there should be only 1
+ // HkpKeyServer server = new HkpKeyServer(mPreferences.getKeyServers()[0]);
+ // String encodedKey = server.get(keyId);
+ //
+ // PGPKeyRing keyring = PGPHelper.decodeKeyRing(new ByteArrayInputStream(
+ // encodedKey.getBytes()));
+ // if (keyring != null && keyring instanceof PGPPublicKeyRing) {
+ // PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring;
+ //
+ // // make sure the fingerprints match before we cache this thing
+ // String actualFingerprint = PGPHelper.convertToHex(publicKeyRing
+ // .getPublicKey().getFingerprint());
+ // if (expectedFingerprint.equals(actualFingerprint)) {
+ // // store the signed key in our local cache
+ // int retval = PGPMain.storeKeyRingInCache(publicKeyRing);
+ // if (retval != Id.return_value.ok
+ // && retval != Id.return_value.updated) {
+ // status.putString(EXTRA_ERROR,
+ // "Failed to store signed key in local cache");
+ // } else {
+ // Intent intent = new Intent(ImportFromQRCodeActivity.this,
+ // SignKeyActivity.class);
+ // intent.putExtra(EXTRA_KEY_ID, keyId);
+ // startActivityForResult(intent, Id.request.sign_key);
+ // }
+ // } else {
+ // status.putString(
+ // EXTRA_ERROR,
+ // "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key.");
+ // }
+ // }
+ // } catch (QueryException e) {
+ // Log.e(TAG, "Failed to query KeyServer", e);
+ // status.putString(EXTRA_ERROR, "Failed to query KeyServer");
+ // status.putInt(Constants.extras.STATUS, Id.message.done);
+ // } catch (IOException e) {
+ // Log.e(TAG, "Failed to query KeyServer", e);
+ // status.putString(EXTRA_ERROR, "Failed to query KeyServer");
+ // status.putInt(Constants.extras.STATUS, Id.message.done);
+ // }
+ // }
+ // };
+ //
+ // t.setName("KeyExchange Download Thread");
+ // t.setDaemon(true);
+ // t.start();
+ // }
+ // }
+
private void importAndSign(final long keyId, final String expectedFingerprint) {
- if (expectedFingerprint != null && expectedFingerprint.length() > 0) {
- Thread t = new Thread() {
- @Override
- public void run() {
- try {
- // TODO: display some sort of spinner here while the user waits
+ // setContentView(R.layout.import_from_qr_code);
- // TODO: there should be only 1
- HkpKeyServer server = new HkpKeyServer(mPreferences.getKeyServers()[0]);
- String encodedKey = server.get(keyId);
-
- PGPKeyRing keyring = PGPHelper.decodeKeyRing(new ByteArrayInputStream(
- encodedKey.getBytes()));
- if (keyring != null && keyring instanceof PGPPublicKeyRing) {
- PGPPublicKeyRing publicKeyRing = (PGPPublicKeyRing) keyring;
-
- // make sure the fingerprints match before we cache this thing
- String actualFingerprint = PGPHelper.convertToHex(publicKeyRing
- .getPublicKey().getFingerprint());
- if (expectedFingerprint.equals(actualFingerprint)) {
- // store the signed key in our local cache
- int retval = PGPMain.storeKeyRingInCache(publicKeyRing);
- if (retval != Id.return_value.ok
- && retval != Id.return_value.updated) {
- status.putString(EXTRA_ERROR,
- "Failed to store signed key in local cache");
- } else {
- Intent intent = new Intent(ImportFromQRCodeActivity.this,
- SignKeyActivity.class);
- intent.putExtra(EXTRA_KEY_ID, keyId);
- startActivityForResult(intent, Id.request.sign_key);
- }
- } else {
- status.putString(
- EXTRA_ERROR,
- "Scanned fingerprint does NOT match the fingerprint of the received key. You shouldnt trust this key.");
- }
- }
- } catch (QueryException e) {
- Log.e(TAG, "Failed to query KeyServer", e);
- status.putString(EXTRA_ERROR, "Failed to query KeyServer");
- status.putInt(Constants.extras.STATUS, Id.message.done);
- } catch (IOException e) {
- Log.e(TAG, "Failed to query KeyServer", e);
- status.putString(EXTRA_ERROR, "Failed to query KeyServer");
- status.putInt(Constants.extras.STATUS, Id.message.done);
- }
- }
- };
-
- t.setName("KeyExchange Download Thread");
- t.setDaemon(true);
- t.start();
- }
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case IntentIntegrator.REQUEST_CODE: {
- boolean debug = true; // TODO: remove this!!!
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode,
data);
- if (debug || (scanResult != null && scanResult.getFormatName() != null)) {
- String[] bits = debug ? new String[] { "5993515643896327656",
- "0816 F68A 6816 68FB 01BF 2CA5 532D 3EB9 1E2F EDE8" } : scanResult
- .getContents().split(",");
- if (bits.length != 2) {
- return; // dont know how to handle this. Not a valid code
- }
+ if (scanResult != null && scanResult.getFormatName() != null) {
- long keyId = Long.parseLong(bits[0]);
- String expectedFingerprint = bits[1];
+ // show layout
+ setContentView(R.layout.import_from_qr_code);
+ TextView contentView = (TextView) findViewById(R.id.import_from_qr_code_content);
- importAndSign(keyId, expectedFingerprint);
+ String content = scanResult.getContents();
+
+ contentView.setText(content);
+ // String[] bits = scanResult.getContents().split(",");
+ // if (bits.length != 2) {
+ // return; // dont know how to handle this. Not a valid code
+ // }
+ //
+ // long keyId = Long.parseLong(bits[0]);
+ // String expectedFingerprint = bits[1];
+
+ // importAndSign(keyId, expectedFingerprint);
- break;
}
+
+ break;
}
case Id.request.sign_key: {
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java
index 97449d316..1d41ab696 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java
@@ -16,9 +16,6 @@
package org.thialfihar.android.apg.ui;
-import org.spongycastle.openpgp.PGPException;
-import org.spongycastle.openpgp.PGPPublicKeyRing;
-import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.helper.PGPHelper;
@@ -26,14 +23,19 @@ import org.thialfihar.android.apg.helper.PGPMain;
import org.thialfihar.android.apg.provider.KeyRings;
import org.thialfihar.android.apg.provider.Keys;
import org.thialfihar.android.apg.provider.UserIds;
+import org.thialfihar.android.apg.service.ApgHandler;
+import org.thialfihar.android.apg.service.ApgService;
+import org.thialfihar.android.apg.ui.dialog.DeleteFileDialogFragment;
+import org.thialfihar.android.apg.ui.dialog.DeleteKeyDialogFragment;
import org.thialfihar.android.apg.ui.dialog.FileDialogFragment;
-import org.thialfihar.android.apg.util.InputData;
+import org.thialfihar.android.apg.ui.dialog.ProgressDialogFragment;
import org.thialfihar.android.apg.R;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import android.app.AlertDialog;
-import android.app.Dialog;
+import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface;
@@ -59,25 +61,14 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.util.Vector;
-public class KeyListActivity extends BaseActivity {
+public class KeyListActivity extends SherlockFragmentActivity {
public static final String ACTION_IMPORT = Constants.INTENT_PREFIX + "IMPORT";
public static final String EXTRA_TEXT = "text";
- // TODO: remove when using new intentservice:
- public static final String EXTRA_ERROR = "error";
-
protected ExpandableListView mList;
protected KeyListAdapter mListAdapter;
protected View mFilterLayout;
@@ -251,7 +242,7 @@ public class KeyListActivity extends BaseActivity {
case Id.menu.delete: {
mSelectedItem = groupPosition;
- showDialog(Id.dialog.delete_key);
+ showDeleteKeyDialog();
return true;
}
@@ -261,177 +252,87 @@ public class KeyListActivity extends BaseActivity {
}
}
- @Override
- protected Dialog onCreateDialog(int id) {
+ private void showDeleteKeyDialog() {
+ final int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
+ mSelectedItem = -1;
- switch (id) {
- case Id.dialog.delete_key: {
- final int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
- mSelectedItem = -1;
- // TODO: better way to do this?
- String userId = "";
- Object keyRing = PGPMain.getKeyRing(keyRingId);
- if (keyRing != null) {
- if (keyRing instanceof PGPPublicKeyRing) {
- userId = PGPHelper.getMainUserIdSafe(this,
- PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing));
- } else {
- userId = PGPHelper.getMainUserIdSafe(this,
- PGPHelper.getMasterKey((PGPSecretKeyRing) keyRing));
+ // Message is received after key is deleted
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
+ refreshList();
}
}
+ };
- 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(keyRingId);
- 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();
- }
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
- default: {
- return super.onCreateDialog(id);
- }
- }
+ DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
+ keyRingId, mKeyType);
+
+ deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
}
public void importKeys() {
- showDialog(Id.dialog.importing);
- mTask = Id.task.import_keys;
- startThread();
- }
+ Log.d(Constants.TAG, "importKeys started");
- public void exportKeys() {
- showDialog(Id.dialog.exporting);
- mTask = Id.task.export_keys;
- startThread();
- }
+ // Send all information needed to service to import key in other thread
+ Intent intent = new Intent(this, ApgService.class);
- @Override
- public void run() {
- String error = null;
+ intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_IMPORT_KEY);
+
+ // fill values for this action
Bundle data = new Bundle();
- Message msg = new Message();
- try {
- InputStream importInputStream = null;
- OutputStream exportOutputStream = null;
- long size = 0;
- if (mTask == Id.task.import_keys) {
- if (mImportData != null) {
- byte[] bytes = mImportData.getBytes();
- size = bytes.length;
- importInputStream = new ByteArrayInputStream(bytes);
- } else {
- File file = new File(mImportFilename);
- size = file.length();
- importInputStream = new FileInputStream(file);
- }
- } else {
- exportOutputStream = new FileOutputStream(mExportFilename);
- }
+ data.putInt(ApgService.IMPORT_KEY_TYPE, mKeyType);
- if (mTask == Id.task.import_keys) {
- data = PGPMain.importKeyRings(this, mKeyType, new InputData(importInputStream,
- size), this);
- } else {
- Vector keyRingIds = new Vector();
- if (mSelectedItem == -1) {
- keyRingIds = PGPMain
- .getKeyRingIds(mKeyType == Id.type.public_key ? Id.database.type_public
- : Id.database.type_secret);
- } else {
- int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
- keyRingIds.add(keyRingId);
- mSelectedItem = -1;
- }
- data = PGPMain.exportKeyRings(this, keyRingIds, exportOutputStream, this);
- }
- } catch (FileNotFoundException e) {
- error = getString(R.string.error_fileNotFound);
- } catch (IOException e) {
- error = "" + e;
- } catch (PGPException e) {
- error = "" + e;
- } catch (PGPMain.GeneralException e) {
- error = "" + e;
- }
-
- mImportData = null;
-
- if (mTask == Id.task.import_keys) {
- data.putInt(Constants.extras.STATUS, Id.message.import_done);
+ if (mImportData != null) {
+ data.putInt(ApgService.TARGET, ApgService.TARGET_BYTES);
+ data.putByteArray(ApgService.IMPORT_BYTES, mImportData.getBytes());
} else {
- data.putInt(Constants.extras.STATUS, Id.message.export_done);
+ data.putInt(ApgService.TARGET, ApgService.TARGET_FILE);
+ data.putString(ApgService.IMPORT_FILENAME, mImportFilename);
}
- if (error != null) {
- data.putString(EXTRA_ERROR, error);
- }
+ intent.putExtra(ApgService.EXTRA_DATA, data);
- msg.setData(data);
- sendMessage(msg);
- }
+ // create progress dialog
+ ProgressDialogFragment importingDialog = ProgressDialogFragment.newInstance(
+ R.string.progress_importing, ProgressDialog.STYLE_HORIZONTAL);
- protected void deleteKey(int keyRingId) {
- PGPMain.deleteKey(keyRingId);
- refreshList();
- }
+ // Message is received after importing is done in ApgService
+ ApgHandler saveHandler = new ApgHandler(this, importingDialog) {
+ public void handleMessage(Message message) {
+ // handle messages by standard ApgHandler first
+ super.handleMessage(message);
- protected void refreshList() {
- mListAdapter.rebuild(true);
- mListAdapter.notifyDataSetChanged();
- }
+ if (message.arg1 == ApgHandler.MESSAGE_OKAY) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
- @Override
- public void doneCallback(Message msg) {
- super.doneCallback(msg);
-
- Bundle data = msg.getData();
- if (data != null) {
- int type = data.getInt(Constants.extras.STATUS);
- switch (type) {
- case Id.message.import_done: {
- removeDialog(Id.dialog.importing);
-
- String error = data.getString(EXTRA_ERROR);
- if (error != null) {
- Toast.makeText(KeyListActivity.this, getString(R.string.errorMessage, error),
- Toast.LENGTH_SHORT).show();
- } else {
- int added = data.getInt("added");
- int updated = data.getInt("updated");
- int bad = data.getInt("bad");
- String message;
+ int added = returnData.getInt("added");
+ int updated = returnData.getInt("updated");
+ int bad = returnData.getInt("bad");
+ String toastMessage;
if (added > 0 && updated > 0) {
- message = getString(R.string.keysAddedAndUpdated, added, updated);
+ toastMessage = getString(R.string.keysAddedAndUpdated, added, updated);
} else if (added > 0) {
- message = getString(R.string.keysAdded, added);
+ toastMessage = getString(R.string.keysAdded, added);
} else if (updated > 0) {
- message = getString(R.string.keysUpdated, updated);
+ toastMessage = getString(R.string.keysUpdated, updated);
} else {
- message = getString(R.string.noKeysAddedOrUpdated);
+ toastMessage = getString(R.string.noKeysAddedOrUpdated);
}
- Toast.makeText(KeyListActivity.this, message, Toast.LENGTH_SHORT).show();
+ Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
if (bad > 0) {
- AlertDialog.Builder alert = new AlertDialog.Builder(this);
+ AlertDialog.Builder alert = new AlertDialog.Builder(KeyListActivity.this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle(R.string.warning);
- alert.setMessage(this.getString(R.string.badKeysEncountered, bad));
+ alert.setMessage(KeyListActivity.this.getString(
+ R.string.badKeysEncountered, bad));
alert.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@@ -443,41 +344,94 @@ public class KeyListActivity extends BaseActivity {
alert.create().show();
} else if (mDeleteAfterImport) {
// everything went well, so now delete, if that was turned on
- setDeleteFile(mImportFilename);
- showDialog(Id.dialog.delete_file);
+ DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment
+ .newInstance(mImportFilename);
+ deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog");
}
+ refreshList();
+
}
- refreshList();
- break;
- }
+ };
+ };
- case Id.message.export_done: {
- removeDialog(Id.dialog.exporting);
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(saveHandler);
+ intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
- String error = data.getString(EXTRA_ERROR);
- if (error != null) {
- Toast.makeText(KeyListActivity.this, getString(R.string.errorMessage, 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, exported);
- } else {
- message = getString(R.string.noKeysExported);
- }
- Toast.makeText(KeyListActivity.this, message, Toast.LENGTH_SHORT).show();
- }
- break;
- }
+ // show progress dialog
+ importingDialog.show(getSupportFragmentManager(), "importingDialog");
- default: {
- break;
- }
- }
+ // start service with intent
+ startService(intent);
+ }
+
+ public void exportKeys() {
+ Log.d(Constants.TAG, "exportKeys started");
+
+ // Send all information needed to service to export key in other thread
+ Intent intent = new Intent(this, ApgService.class);
+
+ intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_EXPORT_KEY);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ data.putString(ApgService.EXPORT_FILENAME, mExportFilename);
+ data.putInt(ApgService.EXPORT_KEY_TYPE, mKeyType);
+
+ if (mSelectedItem == -1) {
+ data.putBoolean(ApgService.EXPORT_ALL, true);
+ } else {
+ int keyRingId = mListAdapter.getKeyRingId(mSelectedItem);
+ data.putInt(ApgService.EXPORT_KEY_RING_ID, keyRingId);
+ mSelectedItem = -1;
}
+
+ intent.putExtra(ApgService.EXTRA_DATA, data);
+
+ // create progress dialog
+ ProgressDialogFragment exportingDialog = ProgressDialogFragment.newInstance(
+ R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL);
+
+ // Message is received after exporting is done in ApgService
+ ApgHandler exportHandler = new ApgHandler(this, exportingDialog) {
+ public void handleMessage(Message message) {
+ // handle messages by standard ApgHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == ApgHandler.MESSAGE_OKAY) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+
+ int exported = returnData.getInt("exported");
+ String toastMessage;
+ if (exported == 1) {
+ toastMessage = getString(R.string.keyExported);
+ } else if (exported > 0) {
+ toastMessage = getString(R.string.keysExported, exported);
+ } else {
+ toastMessage = getString(R.string.noKeysExported);
+ }
+ Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
+
+ }
+ };
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(exportHandler);
+ intent.putExtra(ApgService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ exportingDialog.show(getSupportFragmentManager(), "exportingDialog");
+
+ // start service with intent
+ startService(intent);
+ }
+
+ protected void refreshList() {
+ mListAdapter.rebuild(true);
+ mListAdapter.notifyDataSetChanged();
}
protected class KeyListAdapter extends BaseExpandableListAdapter {
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java
deleted file mode 100644
index 85d9d6ce5..000000000
--- a/org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2010 Thialfihar
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.thialfihar.android.apg.ui;
-
-import java.util.Vector;
-import java.util.regex.Matcher;
-
-import org.thialfihar.android.apg.R;
-import org.thialfihar.android.apg.helper.PGPMain;
-import org.thialfihar.android.apg.helper.Preferences;
-
-import android.app.ListActivity;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.text.Html;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.BaseAdapter;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.TextView;
-
-public class MailListActivity extends ListActivity {
- LayoutInflater mInflater = null;
-
- public static final String EXTRA_ACCOUNT = "account";
-
- private static class Conversation {
- public long id;
- public String subject;
- public Vector messages;
-
- public Conversation(long id, String subject) {
- this.id = id;
- this.subject = subject;
- }
- }
-
- private static class Message {
- public Conversation parent;
- public long id;
- public String subject;
- public String fromAddress;
- public String data;
- public String replyTo;
- public boolean signedOnly;
-
- public Message(Conversation parent, long id, String subject, String fromAddress,
- String replyTo, String data, boolean signedOnly) {
- this.parent = parent;
- this.id = id;
- this.subject = subject;
- this.fromAddress = fromAddress;
- this.replyTo = replyTo;
- this.data = data;
- if (this.replyTo == null || this.replyTo.equals("")) {
- this.replyTo = this.fromAddress;
- }
- this.signedOnly = signedOnly;
- }
- }
-
- private Vector mConversations;
- private Vector mMessages;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- Preferences prefs = Preferences.getPreferences(this);
-
- super.onCreate(savedInstanceState);
-
- mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- mConversations = new Vector();
- mMessages = new Vector();
-
- String account = getIntent().getExtras().getString(EXTRA_ACCOUNT);
- // TODO: what if account is null?
- Uri uri = Uri.parse("content://gmail-ls/conversations/" + account);
- Cursor cursor = managedQuery(uri, new String[] { "conversation_id", "subject" }, null,
- null, null);
- for (int i = 0; i < cursor.getCount(); ++i) {
- cursor.moveToPosition(i);
-
- int idIndex = cursor.getColumnIndex("conversation_id");
- int subjectIndex = cursor.getColumnIndex("subject");
- long conversationId = cursor.getLong(idIndex);
- Conversation conversation = new Conversation(conversationId,
- cursor.getString(subjectIndex));
- Uri messageUri = Uri.withAppendedPath(uri, "" + conversationId + "/messages");
- Cursor messageCursor = managedQuery(messageUri, new String[] { "messageId", "subject",
- "fromAddress", "replyToAddresses", "body" }, null, null, null);
- Vector messages = new Vector();
- for (int j = 0; j < messageCursor.getCount(); ++j) {
- messageCursor.moveToPosition(j);
- idIndex = messageCursor.getColumnIndex("messageId");
- subjectIndex = messageCursor.getColumnIndex("subject");
- int fromAddressIndex = messageCursor.getColumnIndex("fromAddress");
- int replyToIndex = messageCursor.getColumnIndex("replyToAddresses");
- int bodyIndex = messageCursor.getColumnIndex("body");
- String data = messageCursor.getString(bodyIndex);
- data = Html.fromHtml(data).toString();
- boolean signedOnly = false;
- Matcher matcher = PGPMain.PGP_MESSAGE.matcher(data);
- if (matcher.matches()) {
- data = matcher.group(1);
- } else {
- matcher = PGPMain.PGP_SIGNED_MESSAGE.matcher(data);
- if (matcher.matches()) {
- data = matcher.group(1);
- signedOnly = true;
- } else {
- data = null;
- }
- }
- Message message = new Message(conversation, messageCursor.getLong(idIndex),
- messageCursor.getString(subjectIndex),
- messageCursor.getString(fromAddressIndex),
- messageCursor.getString(replyToIndex), data, signedOnly);
-
- messages.add(message);
- mMessages.add(message);
- }
- conversation.messages = messages;
- mConversations.add(conversation);
- }
-
- setListAdapter(new MailboxAdapter());
- getListView().setOnItemClickListener(new OnItemClickListener() {
- public void onItemClick(AdapterView> arg0, View v, int position, long id) {
- Intent intent = new Intent(MailListActivity.this, DecryptActivity.class);
- intent.setAction(DecryptActivity.ACTION_DECRYPT);
- Message message = (Message) ((MailboxAdapter) getListAdapter()).getItem(position);
- intent.putExtra(DecryptActivity.EXTRA_TEXT, message.data);
- intent.putExtra(DecryptActivity.EXTRA_SUBJECT, message.subject);
- intent.putExtra(DecryptActivity.EXTRA_REPLY_TO, message.replyTo);
- startActivity(intent);
- }
- });
- }
-
- private class MailboxAdapter extends BaseAdapter implements ListAdapter {
-
- @Override
- public boolean isEnabled(int position) {
- Message message = (Message) getItem(position);
- return message.data != null;
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- public int getCount() {
- return mMessages.size();
- }
-
- public Object getItem(int position) {
- return mMessages.get(position);
- }
-
- public long getItemId(int position) {
- return mMessages.get(position).id;
- }
-
- public View getView(int position, View convertView, ViewGroup parent) {
- View view = mInflater.inflate(R.layout.mailbox_message_item, null);
-
- Message message = (Message) getItem(position);
-
- TextView subject = (TextView) view.findViewById(R.id.subject);
- TextView email = (TextView) view.findViewById(R.id.emailAddress);
- ImageView status = (ImageView) view.findViewById(R.id.ic_status);
-
- subject.setText(message.subject);
- email.setText(message.fromAddress);
- if (message.data != null) {
- if (message.signedOnly) {
- status.setImageResource(R.drawable.signed);
- } else {
- status.setImageResource(R.drawable.encrypted);
- }
- status.setVisibility(View.VISIBLE);
- } else {
- status.setVisibility(View.INVISIBLE);
- }
-
- return view;
- }
- }
-}
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java
index dafc2924b..26387f870 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java
@@ -17,9 +17,6 @@
package org.thialfihar.android.apg.ui;
-import java.security.Security;
-
-import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.thialfihar.android.apg.Id;
import org.thialfihar.android.apg.R;
@@ -33,9 +30,6 @@ import android.os.Bundle;
import android.view.View;
public class MainActivity extends SherlockActivity {
- static {
- Security.addProvider(new BouncyCastleProvider());
- }
public void manageKeysOnClick(View view) {
startActivity(new Intent(this, PublicKeyListActivity.class));
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java
index 2d5108cad..0ba476768 100644
--- a/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java
+++ b/org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java
@@ -19,16 +19,19 @@ package org.thialfihar.android.apg.ui;
import org.thialfihar.android.apg.R;
import org.thialfihar.android.apg.Constants;
import org.thialfihar.android.apg.Id;
-import org.thialfihar.android.apg.deprecated.AskForPassphrase;
import org.thialfihar.android.apg.helper.PGPHelper;
import org.thialfihar.android.apg.helper.PGPMain;
+import org.thialfihar.android.apg.ui.dialog.PassphraseDialogFragment;
+import org.thialfihar.android.apg.util.Log;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
-import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
@@ -39,6 +42,7 @@ import android.widget.ExpandableListView.OnChildClickListener;
import com.google.zxing.integration.android.IntentIntegrator;
public class SecretKeyListActivity extends KeyListActivity implements OnChildClickListener {
+
@Override
public void onCreate(Bundle savedInstanceState) {
mExportFilename = Constants.path.APP_DIR + "/secexport.asc";
@@ -86,7 +90,7 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
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);
- menu.add(0, Id.menu.share, 2, R.string.menu_share);
+ menu.add(0, Id.menu.share_qr_code, 2, R.string.menu_share);
}
}
@@ -107,12 +111,13 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
return true;
}
- case Id.menu.share: {
+ case Id.menu.share_qr_code: {
mSelectedItem = groupPosition;
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter())
.getGroupId(mSelectedItem);
- String msg = keyId + "," + PGPHelper.getFingerPrint(keyId);
+ // String msg = keyId + "," + PGPHelper.getFingerPrint(keyId);
+ String msg = PGPHelper.getPubkeyAsArmoredString(keyId);
new IntentIntegrator(this).shareText(msg);
}
@@ -130,37 +135,43 @@ public class SecretKeyListActivity extends KeyListActivity implements OnChildCli
return true;
}
- @Override
- protected Dialog onCreateDialog(int id) {
- switch (id) {
- case Id.dialog.pass_phrase: {
- long keyId = ((KeyListAdapter) mList.getExpandableListAdapter())
- .getGroupId(mSelectedItem);
- return AskForPassphrase.createDialog(this, keyId, this);
- }
-
- default: {
- return super.onCreateDialog(id);
- }
- }
- }
-
public void checkPassPhraseAndEdit() {
long keyId = ((KeyListAdapter) mList.getExpandableListAdapter()).getGroupId(mSelectedItem);
String passPhrase = PGPMain.getCachedPassPhrase(keyId);
if (passPhrase == null) {
- showDialog(Id.dialog.pass_phrase);
+ showPassphraseDialog(keyId);
} else {
PGPMain.setEditPassPhrase(passPhrase);
editKey();
}
}
- @Override
- public void passPhraseCallback(long keyId, String passPhrase) {
- super.passPhraseCallback(keyId, passPhrase);
- PGPMain.setEditPassPhrase(passPhrase);
- editKey();
+ private void showPassphraseDialog(final long secretKeyId) {
+ // Message is received after passphrase is cached
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
+ String passPhrase = PGPMain.getCachedPassPhrase(secretKeyId);
+ PGPMain.setEditPassPhrase(passPhrase);
+ editKey();
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(returnHandler);
+
+ try {
+ PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(
+ messenger, secretKeyId);
+
+ passphraseDialog.show(getSupportFragmentManager(), "passphraseDialog");
+ } catch (PGPMain.GeneralException e) {
+ Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!");
+ // send message to handler to start encryption directly
+ returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY);
+ }
}
private void createKey() {
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/DeleteKeyDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/DeleteKeyDialogFragment.java
new file mode 100644
index 000000000..4cb1cd02f
--- /dev/null
+++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/DeleteKeyDialogFragment.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * 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.ui.dialog;
+
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.thialfihar.android.apg.Constants;
+import org.thialfihar.android.apg.Id;
+import org.thialfihar.android.apg.R;
+import org.thialfihar.android.apg.helper.PGPHelper;
+import org.thialfihar.android.apg.helper.PGPMain;
+import org.thialfihar.android.apg.util.Log;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+
+public class DeleteKeyDialogFragment extends DialogFragment {
+
+ private Messenger mMessenger;
+
+ private static final String ARG_MESSENGER = "messenger";
+ private static final String ARG_DELETE_KEY_RING_ID = "delete_file";
+ private static final String ARG_KEY_TYPE = "key_type";
+
+ public static final int MESSAGE_OKAY = 1;
+
+ /**
+ * Creates new instance of this delete file dialog fragment
+ */
+ public static DeleteKeyDialogFragment newInstance(Messenger messenger, int deleteKeyRingId,
+ int keyType) {
+ DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment();
+ Bundle args = new Bundle();
+
+ args.putParcelable(ARG_MESSENGER, messenger);
+ args.putInt(ARG_DELETE_KEY_RING_ID, deleteKeyRingId);
+ args.putInt(ARG_KEY_TYPE, keyType);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ /**
+ * Creates dialog
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final FragmentActivity activity = getActivity();
+
+ final int deleteKeyRingId = getArguments().getInt(ARG_DELETE_KEY_RING_ID);
+ final int keyType = getArguments().getInt(ARG_KEY_TYPE);
+
+ // TODO: better way to do this?
+ String userId = "";
+ Object keyRing = PGPMain.getKeyRing(deleteKeyRingId);
+ if (keyRing != null) {
+ if (keyRing instanceof PGPPublicKeyRing) {
+ userId = PGPHelper.getMainUserIdSafe(activity,
+ PGPHelper.getMasterKey((PGPPublicKeyRing) keyRing));
+ } else {
+ userId = PGPHelper.getMainUserIdSafe(activity,
+ PGPHelper.getMasterKey((PGPSecretKeyRing) keyRing));
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(R.string.warning);
+ builder.setMessage(getString(
+ keyType == 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(deleteKeyRingId);
+ PGPMain.deleteKey(deleteKeyRingId);
+
+ dismiss();
+
+ sendMessageToHandler(MESSAGE_OKAY);
+ }
+ });
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+ }
+ });
+ return builder.create();
+ }
+
+ /**
+ * Send message back to handler which is initialized in a activity
+ *
+ * @param what
+ * Message integer you want to send
+ */
+ private void sendMessageToHandler(Integer what) {
+ Message msg = Message.obtain();
+ msg.what = what;
+
+ try {
+ mMessenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/org_apg/src/org/thialfihar/android/apg/ui/dialog/LookupUnknownKeyDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/dialog/LookupUnknownKeyDialogFragment.java
new file mode 100644
index 000000000..9797abc2a
--- /dev/null
+++ b/org_apg/src/org/thialfihar/android/apg/ui/dialog/LookupUnknownKeyDialogFragment.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2012 Dominik Schürmann
+ *
+ * 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.ui.dialog;
+
+import org.thialfihar.android.apg.helper.PGPHelper;
+import org.thialfihar.android.apg.Constants;
+import org.thialfihar.android.apg.Id;
+import org.thialfihar.android.apg.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.support.v4.app.DialogFragment;
+
+import org.thialfihar.android.apg.ui.KeyServerQueryActivity;
+import org.thialfihar.android.apg.util.Log;
+
+public class LookupUnknownKeyDialogFragment extends DialogFragment {
+
+ private Messenger mMessenger;
+
+ private static final String ARG_MESSENGER = "messenger";
+ private static final String ARG_UNKNOWN_KEY_ID = "unknown_key_id";
+
+ public static final int MESSAGE_OKAY = 1;
+ public static final int MESSAGE_CANCEL = 2;
+
+ /**
+ * Creates new instance of this dialog fragment
+ *
+ * @param messenger
+ * @param unknownKeyId
+ * @return
+ */
+ public static LookupUnknownKeyDialogFragment newInstance(Messenger messenger, long unknownKeyId) {
+ LookupUnknownKeyDialogFragment frag = new LookupUnknownKeyDialogFragment();
+ Bundle args = new Bundle();
+ args.putLong(ARG_UNKNOWN_KEY_ID, unknownKeyId);
+ args.putParcelable(ARG_MESSENGER, messenger);
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ /**
+ * Creates dialog
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Activity activity = getActivity();
+
+ final long unknownKeyId = getArguments().getLong(ARG_UNKNOWN_KEY_ID);
+ mMessenger = getArguments().getParcelable(ARG_MESSENGER);
+
+ AlertDialog.Builder alert = new AlertDialog.Builder(activity);
+
+ alert.setIcon(android.R.drawable.ic_dialog_alert);
+ alert.setTitle(R.string.title_unknownSignatureKey);
+ alert.setMessage(getString(R.string.lookupUnknownKey,
+ PGPHelper.getSmallFingerPrint(unknownKeyId)));
+
+ alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+
+ sendMessageToHandler(MESSAGE_OKAY);
+
+ Intent intent = new Intent(activity, KeyServerQueryActivity.class);
+ intent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID);
+ intent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, unknownKeyId);
+ startActivityForResult(intent, Id.request.look_up_key_id);
+ }
+ });
+ alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+
+ sendMessageToHandler(MESSAGE_CANCEL);
+ }
+ });
+ alert.setCancelable(true);
+ alert.setOnCancelListener(new OnCancelListener() {
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ sendMessageToHandler(MESSAGE_CANCEL);
+ }
+ });
+
+ return alert.create();
+ }
+
+ /**
+ * Send message back to handler which is initialized in a activity
+ *
+ * @param what
+ * Message integer you want to send
+ */
+ private void sendMessageToHandler(Integer what) {
+ Message msg = Message.obtain();
+ msg.what = what;
+
+ try {
+ mMessenger.send(msg);
+ } catch (RemoteException e) {
+ Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
+ } catch (NullPointerException e) {
+ Log.w(Constants.TAG, "Messenger is null!", e);
+ }
+ }
+}
\ No newline at end of file