diff options
Diffstat (limited to 'OpenPGP-Keychain/src/main/java/org')
21 files changed, 605 insertions, 351 deletions
diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 3904a91d8..302dbea0b 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -203,10 +203,18 @@ public class KeychainIntentService extends IntentService implements ProgressDial Messenger mMessenger; + private boolean mIsCanceled; + public KeychainIntentService() { super("ApgService"); } + @Override + public void onDestroy() { + super.onDestroy(); + this.mIsCanceled = true; + } + /** * The IntentService calls this method from the default worker thread with the intent that * started the service. When this method returns, IntentService stops the service, as @@ -815,6 +823,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial } private void sendErrorToHandler(Exception e) { + // Service was canceled. Do not send error to handler. + if (this.mIsCanceled) + return; + Log.e(Constants.TAG, "ApgService Exception: ", e); e.printStackTrace(); @@ -824,6 +836,10 @@ public class KeychainIntentService extends IntentService implements ProgressDial } private void sendMessageToHandler(Integer arg1, Integer arg2, Bundle data) { + // Service was canceled. Do not send message to handler. + if (this.mIsCanceled) + return; + Message msg = Message.obtain(); msg.arg1 = arg1; if (arg2 != null) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java index dfea7eb04..6eba9cc83 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java @@ -21,6 +21,8 @@ import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.R; import android.app.Activity; +import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -55,9 +57,15 @@ public class KeychainIntentServiceHandler extends Handler { } public KeychainIntentServiceHandler(Activity activity, int progressDialogMessageId, int progressDialogStyle) { + this(activity, progressDialogMessageId, progressDialogStyle, false, null); + } + + public KeychainIntentServiceHandler(Activity activity, int progressDialogMessageId, + int progressDialogStyle, boolean cancelable, + OnCancelListener onCancelListener) { this.mActivity = activity; this.mProgressDialogFragment = ProgressDialogFragment.newInstance(progressDialogMessageId, - progressDialogStyle); + progressDialogStyle, cancelable, onCancelListener); } public void showProgressDialog(FragmentActivity activity) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java index 6d8a8beb3..8c8e6f00a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/OpenPgpService.java @@ -28,7 +28,7 @@ import android.os.ParcelFileDescriptor; import org.openintents.openpgp.IOpenPgpService; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.OpenPgpSignatureResult; -import org.openintents.openpgp.util.OpenPgpConstants; +import org.openintents.openpgp.util.OpenPgpApi; import org.spongycastle.util.Arrays; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; @@ -48,7 +48,7 @@ public class OpenPgpService extends RemoteService { private static final int PRIVATE_REQUEST_CODE_PASSPHRASE = 551; private static final int PRIVATE_REQUEST_CODE_USER_IDS = 552; - + private static final int PRIVATE_REQUEST_CODE_GET_KEYS = 553; /** * Search database for key ids based on emails. @@ -56,7 +56,7 @@ public class OpenPgpService extends RemoteService { * @param encryptionUserIds * @return */ - private Bundle getKeyIdsFromEmails(Bundle params, String[] encryptionUserIds) { + private Intent getKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { // find key ids to given emails in database ArrayList<Long> keyIds = new ArrayList<Long>(); @@ -91,20 +91,20 @@ public class OpenPgpService extends RemoteService { // allow the user to verify pub key selection if (missingUserIdsCheck || dublicateUserIdsCheck) { - // build PendingIntent for passphrase input + // build PendingIntent Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS); intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray); intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_USER_IDS, missingUserIds); intent.putExtra(RemoteServiceActivity.EXTRA_DUBLICATE_USER_IDS, dublicateUserIds); - intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_USER_IDS, intent, 0); // return PendingIntent to be executed by client - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); return result; } @@ -113,44 +113,44 @@ public class OpenPgpService extends RemoteService { return null; } - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); - result.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIdsArray); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); + result.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keyIdsArray); return result; } - private Bundle getPassphraseBundleIntent(Bundle params, long keyId) { + private Intent getPassphraseBundleIntent(Intent data, long keyId) { // build PendingIntent for passphrase input Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_CACHE_PASSPHRASE); intent.putExtra(RemoteServiceActivity.EXTRA_SECRET_KEY_ID, keyId); // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_PASSPHRASE, intent, 0); // return PendingIntent to be executed by client - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); return result; } - private Bundle signImpl(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output, - AppSettings appSettings) { + private Intent signImpl(Intent data, ParcelFileDescriptor input, + ParcelFileDescriptor output, AppSettings appSettings) { try { - boolean asciiArmor = params.getBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true); + boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); // get passphrase from cache, if key has "no" passphrase, this returns an empty String String passphrase; - if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) { - passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE); + if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { + passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE); } else { passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId()); } if (passphrase == null) { // get PendingIntent for passphrase input, add it to given params and return to client - Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId()); + Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId()); return passphraseBundle; } @@ -174,43 +174,42 @@ public class OpenPgpService extends RemoteService { os.close(); } - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); return result; } catch (Exception e) { - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); return result; } } - private Bundle encryptAndSignImpl(Bundle params, ParcelFileDescriptor input, - ParcelFileDescriptor output, AppSettings appSettings, - boolean sign) { + private Intent encryptAndSignImpl(Intent data, ParcelFileDescriptor input, + ParcelFileDescriptor output, AppSettings appSettings, boolean sign) { try { - boolean asciiArmor = params.getBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true); + boolean asciiArmor = data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); long[] keyIds; - if (params.containsKey(OpenPgpConstants.PARAMS_KEY_IDS)) { - keyIds = params.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS); - } else if (params.containsKey(OpenPgpConstants.PARAMS_USER_IDS)) { + if (data.hasExtra(OpenPgpApi.EXTRA_KEY_IDS)) { + keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); + } else if (data.hasExtra(OpenPgpApi.EXTRA_USER_IDS)) { // get key ids based on given user ids - String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS); + String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); // give params through to activity... - Bundle result = getKeyIdsFromEmails(params, userIds); + Intent result = getKeyIdsFromEmails(data, userIds); - if (result.getInt(OpenPgpConstants.RESULT_CODE, 0) == OpenPgpConstants.RESULT_CODE_SUCCESS) { - keyIds = result.getLongArray(OpenPgpConstants.PARAMS_KEY_IDS); + if (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0) == OpenPgpApi.RESULT_CODE_SUCCESS) { + keyIds = result.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS); } else { // if not success -> result contains a PendingIntent for user interaction return result; } } else { - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, new OpenPgpError(OpenPgpError.GENERIC_ERROR, "Missing parameter user_ids or key_ids!")); return result; } @@ -235,15 +234,15 @@ public class OpenPgpService extends RemoteService { if (sign) { String passphrase; - if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) { - passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE); + if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { + passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE); } else { passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId()); } if (passphrase == null) { // get PendingIntent for passphrase input, add it to given params and return to client - Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId()); + Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId()); return passphraseBundle; } @@ -263,26 +262,26 @@ public class OpenPgpService extends RemoteService { os.close(); } - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); return result; } catch (Exception e) { - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); return result; } } - private Bundle decryptAndVerifyImpl(Bundle params, ParcelFileDescriptor input, + private Intent decryptAndVerifyImpl(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output, AppSettings appSettings) { try { // Get Input- and OutputStream from ParcelFileDescriptor InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(input); OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(output); - Bundle result = new Bundle(); + Intent result = new Intent(); try { // TODO: @@ -332,14 +331,14 @@ public class OpenPgpService extends RemoteService { // NOTE: currently this only gets the passphrase for the key set for this client String passphrase; - if (params.containsKey(OpenPgpConstants.PARAMS_PASSPHRASE)) { - passphrase = params.getString(OpenPgpConstants.PARAMS_PASSPHRASE); + if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { + passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE); } else { passphrase = PassphraseCacheService.getCachedPassphrase(getContext(), appSettings.getKeyId()); } if (passphrase == null) { // get PendingIntent for passphrase input, add it to given params and return to client - Bundle passphraseBundle = getPassphraseBundleIntent(params, appSettings.getKeyId()); + Intent passphraseBundle = getPassphraseBundleIntent(data, appSettings.getKeyId()); return passphraseBundle; } @@ -375,32 +374,46 @@ public class OpenPgpService extends RemoteService { signatureStatus = OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED; } else if (signatureUnknown) { signatureStatus = OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY; + + // If signature is unknown we return an additional PendingIntent + // to retrieve the missing key + // TODO!!! + Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); + intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE); + intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, "todo"); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); + + PendingIntent pi = PendingIntent.getActivity(getBaseContext(), + PRIVATE_REQUEST_CODE_GET_KEYS, intent, 0); + + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); } + OpenPgpSignatureResult sigResult = new OpenPgpSignatureResult(signatureStatus, signatureUserId, signatureOnly, signatureKeyId); - result.putParcelable(OpenPgpConstants.RESULT_SIGNATURE, sigResult); + result.putExtra(OpenPgpApi.RESULT_SIGNATURE, sigResult); } } finally { is.close(); os.close(); } - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_SUCCESS); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); return result; } catch (Exception e) { - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); return result; } } - private Bundle getKeyIdsImpl(Bundle params) { + private Intent getKeyIdsImpl(Intent data) { // get key ids based on given user ids - String[] userIds = params.getStringArray(OpenPgpConstants.PARAMS_USER_IDS); - Bundle result = getKeyIdsFromEmails(params, userIds); + String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); + Intent result = getKeyIdsFromEmails(data, userIds); return result; } @@ -410,30 +423,30 @@ public class OpenPgpService extends RemoteService { * - has supported API version * - is allowed to call the service (access has been granted) * - * @param params + * @param data * @return null if everything is okay, or a Bundle with an error/PendingIntent */ - private Bundle checkRequirements(Bundle params) { + private Intent checkRequirements(Intent data) { // params Bundle is required! - if (params == null) { - Bundle result = new Bundle(); + if (data == null) { + Intent result = new Intent(); OpenPgpError error = new OpenPgpError(OpenPgpError.GENERIC_ERROR, "params Bundle required!"); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, error); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, error); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); return result; } // version code is required and needs to correspond to version code of service! - if (params.getInt(OpenPgpConstants.PARAMS_API_VERSION) != OpenPgpConstants.API_VERSION) { - Bundle result = new Bundle(); + if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) != OpenPgpApi.API_VERSION) { + Intent result = new Intent(); OpenPgpError error = new OpenPgpError(OpenPgpError.INCOMPATIBLE_API_VERSIONS, "Incompatible API versions!"); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, error); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, error); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); return result; } // check if caller is allowed to access openpgp keychain - Bundle result = isAllowed(params); + Intent result = isAllowed(data); if (result != null) { return result; } @@ -445,61 +458,31 @@ public class OpenPgpService extends RemoteService { private final IOpenPgpService.Stub mBinder = new IOpenPgpService.Stub() { @Override - public Bundle sign(Bundle params, final ParcelFileDescriptor input, final ParcelFileDescriptor output) { - final AppSettings appSettings = getAppSettings(); - - Bundle errorResult = checkRequirements(params); - if (errorResult != null) { - return errorResult; - } - - return signImpl(params, input, output, appSettings); - } - - @Override - public Bundle encrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) { - final AppSettings appSettings = getAppSettings(); - - Bundle errorResult = checkRequirements(params); + public Intent execute(Intent data, ParcelFileDescriptor input, ParcelFileDescriptor output) { + Intent errorResult = checkRequirements(data); if (errorResult != null) { return errorResult; } - return encryptAndSignImpl(params, input, output, appSettings, false); - } - - @Override - public Bundle signAndEncrypt(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) { final AppSettings appSettings = getAppSettings(); - Bundle errorResult = checkRequirements(params); - if (errorResult != null) { - return errorResult; - } - - return encryptAndSignImpl(params, input, output, appSettings, true); - } - - @Override - public Bundle decryptAndVerify(Bundle params, ParcelFileDescriptor input, ParcelFileDescriptor output) { - final AppSettings appSettings = getAppSettings(); - - Bundle errorResult = checkRequirements(params); - if (errorResult != null) { - return errorResult; - } - - return decryptAndVerifyImpl(params, input, output, appSettings); - } - - @Override - public Bundle getKeyIds(Bundle params) { - Bundle errorResult = checkRequirements(params); - if (errorResult != null) { - return errorResult; + String action = data.getAction(); + if (OpenPgpApi.ACTION_SIGN.equals(action)) { + return signImpl(data, input, output, appSettings); + } else if (OpenPgpApi.ACTION_ENCRYPT.equals(action)) { + return encryptAndSignImpl(data, input, output, appSettings, false); + } else if (OpenPgpApi.ACTION_SIGN_AND_ENCTYPT.equals(action)) { + return encryptAndSignImpl(data, input, output, appSettings, true); + } else if (OpenPgpApi.ACTION_DECRYPT_VERIFY.equals(action)) { + return decryptAndVerifyImpl(data, input, output, appSettings); + } else if (OpenPgpApi.ACTION_DOWNLOAD_KEYS.equals(action)) { + // TODO! + return null; + } else if (OpenPgpApi.ACTION_GET_KEY_IDS.equals(action)) { + return getKeyIdsImpl(data); + } else { + return null; } - - return getKeyIdsImpl(params); } }; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java index cfd2b9ec3..e7b3b2945 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteService.java @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; import org.openintents.openpgp.OpenPgpError; -import org.openintents.openpgp.util.OpenPgpConstants; +import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.provider.KeychainContract; @@ -38,10 +38,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; /** * Abstract service class for remote APIs that handle app registration and user input. @@ -57,7 +53,7 @@ public abstract class RemoteService extends Service { return mContext; } - protected Bundle isAllowed(Bundle params) { + protected Intent isAllowed(Intent data) { try { if (isCallerAllowed(false)) { @@ -74,9 +70,9 @@ public abstract class RemoteService extends Service { } catch (NameNotFoundException e) { Log.e(Constants.TAG, "Should not happen, returning!", e); // return error - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_ERROR); - result.putParcelable(OpenPgpConstants.RESULT_ERRORS, + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR); + result.putExtra(OpenPgpApi.RESULT_ERRORS, new OpenPgpError(OpenPgpError.GENERIC_ERROR, e.getMessage())); return result; } @@ -86,14 +82,14 @@ public abstract class RemoteService extends Service { intent.setAction(RemoteServiceActivity.ACTION_REGISTER); intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName); intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageSignature); - intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_REGISTER, intent, 0); // return PendingIntent to be executed by client - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); return result; } @@ -103,14 +99,14 @@ public abstract class RemoteService extends Service { Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class); intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE); intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE, getString(R.string.api_error_wrong_signature)); - intent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); + intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), PRIVATE_REQUEST_CODE_ERROR, intent, 0); // return PendingIntent to be executed by client - Bundle result = new Bundle(); - result.putInt(OpenPgpConstants.RESULT_CODE, OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED); - result.putParcelable(OpenPgpConstants.RESULT_INTENT, pi); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); return result; } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java index af8e3ade8..11b3ee217 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/remote/RemoteServiceActivity.java @@ -25,7 +25,7 @@ import android.os.Messenger; import android.support.v7.app.ActionBarActivity; import android.view.View; -import org.openintents.openpgp.util.OpenPgpConstants; +import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.htmltextview.HtmlTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; @@ -51,6 +51,8 @@ public class RemoteServiceActivity extends ActionBarActivity { public static final String EXTRA_MESSENGER = "messenger"; + public static final String EXTRA_DATA = "data"; + // passphrase action public static final String EXTRA_SECRET_KEY_ID = "secret_key_id"; // register action @@ -100,12 +102,9 @@ public class RemoteServiceActivity extends ActionBarActivity { ProviderHelper.insertApiApp(RemoteServiceActivity.this, mSettingsFragment.getAppSettings()); - // give params through for new service call - Bundle oldParams = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS); - - Intent finishIntent = new Intent(); - finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, oldParams); - RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent); + // give data through for new service call + Intent resultData = extras.getParcelable(EXTRA_DATA); + RemoteServiceActivity.this.setResult(RESULT_OK, resultData); RemoteServiceActivity.this.finish(); } } @@ -128,9 +127,9 @@ public class RemoteServiceActivity extends ActionBarActivity { mSettingsFragment.setAppSettings(settings); } else if (ACTION_CACHE_PASSPHRASE.equals(action)) { long secretKeyId = extras.getLong(EXTRA_SECRET_KEY_ID); - Bundle oldParams = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS); + Intent resultData = extras.getParcelable(EXTRA_DATA); - showPassphraseDialog(oldParams, secretKeyId); + showPassphraseDialog(resultData, secretKeyId); } else if (ACTION_SELECT_PUB_KEYS.equals(action)) { long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS); ArrayList<String> missingUserIds = intent @@ -167,13 +166,11 @@ public class RemoteServiceActivity extends ActionBarActivity { @Override public void onClick(View v) { // add key ids to params Bundle for new request - Bundle params = extras.getBundle(OpenPgpConstants.PI_RESULT_PARAMS); - params.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, + Intent resultData = extras.getParcelable(EXTRA_DATA); + resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS, mSelectFragment.getSelectedMasterKeyIds()); - Intent finishIntent = new Intent(); - finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); - RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent); + RemoteServiceActivity.this.setResult(RESULT_OK, resultData); RemoteServiceActivity.this.finish(); } }, R.string.btn_do_not_save, new View.OnClickListener() { @@ -222,7 +219,7 @@ public class RemoteServiceActivity extends ActionBarActivity { @Override public void onClick(View v) { - RemoteServiceActivity.this.setResult(RESULT_OK); + RemoteServiceActivity.this.setResult(RESULT_CANCELED); RemoteServiceActivity.this.finish(); } }); @@ -244,16 +241,14 @@ public class RemoteServiceActivity extends ActionBarActivity { * encryption. Based on mSecretKeyId it asks for a passphrase to open a private key or it asks * for a symmetric passphrase */ - private void showPassphraseDialog(final Bundle params, long secretKeyId) { + private void showPassphraseDialog(final Intent data, 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) { // return given params again, for calling the service method again - Intent finishIntent = new Intent(); - finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); - RemoteServiceActivity.this.setResult(RESULT_OK, finishIntent); + RemoteServiceActivity.this.setResult(RESULT_OK, data); } else { RemoteServiceActivity.this.setResult(RESULT_CANCELED); } @@ -273,9 +268,7 @@ public class RemoteServiceActivity extends ActionBarActivity { } catch (PgpGeneralException e) { Log.d(Constants.TAG, "No passphrase for this secret key, do pgp operation directly!"); // return given params again, for calling the service method again - Intent finishIntent = new Intent(); - finishIntent.putExtra(OpenPgpConstants.PI_RESULT_PARAMS, params); - setResult(RESULT_OK, finishIntent); + setResult(RESULT_OK, data); finish(); } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 73426e32d..0bed6f264 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -44,8 +44,10 @@ import org.sufficientlysecure.keychain.ui.widget.UserIdEditor; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; +import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -173,7 +175,7 @@ public class EditKeyActivity extends ActionBarActivity { if (generateDefaultKeys) { // Send all information needed to service generate keys in other thread - Intent serviceIntent = new Intent(this, KeychainIntentService.class); + final Intent serviceIntent = new Intent(this, KeychainIntentService.class); serviceIntent.setAction(KeychainIntentService.ACTION_GENERATE_DEFAULT_RSA_KEYS); // fill values for this action @@ -185,7 +187,19 @@ public class EditKeyActivity extends ActionBarActivity { // Message is received after generating is done in ApgService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( - this, R.string.progress_generating, ProgressDialog.STYLE_SPINNER) { + this, R.string.progress_generating, ProgressDialog.STYLE_SPINNER, true, + + new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + // Stop key generation on cancel + stopService(serviceIntent); + EditKeyActivity.this.setResult(Activity.RESULT_CANCELED); + EditKeyActivity.this.finish(); + } + }) { + + @Override public void handleMessage(Message message) { // handle messages by standard ApgHandler first super.handleMessage(message); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index a5027ac1c..5ac421a44 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -17,22 +17,9 @@ package org.sufficientlysecure.keychain.ui; -import java.util.ArrayList; -import java.util.Locale; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; -import org.sufficientlysecure.keychain.util.Log; - import android.annotation.SuppressLint; -import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.nfc.NdefMessage; @@ -51,6 +38,18 @@ import android.widget.ArrayAdapter; import com.beardedhen.androidbootstrap.BootstrapButton; import com.devspark.appmsg.AppMsg; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; +import org.sufficientlysecure.keychain.ui.dialog.BadImportKeyDialogFragment; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.ArrayList; +import java.util.Locale; + public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNavigationListener { public static final String ACTION_IMPORT_KEY = Constants.INTENT_PREFIX + "IMPORT_KEY"; public static final String ACTION_IMPORT_KEY_FROM_QR_CODE = Constants.INTENT_PREFIX @@ -236,10 +235,10 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa * inside your Activity." * <p/> * from http://stackoverflow.com/questions/10983396/fragment-oncreateview-and-onactivitycreated-called-twice/14295474#14295474 - * + * <p/> * In our case, if we start ImportKeysActivity with parameters to directly search using a fingerprint, * the fragment would be loaded twice resulting in the query being empty after the second load. - * + * <p/> * Our solution: * To prevent that a fragment will be loaded again even if it was already loaded loadNavFragment * checks against mCurrentNavPostition. @@ -395,23 +394,8 @@ public class ImportKeysActivity extends DrawerActivity implements ActionBar.OnNa AppMsg.makeText(ImportKeysActivity.this, toastMessage, AppMsg.STYLE_INFO) .show(); if (bad > 0) { - AlertDialog.Builder alert = new AlertDialog.Builder( - ImportKeysActivity.this); - - alert.setIcon(android.R.drawable.ic_dialog_alert); - alert.setTitle(R.string.warning); - - alert.setMessage(ImportKeysActivity.this.getResources() - .getQuantityString(R.plurals.bad_keys_encountered, bad, bad)); - - alert.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - alert.setCancelable(true); - alert.create().show(); + BadImportKeyDialogFragment badImportKeyDialogFragment = BadImportKeyDialogFragment.newInstance(bad); + badImportKeyDialogFragment.show(getSupportFragmentManager(), "badKeyDialog"); } } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index b52de5bc9..1118f0264 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -27,11 +27,13 @@ import java.util.List; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader; import org.sufficientlysecure.keychain.util.InputData; +import org.sufficientlysecure.keychain.util.KeyServer; import org.sufficientlysecure.keychain.util.Log; import android.app.Activity; @@ -42,10 +44,11 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.view.View; import android.widget.ListView; -import android.widget.Toast; + +import com.devspark.appmsg.AppMsg; public class ImportKeysListFragment extends ListFragment implements - LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> { + LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { private static final String ARG_DATA_URI = "uri"; private static final String ARG_BYTES = "bytes"; private static final String ARG_SERVER_QUERY = "query"; @@ -181,11 +184,10 @@ public class ImportKeysListFragment extends ListFragment implements } @Override - public Loader<List<ImportKeysListEntry>> onCreateLoader(int id, Bundle args) { + public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> onCreateLoader(int id, Bundle args) { switch (id) { case LOADER_ID_BYTES: { InputData inputData = getInputData(mKeyBytes, mDataUri); - return new ImportKeysListLoader(mActivity, inputData); } case LOADER_ID_SERVER_QUERY: { @@ -198,15 +200,15 @@ public class ImportKeysListFragment extends ListFragment implements } @Override - public void onLoadFinished(Loader<List<ImportKeysListEntry>> loader, - List<ImportKeysListEntry> data) { + public void onLoadFinished(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader, + AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) { // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) - Log.d(Constants.TAG, "data: " + data); + Log.d(Constants.TAG, "data: " + data.getResult()); // swap in the real data! - mAdapter.setData(data); + mAdapter.setData(data.getResult()); mAdapter.notifyDataSetChanged(); setListAdapter(mAdapter); @@ -222,11 +224,25 @@ public class ImportKeysListFragment extends ListFragment implements break; case LOADER_ID_SERVER_QUERY: - Toast.makeText( - getActivity(), getResources().getQuantityString(R.plurals.keys_found, - mAdapter.getCount(), mAdapter.getCount()), - Toast.LENGTH_SHORT - ).show(); + + Exception error = data.getError(); + + if(error == null){ + AppMsg.makeText( + getActivity(), getResources().getQuantityString(R.plurals.keys_found, + mAdapter.getCount(), mAdapter.getCount()), + AppMsg.STYLE_INFO + ).show(); + } else if(error instanceof KeyServer.InsufficientQuery){ + AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query, + AppMsg.STYLE_ALERT).show(); + }else if(error instanceof KeyServer.QueryException){ + AppMsg.makeText(getActivity(), R.string.error_keyserver_query, + AppMsg.STYLE_ALERT).show(); + }else if(error instanceof KeyServer.TooManyResponses){ + AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses, + AppMsg.STYLE_ALERT).show(); + } break; default: @@ -235,7 +251,7 @@ public class ImportKeysListFragment extends ListFragment implements } @Override - public void onLoaderReset(Loader<List<ImportKeysListEntry>> loader) { + public void onLoaderReset(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader) { switch (loader.getId()) { case LOADER_ID_BYTES: // Clear the data in the adapter. diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java index c28d57627..0afa556cb 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java @@ -33,6 +33,7 @@ import se.emilsjolander.stickylistheaders.ApiLevelTooLowException; import se.emilsjolander.stickylistheaders.StickyListHeadersListView; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -276,7 +277,8 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte viewIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(id))); startActivity(viewIntent); } - + + @TargetApi(11) public void encrypt(ActionMode mode, long[] keyRingRowIds) { // get master key ids from row ids long[] keyRingIds = new long[keyRingRowIds.length]; @@ -298,6 +300,7 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte * * @param keyRingRowIds */ + @TargetApi(11) public void showDeleteKeyDialog(final ActionMode mode, long[] keyRingRowIds) { // Message is received after key is deleted Handler returnHandler = new Handler() { @@ -332,4 +335,4 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog"); } -}
\ No newline at end of file +} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java index f9d267f27..7bb77b60f 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java @@ -29,6 +29,7 @@ import org.sufficientlysecure.keychain.ui.adapter.KeyListSecretAdapter; import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.content.Intent; import android.database.Cursor; import android.net.Uri; @@ -209,6 +210,7 @@ public class KeyListSecretFragment extends ListFragment implements * * @param keyRingRowIds */ + @TargetApi(11) public void showDeleteKeyDialog(final ActionMode mode, long[] keyRingRowIds) { // Message is received after key is deleted Handler returnHandler = new Handler() { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/AsyncTaskResultWrapper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/AsyncTaskResultWrapper.java new file mode 100644 index 000000000..2ac19c1d9 --- /dev/null +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/AsyncTaskResultWrapper.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +/** + * The AsyncTaskResultWrapper is used to wrap a result from a AsyncTask (for example: Loader). + * You can pass the result and an exception in it if an error occurred. + * Concept found at: + * https://stackoverflow.com/questions/19593577/how-to-handle-errors-in-custom-asynctaskloader + * @param <T> - Typ of the result which is wrapped + */ +public class AsyncTaskResultWrapper <T>{ + + private final T result; + private final Exception error; + + public AsyncTaskResultWrapper(T result, Exception error){ + this.result = result; + this.error = error; + } + + public T getResult() { + return result; + } + + public Exception getError() { + return error; + } + +} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index 00ad8c957..29e418db7 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -33,12 +33,13 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream; import android.content.Context; import android.support.v4.content.AsyncTaskLoader; -public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> { +public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { Context mContext; InputData mInputData; ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>(); + AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper; public ImportKeysListLoader(Context context, InputData inputData) { super(context); @@ -47,15 +48,18 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEnt } @Override - public List<ImportKeysListEntry> loadInBackground() { + public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() { + + entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(data, null); + if (mInputData == null) { Log.e(Constants.TAG, "Input data is null!"); - return data; + return entryListWrapper; } generateListOfKeyrings(mInputData); - return data; + return entryListWrapper; } @Override @@ -77,7 +81,7 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEnt } @Override - public void deliverResult(List<ImportKeysListEntry> data) { + public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) { super.deliverResult(data); } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java index b3bc39127..3a3b6e58b 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListServerLoader.java @@ -26,15 +26,15 @@ import org.sufficientlysecure.keychain.util.KeyServer; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; -import java.util.List; -public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> { +public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { Context mContext; String mServerQuery; String mKeyServer; - ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>(); + private ArrayList<ImportKeysListEntry> entryList = new ArrayList<ImportKeysListEntry>(); + private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper; public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) { super(context); @@ -44,15 +44,18 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL } @Override - public List<ImportKeysListEntry> loadInBackground() { + public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() { + + entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null); + if (mServerQuery == null) { Log.e(Constants.TAG, "mServerQuery is null!"); - return data; + return entryListWrapper; } queryServer(mServerQuery, mKeyServer); - return data; + return entryListWrapper; } @Override @@ -74,7 +77,7 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL } @Override - public void deliverResult(List<ImportKeysListEntry> data) { + public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) { super.deliverResult(data); } @@ -87,13 +90,17 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL ArrayList<ImportKeysListEntry> searchResult = server.search(query); // add result to data - data.addAll(searchResult); + entryList.addAll(searchResult); + entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null); } catch (KeyServer.InsufficientQuery e) { Log.e(Constants.TAG, "InsufficientQuery", e); + entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e); } catch (KeyServer.QueryException e) { Log.e(Constants.TAG, "QueryException", e); + entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e); } catch (KeyServer.TooManyResponses e) { Log.e(Constants.TAG, "TooManyResponses", e); + entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e); } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/BadImportKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/BadImportKeyDialogFragment.java new file mode 100644 index 000000000..2b8cba857 --- /dev/null +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/BadImportKeyDialogFragment.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; + +import org.sufficientlysecure.keychain.R; + +public class BadImportKeyDialogFragment extends DialogFragment { + private static final String ARG_BAD_IMPORT = "bad_import"; + + /** + * Creates a new instance of this Bad Import Key DialogFragment + * + * @param bad + * @return + */ + public static BadImportKeyDialogFragment newInstance(int bad) { + BadImportKeyDialogFragment frag = new BadImportKeyDialogFragment(); + Bundle args = new Bundle(); + + args.putInt(ARG_BAD_IMPORT, bad); + frag.setArguments(args); + + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final FragmentActivity activity = getActivity(); + final int badImport = getArguments().getInt(ARG_BAD_IMPORT); + + AlertDialog.Builder alert = new AlertDialog.Builder(activity); + alert.setIcon(R.drawable.ic_dialog_alert_holo_light); + alert.setTitle(R.string.warning); + alert.setMessage(activity.getResources() + .getQuantityString(R.plurals.bad_keys_encountered, badImport, badImport)); + alert.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + } + }); + alert.setCancelable(true); + + return alert.create(); + } +} diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java new file mode 100644 index 000000000..98b677511 --- /dev/null +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CreateKeyDialogFragment.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Spinner; + +import org.sufficientlysecure.keychain.Id; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Choice; + +import java.util.Vector; + +public class CreateKeyDialogFragment extends DialogFragment { + + public interface OnAlgorithmSelectedListener { + public void onAlgorithmSelected(Choice algorithmChoice, int keySize); + } + + private static final String ARG_EDITOR_CHILD_COUNT = "child_count"; + + private int mNewKeySize; + private Choice mNewKeyAlgorithmChoice; + private OnAlgorithmSelectedListener mAlgorithmSelectedListener; + + public void setOnAlgorithmSelectedListener(OnAlgorithmSelectedListener listener) { + mAlgorithmSelectedListener = listener; + } + + public static CreateKeyDialogFragment newInstance(int mEditorChildCount) { + CreateKeyDialogFragment frag = new CreateKeyDialogFragment(); + Bundle args = new Bundle(); + + args.putInt(ARG_EDITOR_CHILD_COUNT, mEditorChildCount); + + frag.setArguments(args); + + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final FragmentActivity context = getActivity(); + final LayoutInflater mInflater; + + final int childCount = getArguments().getInt(ARG_EDITOR_CHILD_COUNT); + mInflater = context.getLayoutInflater(); + + AlertDialog.Builder dialog = new AlertDialog.Builder(context); + + View view = mInflater.inflate(R.layout.create_key_dialog, null); + dialog.setView(view); + dialog.setTitle(R.string.title_create_key); + + boolean wouldBeMasterKey = (childCount == 0); + + final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm); + Vector<Choice> choices = new Vector<Choice>(); + choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString( + R.string.dsa))); + if (!wouldBeMasterKey) { + choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString( + R.string.elgamal))); + } + + choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString( + R.string.rsa))); + + ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(context, + android.R.layout.simple_spinner_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + algorithm.setAdapter(adapter); + // make RSA the default + for (int i = 0; i < choices.size(); ++i) { + if (choices.get(i).getId() == Id.choice.algorithm.rsa) { + algorithm.setSelection(i); + break; + } + } + + final Spinner keySize = (Spinner) view.findViewById(R.id.create_key_size); + ArrayAdapter<CharSequence> keySizeAdapter = ArrayAdapter.createFromResource( + context, R.array.key_size_spinner_values, + android.R.layout.simple_spinner_item); + keySizeAdapter + .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + keySize.setAdapter(keySizeAdapter); + keySize.setSelection(3); // Default to 4096 for the key length + dialog.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface di, int id) { + di.dismiss(); + try { + int nKeyIndex = keySize.getSelectedItemPosition(); + switch (nKeyIndex) { + case 0: + mNewKeySize = 512; + break; + case 1: + mNewKeySize = 1024; + break; + case 2: + mNewKeySize = 2048; + break; + case 3: + mNewKeySize = 4096; + break; + } + } catch (NumberFormatException e) { + mNewKeySize = 0; + } + + mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem(); + mAlgorithmSelectedListener.onAlgorithmSelected(mNewKeyAlgorithmChoice, mNewKeySize); + } + }); + + dialog.setCancelable(true); + dialog.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface di, int id) { + di.dismiss(); + } + }); + + return dialog.create(); + } + +}
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java index f7e41daf7..cd8bc79a9 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java @@ -61,7 +61,8 @@ public class DeleteFileDialogFragment extends DialogFragment { AlertDialog.Builder alert = new AlertDialog.Builder(activity); - alert.setIcon(android.R.drawable.ic_dialog_alert); + + alert.setIcon(R.drawable.ic_dialog_alert_holo_light); alert.setTitle(R.string.warning); alert.setMessage(this.getString(R.string.file_delete_confirmation, deleteFile)); @@ -82,7 +83,7 @@ public class DeleteFileDialogFragment extends DialogFragment { intent.putExtra(KeychainIntentService.EXTRA_DATA, data); ProgressDialogFragment deletingDialog = ProgressDialogFragment.newInstance( - R.string.progress_deleting_securely, ProgressDialog.STYLE_HORIZONTAL); + R.string.progress_deleting_securely, ProgressDialog.STYLE_HORIZONTAL, false, null); // Message is received after deleting is done in ApgService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(activity, deletingDialog) { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java index 3c44bff81..dc40bab2a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java @@ -17,17 +17,6 @@ package org.sufficientlysecure.keychain.ui.dialog; -import org.spongycastle.openpgp.PGPPublicKeyRing; -import org.spongycastle.openpgp.PGPSecretKeyRing; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract; -import org.sufficientlysecure.keychain.provider.KeychainDatabase; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.util.Log; - import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; @@ -40,6 +29,14 @@ import android.os.RemoteException; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.Id; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainDatabase; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.util.Log; + import java.util.ArrayList; public class DeleteKeyDialogFragment extends DialogFragment { @@ -100,7 +97,7 @@ public class DeleteKeyDialogFragment extends DialogFragment { builder.setMessage(R.string.key_deletion_confirmation_multi); } - builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setIcon(R.drawable.ic_dialog_alert_holo_light); builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { @Override diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java index 9b5d233e8..6c62d14e0 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java @@ -21,28 +21,40 @@ import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnKeyListener; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.view.KeyEvent; +import org.sufficientlysecure.keychain.R; + public class ProgressDialogFragment extends DialogFragment { private static final String ARG_MESSAGE_ID = "message_id"; private static final String ARG_STYLE = "style"; + private static final String ARG_CANCELABLE = "cancelable"; + + private OnCancelListener mOnCancelListener; /** * Creates new instance of this fragment * - * @param id + * @param messageId + * @param style + * @param cancelable * @return */ - public static ProgressDialogFragment newInstance(int messageId, int style) { + public static ProgressDialogFragment newInstance(int messageId, int style, boolean cancelable, + OnCancelListener onCancelListener) { ProgressDialogFragment frag = new ProgressDialogFragment(); Bundle args = new Bundle(); args.putInt(ARG_MESSAGE_ID, messageId); args.putInt(ARG_STYLE, style); + args.putBoolean(ARG_CANCELABLE, cancelable); frag.setArguments(args); + frag.mOnCancelListener = onCancelListener; + return frag; } @@ -60,7 +72,6 @@ public class ProgressDialogFragment extends DialogFragment { /** * Updates progress of dialog * - * @param messageId * @param progress * @param max */ @@ -74,7 +85,7 @@ public class ProgressDialogFragment extends DialogFragment { /** * Updates progress of dialog * - * @param messageId + * @param message * @param progress * @param max */ @@ -86,12 +97,20 @@ public class ProgressDialogFragment extends DialogFragment { dialog.setMax(max); } + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + + if (this.mOnCancelListener != null) + this.mOnCancelListener.onCancel(dialog); + } + /** * Creates dialog */ @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - Activity activity = getActivity(); + final Activity activity = getActivity(); ProgressDialog dialog = new ProgressDialog(activity); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); @@ -100,10 +119,22 @@ public class ProgressDialogFragment extends DialogFragment { int messageId = getArguments().getInt(ARG_MESSAGE_ID); int style = getArguments().getInt(ARG_STYLE); + boolean cancelable = getArguments().getBoolean(ARG_CANCELABLE); dialog.setMessage(getString(messageId)); dialog.setProgressStyle(style); + if (cancelable) { + dialog.setButton(DialogInterface.BUTTON_NEGATIVE, + activity.getString(R.string.progress_cancel), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.cancel(); + } + }); + } + // Disable the back button OnKeyListener keyListener = new OnKeyListener() { diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java index 9f3270250..f26cd35c0 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java @@ -17,28 +17,26 @@ package org.sufficientlysecure.keychain.ui.dialog; -import java.util.ArrayList; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.QrCodeUtils; - import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.DialogFragment; -import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.util.QrCodeUtils; + +import java.util.ArrayList; + public class ShareQrCodeDialogFragment extends DialogFragment { private static final String ARG_KEY_URI = "uri"; private static final String ARG_FINGERPRINT_ONLY = "fingerprint_only"; diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index 9d3643914..a95d80a4e 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -16,20 +16,6 @@ package org.sufficientlysecure.keychain.ui.widget; -import java.util.Vector; - -import org.spongycastle.openpgp.PGPSecretKey; -import org.sufficientlysecure.keychain.Id; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; -import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; -import org.sufficientlysecure.keychain.util.Choice; - -import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; @@ -43,13 +29,25 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.LinearLayout; -import android.widget.Spinner; import android.widget.TextView; import com.beardedhen.androidbootstrap.BootstrapButton; +import org.spongycastle.openpgp.PGPSecretKey; +import org.sufficientlysecure.keychain.Id; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.PgpConversionHelper; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.ui.dialog.CreateKeyDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; +import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; +import org.sufficientlysecure.keychain.util.Choice; + +import java.util.Vector; + public class SectionView extends LinearLayout implements OnClickListener, EditorListener { private LayoutInflater mInflater; private BootstrapButton mPlusButton; @@ -149,84 +147,16 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor } case Id.type.key: { - AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); - - View view = mInflater.inflate(R.layout.create_key_dialog, null); - dialog.setView(view); - dialog.setTitle(R.string.title_create_key); - - boolean wouldBeMasterKey = (mEditors.getChildCount() == 0); - - final Spinner algorithm = (Spinner) view.findViewById(R.id.create_key_algorithm); - Vector<Choice> choices = new Vector<Choice>(); - choices.add(new Choice(Id.choice.algorithm.dsa, getResources().getString( - R.string.dsa))); - if (!wouldBeMasterKey) { - choices.add(new Choice(Id.choice.algorithm.elgamal, getResources().getString( - R.string.elgamal))); - } - - choices.add(new Choice(Id.choice.algorithm.rsa, getResources().getString( - R.string.rsa))); - - ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(getContext(), - android.R.layout.simple_spinner_item, choices); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - algorithm.setAdapter(adapter); - // make RSA the default - for (int i = 0; i < choices.size(); ++i) { - if (choices.get(i).getId() == Id.choice.algorithm.rsa) { - algorithm.setSelection(i); - break; + CreateKeyDialogFragment mCreateKeyDialogFragment = CreateKeyDialogFragment.newInstance(mEditors.getChildCount()); + mCreateKeyDialogFragment.setOnAlgorithmSelectedListener(new CreateKeyDialogFragment.OnAlgorithmSelectedListener() { + @Override + public void onAlgorithmSelected(Choice algorithmChoice, int keySize) { + mNewKeyAlgorithmChoice = algorithmChoice; + mNewKeySize = keySize; + createKey(); } - } - - final Spinner keySize = (Spinner) view.findViewById(R.id.create_key_size); - ArrayAdapter<CharSequence> keySizeAdapter = ArrayAdapter.createFromResource( - getContext(), R.array.key_size_spinner_values, - android.R.layout.simple_spinner_item); - keySizeAdapter - .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - keySize.setAdapter(keySizeAdapter); - keySize.setSelection(3); // Default to 4096 for the key length - dialog.setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - try { - int nKeyIndex = keySize.getSelectedItemPosition(); - switch (nKeyIndex) { - case 0: - mNewKeySize = 512; - break; - case 1: - mNewKeySize = 1024; - break; - case 2: - mNewKeySize = 2048; - break; - case 3: - mNewKeySize = 4096; - break; - } - } catch (NumberFormatException e) { - mNewKeySize = 0; - } - - mNewKeyAlgorithmChoice = (Choice) algorithm.getSelectedItem(); - createKey(); - } - }); - - dialog.setCancelable(true); - dialog.setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface di, int id) { - di.dismiss(); - } - }); - - dialog.create().show(); + }); + mCreateKeyDialogFragment.show(mActivity.getSupportFragmentManager(), "createKeyDialog"); break; } @@ -282,7 +212,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor private void createKey() { // Send all information needed to service to edit key in other thread - Intent intent = new Intent(mActivity, KeychainIntentService.class); + final Intent intent = new Intent(mActivity, KeychainIntentService.class); intent.setAction(KeychainIntentService.ACTION_GENERATE_KEY); @@ -309,7 +239,12 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor // show progress dialog mGeneratingDialog = ProgressDialogFragment.newInstance(R.string.progress_generating, - ProgressDialog.STYLE_SPINNER); + ProgressDialog.STYLE_SPINNER, true, new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + mActivity.stopService(intent); + } + }); // Message is received after generating is done in ApgService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(mActivity, diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java index 61fe13ffb..b94c42e90 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/util/HkpKeyServer.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.Locale; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -172,11 +173,11 @@ public class HkpKeyServer extends KeyServer { if (e.getCode() == 404) { return results; } else { - if (e.getData().toLowerCase().contains("no keys found")) { + if (e.getData().toLowerCase(Locale.US).contains("no keys found")) { return results; - } else if (e.getData().toLowerCase().contains("too many")) { + } else if (e.getData().toLowerCase(Locale.US).contains("too many")) { throw new TooManyResponses(); - } else if (e.getData().toLowerCase().contains("insufficient")) { + } else if (e.getData().toLowerCase(Locale.US).contains("insufficient")) { throw new InsufficientQuery(); } } |