aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik <dominik@dominikschuermann.de>2012-09-10 11:13:32 +0200
committerDominik <dominik@dominikschuermann.de>2012-09-10 11:13:32 +0200
commit45d760008cddaa1125027edbc8a65b6df86e28f1 (patch)
tree09e167478532ec862c81dad68f3b436597567e3c
parent5cd51b2ad08ee7bef57b2bbe24209a32ee5dbd35 (diff)
downloadopen-keychain-45d760008cddaa1125027edbc8a65b6df86e28f1.tar.gz
open-keychain-45d760008cddaa1125027edbc8a65b6df86e28f1.tar.bz2
open-keychain-45d760008cddaa1125027edbc8a65b6df86e28f1.zip
externalized import, export, started working on qr code import
-rw-r--r--org_apg/res/layout/import_from_qr_code.xml63
-rw-r--r--org_apg/res/values/strings.xml89
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ApgApplication.java7
-rw-r--r--org_apg/src/org/thialfihar/android/apg/Id.java2
-rw-r--r--org_apg/src/org/thialfihar/android/apg/helper/OtherHelper.java28
-rw-r--r--org_apg/src/org/thialfihar/android/apg/helper/PGPHelper.java40
-rw-r--r--org_apg/src/org/thialfihar/android/apg/helper/PGPMain.java4
-rw-r--r--org_apg/src/org/thialfihar/android/apg/service/ApgService.java121
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/DecryptActivity.java2
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/ImportFromQRCodeActivity.java148
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/KeyListActivity.java324
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/MailListActivity.java212
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/MainActivity.java6
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/SecretKeyListActivity.java63
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/dialog/DeleteKeyDialogFragment.java130
-rw-r--r--org_apg/src/org/thialfihar/android/apg/ui/dialog/LookupUnknownKeyDialogFragment.java133
16 files changed, 813 insertions, 559 deletions
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true" >
+
+ <LinearLayout
+ android:id="@+id/import_from_qr_code_footer"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:orientation="vertical"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp" >
+
+
+ <Button
+ android:id="@+id/import_from_qr_code_import"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_from_qr_code_import" />
+
+ <Button
+ android:id="@+id/import_from_qr_code_import_sign_and_upload"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_from_qr_code_import_sign_and_upload" />
+
+ <Button
+ android:id="@+id/import_from_qr_code_scan_again"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_from_qr_code_scan_again" />
+
+ <Button
+ android:id="@+id/import_from_qr_code_finish"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_from_qr_code_finish" />
+ </LinearLayout>
+
+ <ScrollView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_above="@id/import_from_qr_code_footer"
+ android:fillViewport="true" >
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp" >
+
+ <TextView
+ android:id="@+id/import_from_qr_code_content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="" />
+ </LinearLayout>
+ </ScrollView>
+
+</RelativeLayout> \ 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 @@
<string name="title_keyServerPreference">Key Server Preference</string>
<string name="title_changePassPhrase">Change Passphrase</string>
<string name="title_setPassPhrase">Set Passphrase</string>
- <string name="title_sendEmail">"Send Mail..."</string>
+ <string name="title_sendEmail">"Send Mail…"</string>
<string name="title_encryptToFile">Encrypt To File</string>
<string name="title_decryptToFile">Decrypt To File</string>
<string name="title_importKeys">Import Keys</string>
@@ -100,7 +100,7 @@
<string name="menu_keyServer">Key Server</string>
<string name="menu_updateKey">Update</string>
<string name="menu_exportKeyToServer">Export To Server</string>
- <string name="menu_share">Share with QR Code</string>
+ <string name="menu_share">Share public key with QR Code</string>
<string name="menu_scanQRCode">Scan QR Code</string>
<string name="menu_signKey">Sign Key</string>
@@ -173,10 +173,10 @@
<string name="dsa">DSA</string>
<string name="elgamal">ElGamal</string>
<string name="rsa">RSA</string>
- <string name="filemanager_titleOpen">Open...</string>
- <string name="filemanager_titleSave">Save As...</string>
- <string name="filemanager_titleEncrypt">Select File To Encrypt...</string>
- <string name="filemanager_titleDecrypt">Select File To Decrypt...</string>
+ <string name="filemanager_titleOpen">Open…</string>
+ <string name="filemanager_titleSave">Save As…</string>
+ <string name="filemanager_titleEncrypt">Select File To Encrypt…</string>
+ <string name="filemanager_titleDecrypt">Select File To Decrypt…</string>
<string name="filemanager_btnOpen">Open</string>
<string name="filemanager_btnSave">Save</string>
<string name="warning">Warning</string>
@@ -260,41 +260,41 @@
<string name="error_savingKeys">error saving some key(s)</string>
<string name="error_couldNotExtractPrivateKey">could not extract private key</string>
- <!-- progress_lowerCase: lowercase, phrases, usually ending in '...' -->
+ <!-- progress_lowerCase: lowercase, phrases, usually ending in '…' -->
<string name="progress_done">done.</string>
- <string name="progress_initializing">initializing...</string>
- <string name="progress_saving">saving...</string>
- <string name="progress_importing">importing...</string>
- <string name="progress_exporting">exporting...</string>
- <string name="progress_generating">generating key, this can take a while...</string>
- <string name="progress_buildingKey">building key...</string>
- <string name="progress_preparingMasterKey">preparing master key...</string>
- <string name="progress_certifyingMasterKey">certifying master key...</string>
- <string name="progress_buildingMasterKeyRing">building master key ring...</string>
- <string name="progress_addingSubKeys">adding sub keys...</string>
- <string name="progress_savingKeyRing">saving key ring...</string>
- <string name="progress_importingSecretKeys">importing secret keys...</string>
- <string name="progress_importingPublicKeys">importing public keys...</string>
- <string name="progress_reloadingKeys">reloading keys...</string>
- <string name="progress_exportingKey">exporting key...</string>
- <string name="progress_exportingKeys">exporting keys...</string>
- <string name="progress_extractingSignatureKey">extracting signature key...</string>
- <string name="progress_extractingKey">extracting key...</string>
- <string name="progress_preparingStreams">preparing streams...</string>
- <string name="progress_encrypting">encrypting data...</string>
- <string name="progress_decrypting">decrypting data...</string>
- <string name="progress_preparingSignature">preparing signature...</string>
- <string name="progress_generatingSignature">generating signature...</string>
- <string name="progress_processingSignature">processing signature...</string>
- <string name="progress_verifyingSignature">verifying signature...</string>
- <string name="progress_signing">signing...</string>
- <string name="progress_readingData">reading data...</string>
- <string name="progress_findingKey">finding key...</string>
- <string name="progress_decompressingData">decompressing data...</string>
- <string name="progress_verifyingIntegrity">verifying integrity...</string>
- <string name="progress_deletingSecurely">deleting \'%s\' securely...</string>
- <string name="progress_querying">querying...</string>
- <string name="progress_queryingServer">querying %s...</string>
+ <string name="progress_initializing">initializing…</string>
+ <string name="progress_saving">saving…</string>
+ <string name="progress_importing">importing…</string>
+ <string name="progress_exporting">exporting…</string>
+ <string name="progress_generating">generating key, this can take a while…</string>
+ <string name="progress_buildingKey">building key…</string>
+ <string name="progress_preparingMasterKey">preparing master key…</string>
+ <string name="progress_certifyingMasterKey">certifying master key…</string>
+ <string name="progress_buildingMasterKeyRing">building master key ring…</string>
+ <string name="progress_addingSubKeys">adding sub keys…</string>
+ <string name="progress_savingKeyRing">saving key ring…</string>
+ <string name="progress_importingSecretKeys">importing secret keys…</string>
+ <string name="progress_importingPublicKeys">importing public keys…</string>
+ <string name="progress_reloadingKeys">reloading keys…</string>
+ <string name="progress_exportingKey">exporting key…</string>
+ <string name="progress_exportingKeys">exporting keys…</string>
+ <string name="progress_extractingSignatureKey">extracting signature key…</string>
+ <string name="progress_extractingKey">extracting key…</string>
+ <string name="progress_preparingStreams">preparing streams…</string>
+ <string name="progress_encrypting">encrypting data…</string>
+ <string name="progress_decrypting">decrypting data…</string>
+ <string name="progress_preparingSignature">preparing signature…</string>
+ <string name="progress_generatingSignature">generating signature…</string>
+ <string name="progress_processingSignature">processing signature…</string>
+ <string name="progress_verifyingSignature">verifying signature…</string>
+ <string name="progress_signing">signing…</string>
+ <string name="progress_readingData">reading data…</string>
+ <string name="progress_findingKey">finding key…</string>
+ <string name="progress_decompressingData">decompressing data…</string>
+ <string name="progress_verifyingIntegrity">verifying integrity…</string>
+ <string name="progress_deletingSecurely">deleting \'%s\' securely…</string>
+ <string name="progress_querying">querying…</string>
+ <string name="progress_queryingServer">querying %s…</string>
<!-- permission strings -->
<string name="permission_read_key_details_label">Read key details from APG.</string>
@@ -316,7 +316,7 @@
<string name="slow">slow</string>
<string name="very_slow">very slow</string>
- <!-- APG Fork -->
+ <!-- APG 2.0 -->
<!-- Dashboard -->
@@ -333,4 +333,11 @@
<string name="help_tab_about">About</string>
<string name="help_about_version">Version:</string>
+ <!-- Import from QR Code -->
+
+ <string name="import_from_qr_code_import">Import key (only locally)</string>
+ <string name="import_from_qr_code_import_sign_and_upload">Import, Sign, and upload key</string>
+ <string name="import_from_qr_code_scan_again">Scan qr code again</string>
+ <string name="import_from_qr_code_finish">Finish</string>
+
</resources> \ 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<String> ks = bundle.keySet();
- Iterator<String> iterator = ks.iterator();
+ if (bundle != null) {
+ Set<String> ks = bundle.keySet();
+ Iterator<String> 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<Integer> keyRingIds,
+ public static Bundle exportKeyRings(Context context, Vector<Integer> 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<Integer> keyRingIds = new Vector<Integer>();
+ 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
-
- // 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();
- }
+
+ // setContentView(R.layout.import_from_qr_code);
+
}
@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 = "<unknown>";
- 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;
- 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);
- }
+ intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_IMPORT_KEY);
- if (mTask == Id.task.import_keys) {
- data = PGPMain.importKeyRings(this, mKeyType, new InputData(importInputStream,
- size), this);
- } else {
- Vector<Integer> keyRingIds = new Vector<Integer>();
- 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;
- }
+ // fill values for this action
+ Bundle data = new Bundle();
- mImportData = null;
+ data.putInt(ApgService.IMPORT_KEY_TYPE, mKeyType);
- 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;
+ // show progress dialog
+ importingDialog.show(getSupportFragmentManager(), "importingDialog");
+
+ // 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) {
- message = getString(R.string.keyExported);
+ toastMessage = getString(R.string.keyExported);
} else if (exported > 0) {
- message = getString(R.string.keysExported, exported);
+ toastMessage = getString(R.string.keysExported, exported);
} else {
- message = getString(R.string.noKeysExported);
+ toastMessage = getString(R.string.noKeysExported);
}
- Toast.makeText(KeyListActivity.this, message, Toast.LENGTH_SHORT).show();
+ Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
+
}
- break;
- }
+ };
+ };
- default: {
- break;
- }
- }
- }
+ // 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 <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.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<Message> 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<Conversation> mConversations;
- private Vector<Message> 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<Conversation>();
- mMessages = new Vector<Message>();
-
- 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<Message> messages = new Vector<Message>();
- 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 <dominik@dominikschuermann.de>
+ *
+ * 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 = "<unknown>";
+ 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 <dominik@dominikschuermann.de>
+ *
+ * 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