From f06fcd989b2eb1416eea521c88944ff0c1482347 Mon Sep 17 00:00:00 2001 From: Dominik Date: Wed, 25 Apr 2012 15:10:12 +0200 Subject: [PATCH] externalizing code into service --- .../src/org/thialfihar/android/apg/Apg.java | 167 ++++++------ .../src/org/thialfihar/android/apg/Id.java | 37 ++- .../android/apg/service/ApgHandler.java | 103 +++++++ .../android/apg/service/ApgService.java | 258 ++++++++++-------- .../android/apg/ui/BaseActivity.java | 7 +- .../android/apg/ui/EditKeyActivity.java | 245 +++++++---------- .../android/apg/ui/ProgressDialog.java | 42 --- .../apg/ui/ProgressDialogFragment.java | 148 +++++----- .../android/apg/ui/widget/SectionView.java | 156 +++++------ .../thialfihar/android/apg/util/Utils.java | 74 +++++ 10 files changed, 686 insertions(+), 551 deletions(-) create mode 100644 org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java delete mode 100644 org_apg/src/org/thialfihar/android/apg/ui/ProgressDialog.java diff --git a/org_apg/src/org/thialfihar/android/apg/Apg.java b/org_apg/src/org/thialfihar/android/apg/Apg.java index 1e00fce40..9d8264dd4 100644 --- a/org_apg/src/org/thialfihar/android/apg/Apg.java +++ b/org_apg/src/org/thialfihar/android/apg/Apg.java @@ -77,6 +77,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Message; +import android.util.Log; import android.view.ViewGroup; import java.io.BufferedInputStream; @@ -110,7 +111,8 @@ import java.util.Vector; import java.util.regex.Pattern; public class Apg { - private static final String PACKAGE_NAME = "org.thialfihar.android.apg"; + public static final String PACKAGE_NAME = "org.thialfihar.android.apg"; + private static final String INTENT_PREFIX = "org.thialfihar.android.apg.intent."; public static class Intent { @@ -378,14 +380,16 @@ public class Apg { secretKey = it.next(); } + Log.d(Constants.TAG, "new secretkey: " + secretKey.toString()); + return secretKey; } public static void buildSecretKey(Context context, ArrayList userIds, - ArrayList keys, ArrayList keysUsages, long masterKeyId, String oldPassPhrase, String newPassPhrase, - ProgressDialogUpdater progress) throws Apg.GeneralException, NoSuchProviderException, - PGPException, NoSuchAlgorithmException, SignatureException, IOException, - Database.GeneralException { + ArrayList keys, ArrayList keysUsages, long masterKeyId, + String oldPassPhrase, String newPassPhrase, ProgressDialogUpdater progress) + throws Apg.GeneralException, NoSuchProviderException, PGPException, + NoSuchAlgorithmException, SignatureException, IOException, Database.GeneralException { if (progress != null) progress.setProgress(R.string.progress_buildingKey, 0, 100); @@ -400,64 +404,63 @@ public class Apg { newPassPhrase = ""; } -// Vector userIds = new Vector(); -// Vector keys = new Vector(); + // Vector userIds = new Vector(); + // Vector keys = new Vector(); -// ViewGroup userIdEditors = userIdsView.getEditors(); -// ViewGroup keyEditors = keysView.getEditors(); -// -// boolean gotMainUserId = false; -// for (int i = 0; i < userIdEditors.getChildCount(); ++i) { -// UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i); -// String userId = null; -// try { -// userId = editor.getValue(); -// } catch (UserIdEditor.NoNameException e) { -// throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName)); -// } catch (UserIdEditor.NoEmailException e) { -// throw new Apg.GeneralException( -// context.getString(R.string.error_userIdNeedsAnEmailAddress)); -// } catch (UserIdEditor.InvalidEmailException e) { -// throw new Apg.GeneralException("" + e); -// } -// -// if (userId.equals("")) { -// continue; -// } -// -// if (editor.isMainUserId()) { -// userIds.insertElementAt(userId, 0); -// gotMainUserId = true; -// } else { -// userIds.add(userId); -// } -// } + // ViewGroup userIdEditors = userIdsView.getEditors(); + // ViewGroup keyEditors = keysView.getEditors(); + // + // boolean gotMainUserId = false; + // for (int i = 0; i < userIdEditors.getChildCount(); ++i) { + // UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i); + // String userId = null; + // try { + // userId = editor.getValue(); + // } catch (UserIdEditor.NoNameException e) { + // throw new Apg.GeneralException(context.getString(R.string.error_userIdNeedsAName)); + // } catch (UserIdEditor.NoEmailException e) { + // throw new Apg.GeneralException( + // context.getString(R.string.error_userIdNeedsAnEmailAddress)); + // } catch (UserIdEditor.InvalidEmailException e) { + // throw new Apg.GeneralException("" + e); + // } + // + // if (userId.equals("")) { + // continue; + // } + // + // if (editor.isMainUserId()) { + // userIds.insertElementAt(userId, 0); + // gotMainUserId = true; + // } else { + // userIds.add(userId); + // } + // } -// if (userIds.size() == 0) { -// throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsAUserId)); -// } -// -// if (!gotMainUserId) { -// throw new Apg.GeneralException( -// context.getString(R.string.error_mainUserIdMustNotBeEmpty)); -// } + // if (userIds.size() == 0) { + // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsAUserId)); + // } + // + // if (!gotMainUserId) { + // throw new Apg.GeneralException( + // context.getString(R.string.error_mainUserIdMustNotBeEmpty)); + // } -// if (keyEditors.getChildCount() == 0) { -// throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsMasterKey)); -// } -// -// for (int i = 0; i < keyEditors.getChildCount(); ++i) { -// KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); -// keys.add(editor.getValue()); -// } + // if (keyEditors.getChildCount() == 0) { + // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsMasterKey)); + // } + // + // for (int i = 0; i < keyEditors.getChildCount(); ++i) { + // KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); + // keys.add(editor.getValue()); + // } if (progress != null) progress.setProgress(R.string.progress_preparingMasterKey, 10, 100); - - -// KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0); -// int usageId = keyEditor.getUsage(); - + + // KeyEditor keyEditor = (KeyEditor) keyEditors.getChildAt(0); + // int usageId = keyEditor.getUsage(); + int usageId = keysUsages.get(0); boolean canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt); boolean canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt); @@ -504,17 +507,17 @@ public class Apg { hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS); // TODO: this doesn't work quite right yet -// if (keyEditor.getExpiryDate() != null) { -// GregorianCalendar creationDate = new GregorianCalendar(); -// creationDate.setTime(getCreationDate(masterKey)); -// GregorianCalendar expiryDate = keyEditor.getExpiryDate(); -// long numDays = Utils.getNumDaysBetween(creationDate, expiryDate); -// if (numDays <= 0) { -// throw new GeneralException( -// context.getString(R.string.error_expiryMustComeAfterCreation)); -// } -// hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400); -// } + // if (keyEditor.getExpiryDate() != null) { + // GregorianCalendar creationDate = new GregorianCalendar(); + // creationDate.setTime(getCreationDate(masterKey)); + // GregorianCalendar expiryDate = keyEditor.getExpiryDate(); + // long numDays = Utils.getNumDaysBetween(creationDate, expiryDate); + // if (numDays <= 0) { + // throw new GeneralException( + // context.getString(R.string.error_expiryMustComeAfterCreation)); + // } + // hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400); + // } if (progress != null) { progress.setProgress(R.string.progress_buildingMasterKeyRing, 30, 100); @@ -531,7 +534,7 @@ public class Apg { if (progress != null) progress.setProgress(40 + 50 * (i - 1) / (keys.size() - 1), 100); PGPSecretKey subKey = keys.get(i); -// keyEditor = (KeyEditor) keyEditors.getChildAt(i); + // keyEditor = (KeyEditor) keyEditors.getChildAt(i); PGPPublicKey subPublicKey = subKey.getPublicKey(); PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(oldPassPhrase.toCharArray(), new BouncyCastleProvider()); @@ -543,8 +546,8 @@ public class Apg { unhashedPacketsGen = new PGPSignatureSubpacketGenerator(); keyFlags = 0; -// usageId = keyEditor.getUsage(); - + // usageId = keyEditor.getUsage(); + usageId = keysUsages.get(i); canSign = (usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt); canEncrypt = (usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt); @@ -557,17 +560,17 @@ public class Apg { hashedPacketsGen.setKeyFlags(true, keyFlags); // TODO: this doesn't work quite right yet -// if (keyEditor.getExpiryDate() != null) { -// GregorianCalendar creationDate = new GregorianCalendar(); -// creationDate.setTime(getCreationDate(masterKey)); -// GregorianCalendar expiryDate = keyEditor.getExpiryDate(); -// long numDays = Utils.getNumDaysBetween(creationDate, expiryDate); -// if (numDays <= 0) { -// throw new GeneralException( -// context.getString(R.string.error_expiryMustComeAfterCreation)); -// } -// hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400); -// } + // if (keyEditor.getExpiryDate() != null) { + // GregorianCalendar creationDate = new GregorianCalendar(); + // creationDate.setTime(getCreationDate(masterKey)); + // GregorianCalendar expiryDate = keyEditor.getExpiryDate(); + // long numDays = Utils.getNumDaysBetween(creationDate, expiryDate); + // if (numDays <= 0) { + // throw new GeneralException( + // context.getString(R.string.error_expiryMustComeAfterCreation)); + // } + // hashedPacketsGen.setKeyExpirationTime(true, numDays * 86400); + // } keyGen.addSubKey(subKeyPair, hashedPacketsGen.generate(), unhashedPacketsGen.generate()); } diff --git a/org_apg/src/org/thialfihar/android/apg/Id.java b/org_apg/src/org/thialfihar/android/apg/Id.java index 7308d5d25..138a9535d 100644 --- a/org_apg/src/org/thialfihar/android/apg/Id.java +++ b/org_apg/src/org/thialfihar/android/apg/Id.java @@ -55,20 +55,35 @@ public final class Id { } } + // use only lower 16 bits due to compatibility lib public static final class message { - public static final int progress_update = 0x21070001; - public static final int done = 0x21070002; - public static final int import_keys = 0x21070003; - public static final int export_keys = 0x21070004; - public static final int import_done = 0x21070005; - public static final int export_done = 0x21070006; - public static final int create_key = 0x21070007; - public static final int edit_key = 0x21070008; - public static final int delete_done = 0x21070009; - public static final int query_done = 0x21070010; - public static final int unknown_signature_key = 0x21070011; + public static final int progress_update = 0x00006001; + public static final int done = 0x00006002; + public static final int import_keys = 0x00006003; + public static final int export_keys = 0x00006004; + public static final int import_done = 0x00006005; + public static final int export_done = 0x00006006; + public static final int create_key = 0x00006007; + public static final int edit_key = 0x00006008; + public static final int delete_done = 0x00006009; + public static final int query_done = 0x00006010; + public static final int unknown_signature_key = 0x00006011; } + // public static final class message { + // public static final int progress_update = 0x21070001; + // public static final int done = 0x21070002; + // public static final int import_keys = 0x21070003; + // public static final int export_keys = 0x21070004; + // public static final int import_done = 0x21070005; + // public static final int export_done = 0x21070006; + // public static final int create_key = 0x21070007; + // public static final int edit_key = 0x21070008; + // public static final int delete_done = 0x21070009; + // public static final int query_done = 0x21070010; + // public static final int unknown_signature_key = 0x21070011; + // } + public static final class request { public static final int public_keys = 0x21070001; public static final int secret_keys = 0x21070002; diff --git a/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java b/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java new file mode 100644 index 000000000..fe848fb68 --- /dev/null +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgHandler.java @@ -0,0 +1,103 @@ +/* + * 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.service; + +import org.thialfihar.android.apg.R; +import org.thialfihar.android.apg.ui.ProgressDialogFragment; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.widget.Toast; + +public class ApgHandler extends Handler { + + // possible messages send from this service to handler on ui + public static final int MESSAGE_OKAY = 1; + public static final int MESSAGE_EXCEPTION = 2; + public static final int MESSAGE_UPDATE_PROGRESS = 3; + + // possible data keys for messages + public static final String ERROR = "error"; + public static final String PROGRESS = "progress"; + public static final String PROGRESS_MAX = "max"; + public static final String MESSAGE = "message"; + public static final String MESSAGE_ID = "message_id"; + + // generate key results + public static final String NEW_KEY = "new_key"; + + + Activity mActivity; + + ProgressDialogFragment mProgressDialogFragment; + + public ApgHandler(Activity activity) { + this.mActivity = activity; + } + + public ApgHandler(Activity activity, ProgressDialogFragment progressDialogFragment) { + this.mActivity = activity; + this.mProgressDialogFragment = progressDialogFragment; + } + + @Override + public void handleMessage(Message message) { + Bundle data = message.getData(); + + switch (message.arg1) { + case MESSAGE_OKAY: + mProgressDialogFragment.dismiss(); + + break; + + case MESSAGE_EXCEPTION: + mProgressDialogFragment.dismiss(); + + if (data.containsKey(ERROR)) { + Toast.makeText(mActivity, + mActivity.getString(R.string.errorMessage, data.getString(ERROR)), + Toast.LENGTH_SHORT).show(); + } + + break; + + case MESSAGE_UPDATE_PROGRESS: + if (data.containsKey(PROGRESS) && data.containsKey(PROGRESS_MAX)) { + + if (data.containsKey(MESSAGE)) { + mProgressDialogFragment.setProgress(data.getString(MESSAGE), + data.getInt(PROGRESS), data.getInt(PROGRESS_MAX)); + } else if (data.containsKey(MESSAGE_ID)) { + mProgressDialogFragment.setProgress(data.getInt(MESSAGE_ID), + data.getInt(PROGRESS), data.getInt(PROGRESS_MAX)); + + } else { + mProgressDialogFragment.setProgress(data.getInt(PROGRESS), + data.getInt(PROGRESS_MAX)); + } + + } + + break; + + default: + break; + } + } +} 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 7a77e4891..6a27ba45d 100644 --- a/org_apg/src/org/thialfihar/android/apg/service/ApgService.java +++ b/org_apg/src/org/thialfihar/android/apg/service/ApgService.java @@ -1,24 +1,28 @@ -/** - * TODO: - * - Reimplement all the threads in the activitys as intents in this intentService - * - This IntentService stopps itself after an action is executed +/* + * 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.service; import java.util.ArrayList; -import java.util.Iterator; -import java.util.Vector; -import org.spongycastle.openpgp.PGPObjectFactory; import org.spongycastle.openpgp.PGPSecretKey; -import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Constants; -import org.thialfihar.android.apg.Id; import org.thialfihar.android.apg.ProgressDialogUpdater; -import org.thialfihar.android.apg.ui.widget.KeyEditor; -import org.thialfihar.android.apg.ui.widget.SectionView; +import org.thialfihar.android.apg.util.Utils; import android.app.IntentService; import android.content.Intent; @@ -28,7 +32,12 @@ import android.os.Messenger; import android.os.RemoteException; import android.util.Log; -//TODO: ProgressDialogUpdater rework??? +/** + * This Service contains all important long lasting operations for APG. It receives Intents with + * data from the activities or other apps, queues these intents, executes them, and stops itself + * doing it. + */ +// TODO: ProgressDialogUpdater rework??? public class ApgService extends IntentService implements ProgressDialogUpdater { // extras that can be given by intent @@ -38,22 +47,22 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { // keys for data bundle // edit keys - public static final String DATA_NEW_PASSPHRASE = "new_passphrase"; - public static final String DATA_CURRENT_PASSPHRASE = "current_passphrase"; - public static final String DATA_USER_IDS = "user_ids"; - public static final String DATA_KEYS = "keys"; - public static final String DATA_KEYS_USAGES = "keys_usages"; - public static final String DATA_MASTER_KEY_ID = "master_key_id"; + public static final String NEW_PASSPHRASE = "new_passphrase"; + public static final String CURRENT_PASSPHRASE = "current_passphrase"; + public static final String USER_IDS = "user_ids"; + public static final String KEYS = "keys"; + public static final String KEYS_USAGES = "keys_usages"; + public static final String MASTER_KEY_ID = "master_key_id"; + + // generate key + public static final String ALGORITHM = "algorithm"; + public static final String KEY_SIZE = "key_size"; + public static final String PASSPHRASE = "passphrase"; + public static final String MASTER_KEY = "master_key"; // possible ints for EXTRA_ACTION public static final int ACTION_SAVE_KEYRING = 1; - - // possible messages send from this service to handler on ui - public static final int MESSAGE_OKAY = 1; - public static final int MESSAGE_EXCEPTION = 2; - - // possible data keys for messages - public static final String MESSAGE_DATA_ERROR = "error"; + public static final int ACTION_GENERATE_KEY = 2; Messenger mMessenger; @@ -69,89 +78,104 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); - if (extras != null) { + if (extras == null) { + Log.e(Constants.TAG, "Extra bundle is null!"); + return; + } - if (!extras.containsKey(EXTRA_ACTION)) { - Log.e(Constants.TAG, "Extra bundle must contain a action!"); - return; + if (!extras.containsKey(EXTRA_MESSENGER)) { + Log.e(Constants.TAG, "Extra bundle must contain a messenger!"); + return; + } + mMessenger = (Messenger) extras.get(EXTRA_MESSENGER); + + if (!extras.containsKey(EXTRA_DATA)) { + Log.e(Constants.TAG, "Extra bundle must contain data bundle!"); + return; + } + Bundle data = extras.getBundle(EXTRA_DATA); + + if (!extras.containsKey(EXTRA_ACTION)) { + Log.e(Constants.TAG, "Extra bundle must contain a action!"); + return; + } + int action = extras.getInt(EXTRA_ACTION); + + // execute action from extra bundle + switch (action) { + case ACTION_SAVE_KEYRING: + + try { + // Input + String oldPassPhrase = data.getString(CURRENT_PASSPHRASE); + String newPassPhrase = data.getString(NEW_PASSPHRASE); + if (newPassPhrase == null) { + newPassPhrase = oldPassPhrase; + } + @SuppressWarnings("unchecked") + ArrayList userIds = (ArrayList) data.getSerializable(USER_IDS); + ArrayList keys = Utils.BytesToPGPSecretKeyList(data + .getByteArray(KEYS)); + @SuppressWarnings("unchecked") + ArrayList keysUsages = (ArrayList) data + .getSerializable(KEYS_USAGES); + long masterKeyId = data.getLong(MASTER_KEY_ID); + + // Operation + Apg.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase, + newPassPhrase, this); + Apg.setCachedPassPhrase(masterKeyId, newPassPhrase); + + // Output + sendMessageToHandler(ApgHandler.MESSAGE_OKAY); + } catch (Exception e) { + sendErrorToHandler(e); } - if (!extras.containsKey(EXTRA_MESSENGER)) { - Log.e(Constants.TAG, "Extra bundle must contain a messenger!"); - return; - } - mMessenger = (Messenger) extras.get(EXTRA_MESSENGER); + break; - Bundle data = null; - if (extras.containsKey(EXTRA_DATA)) { - data = extras.getBundle(EXTRA_DATA); - } + case ACTION_GENERATE_KEY: - int action = extras.getInt(EXTRA_ACTION); - - // will be filled if error occurs - String error = ""; - - // execute action from extra bundle - switch (action) { - case ACTION_SAVE_KEYRING: - - try { - String oldPassPhrase = data.getString(DATA_CURRENT_PASSPHRASE); - String newPassPhrase = data.getString(DATA_NEW_PASSPHRASE); - if (newPassPhrase == null) { - newPassPhrase = oldPassPhrase; - } - ArrayList userIds = (ArrayList) data - .getSerializable(DATA_USER_IDS); - - byte[] keysBytes = data.getByteArray(DATA_KEYS); - - // convert back from byte[] to ArrayList - PGPObjectFactory factory = new PGPObjectFactory(keysBytes); - PGPSecretKeyRing keyRing = null; - if ((keyRing = (PGPSecretKeyRing) factory.nextObject()) == null) { - Log.e(Constants.TAG, "No keys given!"); - } - ArrayList keys = new ArrayList(); - - Iterator itr = keyRing.getSecretKeys(); - while (itr.hasNext()) { - keys.add(itr.next()); - Log.d(Constants.TAG, "added..."); - } - - ArrayList keysUsages = (ArrayList) data - .getSerializable(DATA_KEYS_USAGES); - long masterKeyId = data.getLong(DATA_MASTER_KEY_ID); - - Apg.buildSecretKey(this, userIds, keys, keysUsages, masterKeyId, oldPassPhrase, - newPassPhrase, this); - Apg.setCachedPassPhrase(masterKeyId, newPassPhrase); - } catch (Exception e) { - error = e.getMessage(); - Log.e(Constants.TAG, "Exception: " + error); - e.printStackTrace(); - sendErrorToUi(error); + try { + // Input + int algorithm = data.getInt(ALGORITHM); + String passphrase = data.getString(PASSPHRASE); + int keysize = data.getInt(KEY_SIZE); + PGPSecretKey masterKey = null; + if (data.containsKey(MASTER_KEY)) { + masterKey = Utils.BytesToPGPSecretKey(data.getByteArray(MASTER_KEY)); } - sendMessageToUi(MESSAGE_OKAY, null, null); - break; + // Operation + PGPSecretKey newKey = Apg + .createKey(this, algorithm, keysize, passphrase, masterKey); - default: - break; + // Output + Bundle resultData = new Bundle(); + resultData.putByteArray(ApgHandler.NEW_KEY, Utils.PGPSecretKeyToBytes(newKey)); + sendMessageToHandler(ApgHandler.MESSAGE_OKAY, null, resultData); + } catch (Exception e) { + sendErrorToHandler(e); } + break; + + default: + break; } + } - private void sendErrorToUi(String error) { + private void sendErrorToHandler(Exception e) { + Log.e(Constants.TAG, "ApgService Exception: ", e); + e.printStackTrace(); + Bundle data = new Bundle(); - data.putString(MESSAGE_DATA_ERROR, error); - sendMessageToUi(MESSAGE_EXCEPTION, null, data); + data.putString(ApgHandler.ERROR, e.getMessage()); + sendMessageToHandler(ApgHandler.MESSAGE_EXCEPTION, null, data); } - private void sendMessageToUi(Integer arg1, Integer arg2, Bundle data) { + private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) { Message msg = Message.obtain(); msg.arg1 = arg1; if (arg2 != null) { @@ -164,43 +188,37 @@ public class ApgService extends IntentService implements ProgressDialogUpdater { try { mMessenger.send(msg); } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message", e); + Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); } catch (NullPointerException e) { Log.w(Constants.TAG, "Messenger is null!", e); } } + private void sendMessageToHandler(Integer arg1) { + sendMessageToHandler(arg1, null, null); + } + + /** + * Set progress of ProgressDialog by sending message to handler on UI thread + */ + public void setProgress(String message, int progress, int max) { + Log.d(Constants.TAG, "Send message by setProgress"); + + Bundle data = new Bundle(); + if (message != null) { + data.putString(ApgHandler.MESSAGE, message); + } + data.putInt(ApgHandler.PROGRESS, progress); + data.putInt(ApgHandler.PROGRESS_MAX, max); + + sendMessageToHandler(ApgHandler.MESSAGE_UPDATE_PROGRESS, null, data); + } + public void setProgress(int resourceId, int progress, int max) { setProgress(getString(resourceId), progress, max); } public void setProgress(int progress, int max) { - Message msg = new Message(); - Bundle data = new Bundle(); - data.putInt(Constants.extras.STATUS, Id.message.progress_update); - data.putInt(Constants.extras.PROGRESS, progress); - data.putInt(Constants.extras.PROGRESS_MAX, max); - msg.setData(data); - try { - mMessenger.send(msg); - } catch (RemoteException e) { - e.printStackTrace(); - } - } - - public void setProgress(String message, int progress, int max) { - Message msg = new Message(); - Bundle data = new Bundle(); - data.putInt(Constants.extras.STATUS, Id.message.progress_update); - data.putString(Constants.extras.MESSAGE, message); - data.putInt(Constants.extras.PROGRESS, progress); - data.putInt(Constants.extras.PROGRESS_MAX, max); - msg.setData(data); - try { - mMessenger.send(msg); - } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + setProgress(null, progress, max); } } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java index 022daf420..73d71c456 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/BaseActivity.java @@ -32,6 +32,7 @@ import org.thialfihar.android.apg.Service; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.MenuItem; import android.app.Activity; @@ -44,10 +45,12 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.Fragment; import android.widget.Toast; -public class BaseActivity extends SherlockActivity implements Runnable, ProgressDialogUpdater, - AskForSecretKeyPassPhrase.PassPhraseCallbackInterface { +public class BaseActivity extends SherlockFragmentActivity implements Runnable, + ProgressDialogUpdater, AskForSecretKeyPassPhrase.PassPhraseCallbackInterface { private ProgressDialog mProgressDialog = null; private PausableThread mRunningThread = null; diff --git a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java index 6abbc1b56..339d743b6 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/EditKeyActivity.java @@ -22,28 +22,29 @@ import org.spongycastle.openpgp.PGPSecretKeyRing; import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Constants; import org.thialfihar.android.apg.Id; +import org.thialfihar.android.apg.service.ApgHandler; import org.thialfihar.android.apg.service.ApgService; import org.thialfihar.android.apg.ui.widget.KeyEditor; import org.thialfihar.android.apg.ui.widget.SectionView; import org.thialfihar.android.apg.ui.widget.UserIdEditor; import org.thialfihar.android.apg.util.IterableIterator; +import org.thialfihar.android.apg.util.Utils; import org.thialfihar.android.apg.R; import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.SherlockActivity; +import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuItem; import android.app.AlertDialog; import android.app.Dialog; +import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; import android.os.Message; import android.os.Messenger; -import android.support.v4.app.DialogFragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -57,11 +58,9 @@ import android.widget.LinearLayout; import android.widget.Toast; import android.widget.CompoundButton.OnCheckedChangeListener; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.util.Vector; -public class EditKeyActivity extends SherlockActivity { // extends BaseActivity { +public class EditKeyActivity extends SherlockFragmentActivity { // extends BaseActivity { private Intent mIntent = null; private ActionBar mActionBar; @@ -77,6 +76,8 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity private CheckBox mNoPassphrase; + private ProgressDialogFragment mSavingDialog; + @Override public boolean onCreateOptionsMenu(Menu menu) { menu.add(1, Id.menu.option.cancel, 0, R.string.btn_doNotSave).setShowAsAction( @@ -115,6 +116,16 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity setContentView(R.layout.edit_key); mActionBar = getSupportActionBar(); + mActionBar.setDisplayShowTitleEnabled(true); + + // set actionbar without home button if called from another app + if (getCallingPackage() != null && getCallingPackage().equals(Apg.PACKAGE_NAME)) { + mActionBar.setDisplayHomeAsUpEnabled(true); + mActionBar.setHomeButtonEnabled(true); + } else { + mActionBar.setDisplayHomeAsUpEnabled(false); + mActionBar.setHomeButtonEnabled(false); + } // find views mChangePassPhrase = (Button) findViewById(R.id.edit_key_btn_change_pass_phrase); @@ -126,6 +137,8 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity // Catch Intents opened from other apps mIntent = getIntent(); + + // Handle intents Bundle extras = mIntent.getExtras(); if (Apg.Intent.CREATE_KEY.equals(mIntent.getAction())) { @@ -134,12 +147,6 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity mCurrentPassPhrase = ""; if (extras != null) { - - // disable home button on actionbar because this activity is run from another app - mActionBar.setDisplayShowTitleEnabled(true); - mActionBar.setDisplayHomeAsUpEnabled(false); - mActionBar.setHomeButtonEnabled(false); - // if userId is given, prefill the fields if (extras.containsKey(Apg.EXTRA_USER_IDS)) { Log.d(Constants.TAG, "UserIds are given!"); @@ -339,72 +346,71 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity } private void saveClicked() { - if (!isPassphraseSet()) { - Toast.makeText(this, R.string.setAPassPhrase, Toast.LENGTH_SHORT).show(); - return; - } -// showDialog(Id.dialog.saving); - - ProgressDialogFragment newFragment = ProgressDialogFragment.newInstance( - ProgressDialogFragment.ID_SAVING); - newFragment.show(getSupportFragmentManager(), "saving"); -// ((ProgressDialog) newFragment.getDialog()).setProgress(value) - // startThread(); - - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(this, ApgService.class); - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(handler); - intent.putExtra(ApgService.EXTRA_MESSENGER, messenger); - intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_SAVE_KEYRING); - - // fill values for this action - Bundle data = new Bundle(); - data.putString(ApgService.DATA_CURRENT_PASSPHRASE, mCurrentPassPhrase); - data.putString(ApgService.DATA_NEW_PASSPHRASE, mNewPassPhrase); - data.putSerializable(ApgService.DATA_USER_IDS, getUserIds(mUserIds)); - - Vector keys = getKeys(mKeys); - - // convert to byte[] - ByteArrayOutputStream os = new ByteArrayOutputStream(); - for (PGPSecretKey key : keys) { - try { - key.encode(os); - } catch (IOException e) { - Log.e(Constants.TAG, - "Error while converting PGPSecretKey to byte[]: " + e.getMessage()); - e.printStackTrace(); + try { + if (!isPassphraseSet()) { + throw new Apg.GeneralException(this.getString(R.string.setAPassPhrase)); } + + // Send all information needed to service to edit key in other thread + Intent intent = new Intent(this, ApgService.class); + + intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_SAVE_KEYRING); + + // fill values for this action + Bundle data = new Bundle(); + data.putString(ApgService.CURRENT_PASSPHRASE, mCurrentPassPhrase); + data.putString(ApgService.NEW_PASSPHRASE, mNewPassPhrase); + + data.putSerializable(ApgService.USER_IDS, getUserIds(mUserIds)); + + Vector keys = getKeys(mKeys); + byte[] keysBytes = Utils.PGPSecretKeyListToBytes(keys); + data.putByteArray(ApgService.KEYS, keysBytes); + + data.putSerializable(ApgService.KEYS_USAGES, getKeysUsages(mKeys)); + + data.putLong(ApgService.MASTER_KEY_ID, getMasterKeyId()); + + intent.putExtra(ApgService.EXTRA_DATA, data); + + // show progress dialog + mSavingDialog = ProgressDialogFragment.newInstance(R.string.progress_saving, + ProgressDialog.STYLE_HORIZONTAL); + + // Message is received after saving is done in ApgService + ApgHandler saveHandler = new ApgHandler(this, mSavingDialog) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == ApgHandler.MESSAGE_OKAY) { + finish(); + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(ApgService.EXTRA_MESSENGER, messenger); + + mSavingDialog.show(getSupportFragmentManager(), "dialog"); + + // start service with intent + startService(intent); + } catch (Apg.GeneralException e) { + Toast.makeText(this, getString(R.string.errorMessage, e.getMessage()), + Toast.LENGTH_SHORT).show(); } - - byte[] keysBytes = os.toByteArray(); - - data.putByteArray(ApgService.DATA_KEYS, keysBytes); - - data.putSerializable(ApgService.DATA_KEYS_USAGES, getKeysUsages(mKeys).toArray()); - data.putLong(ApgService.DATA_MASTER_KEY_ID, getMasterKeyId()); - - intent.putExtra(ApgService.EXTRA_DATA, data); - - startService(intent); } - private Handler handler = new Handler() { - public void handleMessage(Message message) { - Object path = message.obj; - if (message.arg1 == ApgService.MESSAGE_OKAY) { - Toast.makeText(EditKeyActivity.this, "okay", Toast.LENGTH_LONG).show(); - } else { - Toast.makeText(EditKeyActivity.this, "nope", Toast.LENGTH_LONG).show(); - } - - }; - }; - - // TODO: put in other class - private Vector getUserIds(SectionView userIdsView) { + /** + * Returns user ids from the SectionView + * + * @param userIdsView + * @return + */ + private Vector getUserIds(SectionView userIdsView) throws Apg.GeneralException { Vector userIds = new Vector(); ViewGroup userIdEditors = userIdsView.getEditors(); @@ -416,12 +422,12 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity try { userId = editor.getValue(); } catch (UserIdEditor.NoNameException e) { - // throw new Apg.GeneralException(this.getString(R.string.error_userIdNeedsAName)); + throw new Apg.GeneralException(this.getString(R.string.error_userIdNeedsAName)); } catch (UserIdEditor.NoEmailException e) { - // throw new Apg.GeneralException( - // this.getString(R.string.error_userIdNeedsAnEmailAddress)); + throw new Apg.GeneralException( + this.getString(R.string.error_userIdNeedsAnEmailAddress)); } catch (UserIdEditor.InvalidEmailException e) { - // throw new Apg.GeneralException("" + e); + throw new Apg.GeneralException(e.getMessage()); } if (userId.equals("")) { @@ -437,24 +443,29 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity } if (userIds.size() == 0) { - // throw new Apg.GeneralException(context.getString(R.string.error_keyNeedsAUserId)); + throw new Apg.GeneralException(getString(R.string.error_keyNeedsAUserId)); } if (!gotMainUserId) { - // throw new Apg.GeneralException( - // context.getString(R.string.error_mainUserIdMustNotBeEmpty)); + throw new Apg.GeneralException(getString(R.string.error_mainUserIdMustNotBeEmpty)); } return userIds; } - private Vector getKeys(SectionView keysView) { + /** + * Returns keys from the SectionView + * + * @param keysView + * @return + */ + private Vector getKeys(SectionView keysView) throws Apg.GeneralException { Vector keys = new Vector(); ViewGroup keyEditors = keysView.getEditors(); if (keyEditors.getChildCount() == 0) { - // throw new Apg.GeneralException(getString(R.string.error_keyNeedsMasterKey)); + throw new Apg.GeneralException(getString(R.string.error_keyNeedsMasterKey)); } for (int i = 0; i < keyEditors.getChildCount(); ++i) { @@ -465,13 +476,19 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity return keys; } - private Vector getKeysUsages(SectionView keysView) { + /** + * Returns usage selections of keys from the SectionView + * + * @param keysView + * @return + */ + private Vector getKeysUsages(SectionView keysView) throws Apg.GeneralException { Vector getKeysUsages = new Vector(); ViewGroup keyEditors = keysView.getEditors(); if (keyEditors.getChildCount() == 0) { - // throw new Apg.GeneralException(getString(R.string.error_keyNeedsMasterKey)); + throw new Apg.GeneralException(getString(R.string.error_keyNeedsMasterKey)); } for (int i = 0; i < keyEditors.getChildCount(); ++i) { @@ -482,66 +499,6 @@ public class EditKeyActivity extends SherlockActivity { // extends BaseActivity return getKeysUsages; } - // @Override - // public void run() { - // String error = null; - // Bundle data = new Bundle(); - // Message msg = new Message(); - // - // data.putParcelable("ts", (Parcelable) mUserIds); - // - // try { - // String oldPassPhrase = mCurrentPassPhrase; - // String newPassPhrase = mNewPassPhrase; - // if (newPassPhrase == null) { - // newPassPhrase = oldPassPhrase; - // } - // Apg.buildSecretKey(this, mUserIds, mKeys, oldPassPhrase, newPassPhrase, this); - // Apg.setCachedPassPhrase(getMasterKeyId(), newPassPhrase); - // } catch (NoSuchProviderException e) { - // error = "" + e; - // } catch (NoSuchAlgorithmException e) { - // error = "" + e; - // } catch (PGPException e) { - // error = "" + e; - // } catch (SignatureException e) { - // error = "" + e; - // } catch (Apg.GeneralException e) { - // error = "" + e; - // } catch (Database.GeneralException e) { - // error = "" + e; - // } catch (IOException e) { - // error = "" + e; - // } - // - // data.putInt(Constants.extras.STATUS, Id.message.done); - // - // if (error != null) { - // data.putString(Apg.EXTRA_ERROR, error); - // } - // - // msg.setData(data); - // sendMessage(msg); - // } - - // @Override - // public void doneCallback(Message msg) { - // super.doneCallback(msg); - // - // Bundle data = msg.getData(); - // removeDialog(Id.dialog.saving); - // - // String error = data.getString(Apg.EXTRA_ERROR); - // if (error != null) { - // Toast.makeText(EditKeyActivity.this, getString(R.string.errorMessage, error), - // Toast.LENGTH_SHORT).show(); - // } else { - // Toast.makeText(EditKeyActivity.this, R.string.keySaved, Toast.LENGTH_SHORT).show(); - // setResult(RESULT_OK); - // finish(); - // } - // } - private void updatePassPhraseButtonText() { mChangePassPhrase.setText(isPassphraseSet() ? R.string.btn_changePassPhrase : R.string.btn_setPassPhrase); diff --git a/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialog.java b/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialog.java deleted file mode 100644 index 05bd02cf0..000000000 --- a/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialog.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.thialfihar.android.apg.ui; - -import org.thialfihar.android.apg.Constants; -import org.thialfihar.android.apg.Id; - -import android.content.Context; -import android.os.Bundle; -import android.os.Message; - -/** - * Extends the standard ProgressDialog by new methods for setting progress - * - */ -public class ProgressDialog extends android.app.ProgressDialog{ - - Context mContext; - - public ProgressDialog(Context context) { - super(context); - mContext = context; - } - - public void setProgress(int resourceId, int progress, int max) { - setProgress(mContext.getString(resourceId), progress, max); - } - - public void setProgress(int progress, int max) { - this.setP - } - - public void setProgress(String message, int progress, int max) { - Message msg = new Message(); - Bundle data = new Bundle(); - data.putInt(Constants.extras.STATUS, Id.message.progress_update); - data.putString(Constants.extras.MESSAGE, message); - data.putInt(Constants.extras.PROGRESS, progress); - data.putInt(Constants.extras.PROGRESS_MAX, max); - msg.setData(data); - mHandler.sendMessage(msg); - } - -} diff --git a/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialogFragment.java b/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialogFragment.java index 5bc5b1ced..63d8f5907 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialogFragment.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/ProgressDialogFragment.java @@ -1,6 +1,20 @@ -package org.thialfihar.android.apg.ui; +/* + * 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. + */ -import org.thialfihar.android.apg.R; +package org.thialfihar.android.apg.ui; import android.app.Activity; import android.app.Dialog; @@ -13,27 +27,68 @@ import android.view.KeyEvent; public class ProgressDialogFragment extends DialogFragment { - public static final int ID_ENCRYPTING = 1; - public static final int ID_DECRYPTING = 2; - public static final int ID_SAVING = 3; - public static final int ID_IMPORTING = 4; - public static final int ID_EXPORTING = 5; - public static final int ID_DELETING = 6; - public static final int ID_QUERYING = 7; - public static final int ID_SIGNING = 8; + private static final String ARG_MESSAGE_ID = "message_id"; + private static final String ARG_STYLE = "style"; - public static ProgressDialogFragment newInstance(int id) { + /** + * Instantiates new instance of this fragment + * + * @param id + * @return + */ + public static ProgressDialogFragment newInstance(int messageId, int style) { ProgressDialogFragment frag = new ProgressDialogFragment(); Bundle args = new Bundle(); - args.putInt("id", id); + args.putInt(ARG_MESSAGE_ID, messageId); + args.putInt(ARG_STYLE, style); + frag.setArguments(args); return frag; } - public static void test() { - + /** + * Updates progress of dialog + * + * @param messageId + * @param progress + * @param max + */ + public void setProgress(int messageId, int progress, int max) { + setProgress(getString(messageId), progress, max); } + /** + * Updates progress of dialog + * + * @param messageId + * @param progress + * @param max + */ + public void setProgress(int progress, int max) { + ProgressDialog dialog = (ProgressDialog) getDialog(); + + dialog.setProgress(progress); + dialog.setMax(max); + } + + /** + * Updates progress of dialog + * + * @param messageId + * @param progress + * @param max + */ + public void setProgress(String message, int progress, int max) { + ProgressDialog dialog = (ProgressDialog) getDialog(); + + dialog.setMessage(message); + dialog.setProgress(progress); + dialog.setMax(max); + } + + /** + * Creates dialog based on arguments (messageId, style) + */ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Activity activity = getActivity(); @@ -41,57 +96,28 @@ public class ProgressDialogFragment extends DialogFragment { ProgressDialog dialog = new ProgressDialog(activity); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); + dialog.setCanceledOnTouchOutside(false); - int id = getArguments().getInt("id"); + int messageId = getArguments().getInt(ARG_MESSAGE_ID); + int style = getArguments().getInt(ARG_STYLE); - switch (id) { - case ID_ENCRYPTING: - dialog.setMessage(this.getString(R.string.progress_initializing)); - - case ID_DECRYPTING: - dialog.setMessage(this.getString(R.string.progress_initializing)); - - case ID_SAVING: - dialog.setMessage(this.getString(R.string.progress_saving)); - - case ID_IMPORTING: - dialog.setMessage(this.getString(R.string.progress_importing)); - - case ID_EXPORTING: - dialog.setMessage(this.getString(R.string.progress_exporting)); - - case ID_DELETING: - dialog.setMessage(this.getString(R.string.progress_initializing)); - - case ID_QUERYING: - dialog.setMessage(this.getString(R.string.progress_querying)); - dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); - dialog.setCancelable(false); - - case ID_SIGNING: - dialog.setMessage(this.getString(R.string.progress_signing)); - dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); - dialog.setCancelable(false); - - default: - break; - - } + dialog.setMessage(getString(messageId)); + dialog.setProgressStyle(style); // Disable the back button - // OnKeyListener keyListener = new OnKeyListener() { - // - // @Override - // public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { - // - // if (keyCode == KeyEvent.KEYCODE_BACK) { - // return true; - // } - // return false; - // } - // - // }; - // dialog.setOnKeyListener(keyListener); + OnKeyListener keyListener = new OnKeyListener() { + + @Override + public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { + + if (keyCode == KeyEvent.KEYCODE_BACK) { + return true; + } + return false; + } + + }; + dialog.setOnKeyListener(keyListener); return dialog; } diff --git a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java index 8f55c9133..895e2b5a6 100644 --- a/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java +++ b/org_apg/src/org/thialfihar/android/apg/ui/widget/SectionView.java @@ -16,44 +16,41 @@ package org.thialfihar.android.apg.ui.widget; -import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPSecretKey; import org.thialfihar.android.apg.Apg; import org.thialfihar.android.apg.Id; +import org.thialfihar.android.apg.service.ApgHandler; +import org.thialfihar.android.apg.service.ApgService; +import org.thialfihar.android.apg.ui.ProgressDialogFragment; import org.thialfihar.android.apg.ui.widget.Editor.EditorListener; import org.thialfihar.android.apg.util.Choice; +import org.thialfihar.android.apg.util.Utils; import org.thialfihar.android.apg.R; +import com.actionbarsherlock.app.SherlockFragmentActivity; + import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; import android.os.Bundle; -import android.os.Handler; import android.os.Message; +import android.os.Messenger; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.Spinner; -import android.widget.TableRow; import android.widget.TextView; -import android.widget.Toast; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; import java.util.Vector; -public class SectionView extends LinearLayout implements OnClickListener, EditorListener, Runnable { +public class SectionView extends LinearLayout implements OnClickListener, EditorListener { private LayoutInflater mInflater; private View mAdd; private ViewGroup mEditors; @@ -63,50 +60,18 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor private Choice mNewKeyAlgorithmChoice; private int mNewKeySize; - volatile private PGPSecretKey mNewKey; - private ProgressDialog mProgressDialog; - private Thread mRunningThread = null; + private SherlockFragmentActivity mActivity; - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - Bundle data = msg.getData(); - if (data != null) { - boolean closeProgressDialog = data.getBoolean("closeProgressDialog"); - if (closeProgressDialog) { - if (mProgressDialog != null) { - mProgressDialog.dismiss(); - mProgressDialog = null; - } - } - - String error = data.getString(Apg.EXTRA_ERROR); - if (error != null) { - Toast.makeText(getContext(), - getContext().getString(R.string.errorMessage, error), - Toast.LENGTH_SHORT).show(); - } - - boolean gotNewKey = data.getBoolean("gotNewKey"); - if (gotNewKey) { - KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, - mEditors, false); - view.setEditorListener(SectionView.this); - boolean isMasterKey = (mEditors.getChildCount() == 0); - view.setValue(mNewKey, isMasterKey, -1); - mEditors.addView(view); - SectionView.this.updateEditorsVisible(); - } - } - } - }; + private ProgressDialogFragment mGeneratingDialog; public SectionView(Context context) { super(context); + mActivity = (SherlockFragmentActivity) context; } public SectionView(Context context, AttributeSet attrs) { super(context, attrs); + mActivity = (SherlockFragmentActivity) context; } public ViewGroup getEditors() { @@ -281,51 +246,64 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor } private void createKey() { - mProgressDialog = new ProgressDialog(getContext()); - mProgressDialog.setMessage(getContext().getString(R.string.progress_generating)); - mProgressDialog.setCancelable(false); - mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); - mProgressDialog.show(); - mRunningThread = new Thread(this); - mRunningThread.start(); - } + // Send all information needed to service to edit key in other thread + Intent intent = new Intent(mActivity, ApgService.class); - public void run() { - String error = null; - try { - PGPSecretKey masterKey = null; - String passPhrase; - if (mEditors.getChildCount() > 0) { - masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); - passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID()); - } else { - passPhrase = ""; - } - mNewKey = Apg.createKey(getContext(), mNewKeyAlgorithmChoice.getId(), mNewKeySize, - passPhrase, masterKey); - } catch (NoSuchProviderException e) { - error = "" + e; - } catch (NoSuchAlgorithmException e) { - error = "" + e; - } catch (PGPException e) { - error = "" + e; - } catch (InvalidParameterException e) { - error = "" + e; - } catch (InvalidAlgorithmParameterException e) { - error = "" + e; - } catch (Apg.GeneralException e) { - error = "" + e; - } + intent.putExtra(ApgService.EXTRA_ACTION, ApgService.ACTION_GENERATE_KEY); - Message message = new Message(); + // fill values for this action Bundle data = new Bundle(); - data.putBoolean("closeProgressDialog", true); - if (error != null) { - data.putString(Apg.EXTRA_ERROR, error); + + String passPhrase; + if (mEditors.getChildCount() > 0) { + PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); + passPhrase = Apg.getCachedPassPhrase(masterKey.getKeyID()); + + data.putByteArray(ApgService.MASTER_KEY, Utils.PGPSecretKeyToBytes(masterKey)); } else { - data.putBoolean("gotNewKey", true); + passPhrase = ""; } - message.setData(data); - mHandler.sendMessage(message); + data.putString(ApgService.PASSPHRASE, passPhrase); + data.putInt(ApgService.ALGORITHM, mNewKeyAlgorithmChoice.getId()); + data.putInt(ApgService.KEY_SIZE, mNewKeySize); + + intent.putExtra(ApgService.EXTRA_DATA, data); + + // show progress dialog + mGeneratingDialog = ProgressDialogFragment.newInstance(R.string.progress_generating, + ProgressDialog.STYLE_SPINNER); + + // Message is received after generating is done in ApgService + ApgHandler saveHandler = new ApgHandler(mActivity, mGeneratingDialog) { + public void handleMessage(Message message) { + // handle messages by standard ApgHandler first + super.handleMessage(message); + + if (message.arg1 == ApgHandler.MESSAGE_OKAY) { + // get new key from data bundle returned from service + Bundle data = message.getData(); + PGPSecretKey newKey = Utils.BytesToPGPSecretKey(data + .getByteArray(ApgHandler.NEW_KEY)); + + // add view with new key + KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, + mEditors, false); + view.setEditorListener(SectionView.this); + boolean isMasterKey = (mEditors.getChildCount() == 0); + view.setValue(newKey, isMasterKey, -1); + mEditors.addView(view); + SectionView.this.updateEditorsVisible(); + } + }; + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(ApgService.EXTRA_MESSENGER, messenger); + + mGeneratingDialog.show(mActivity.getSupportFragmentManager(), "dialog"); + + // start service with intent + mActivity.startService(intent); } } diff --git a/org_apg/src/org/thialfihar/android/apg/util/Utils.java b/org_apg/src/org/thialfihar/android/apg/util/Utils.java index 4ea2a48af..13bfb7b91 100644 --- a/org_apg/src/org/thialfihar/android/apg/util/Utils.java +++ b/org_apg/src/org/thialfihar/android/apg/util/Utils.java @@ -19,10 +19,19 @@ package org.thialfihar.android.apg.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; +import java.util.Iterator; +import java.util.Vector; + +import org.spongycastle.openpgp.PGPObjectFactory; +import org.spongycastle.openpgp.PGPSecretKey; +import org.spongycastle.openpgp.PGPSecretKeyRing; +import org.thialfihar.android.apg.Constants; import android.content.Context; +import android.util.Log; public class Utils { @@ -72,4 +81,69 @@ public class Utils { return numDays; } + /** + * Converts Vector to a byte[] array to send it by intent to service + * + * @param keys + * @return + */ + public static byte[] PGPSecretKeyListToBytes(Vector keys) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + for (PGPSecretKey key : keys) { + try { + key.encode(os); + } catch (IOException e) { + Log.e(Constants.TAG, + "Error while converting PGPSecretKey to byte[]: " + e.getMessage()); + e.printStackTrace(); + } + } + + byte[] keysBytes = os.toByteArray(); + + return keysBytes; + } + + /** + * Convert from byte[] to ArrayList + * + * @param keysBytes + * @return + */ + public static ArrayList BytesToPGPSecretKeyList(byte[] keysBytes) { + PGPObjectFactory factory = new PGPObjectFactory(keysBytes); + PGPSecretKeyRing keyRing = null; + try { + if ((keyRing = (PGPSecretKeyRing) factory.nextObject()) == null) { + Log.e(Constants.TAG, "No keys given!"); + } + } catch (IOException e) { + e.printStackTrace(); + } + ArrayList keys = new ArrayList(); + + Iterator itr = keyRing.getSecretKeys(); + while (itr.hasNext()) { + keys.add(itr.next()); + } + + return keys; + } + + public static PGPSecretKey BytesToPGPSecretKey(byte[] keyBytes) { + PGPSecretKey key = BytesToPGPSecretKeyList(keyBytes).get(0); + + return key; + } + + public static byte[] PGPSecretKeyToBytes(PGPSecretKey key) { + try { + return key.getEncoded(); + } catch (IOException e) { + Log.e(Constants.TAG, "Encoding failed: ", e); + + return null; + } + } + }