From fcd27d2600711ccd32c000c6d58da19cb816a9bf Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Thu, 9 Jul 2015 22:51:20 +0530 Subject: implemented revocation on deletion --- .../keychain/operations/DeleteOperation.java | 18 +- .../keychain/operations/EditKeyOperation.java | 33 ++- .../keychain/operations/ExportOperation.java | 27 ++- .../keychain/operations/RevokeOperation.java | 124 ++++++++++ .../keychain/operations/results/DeleteResult.java | 16 +- .../keychain/operations/results/EditKeyResult.java | 2 +- .../operations/results/InputPendingResult.java | 10 +- .../operations/results/OperationResult.java | 7 + .../keychain/operations/results/RevokeResult.java | 100 ++++++++ .../keychain/pgp/UncachedKeyRing.java | 5 +- .../keychain/service/ExportKeyringParcel.java | 11 + .../keychain/service/KeychainService.java | 5 +- .../keychain/service/RevokeKeyringParcel.java | 47 ++++ .../keychain/service/SaveKeyringParcel.java | 34 +++ .../keychain/service/input/CryptoInputParcel.java | 9 +- .../service/input/RequiredInputParcel.java | 2 +- .../keychain/ui/DeleteKeyDialogActivity.java | 231 ++++++++++++++++++ .../keychain/ui/EditKeyFragment.java | 1 + .../keychain/ui/KeyListFragment.java | 70 +++--- .../keychain/ui/RevokeDeleteDialogActivity.java | 258 +++++++++++++++++++++ .../keychain/ui/ViewKeyActivity.java | 50 ++-- .../keychain/ui/base/CryptoOperationHelper.java | 34 +-- .../ui/dialog/DeleteKeyDialogFragment.java | 211 ----------------- 23 files changed, 1000 insertions(+), 305 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java index ac4a0da11..63c613aa6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java @@ -18,19 +18,29 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; +import android.net.Uri; import android.support.annotation.NonNull; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; import org.sufficientlysecure.keychain.operations.results.DeleteResult; +import org.sufficientlysecure.keychain.operations.results.InputPendingResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.Progressable; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ContactSyncAdapterService; import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.Log; /** An operation which implements a high level keyring delete operation. * @@ -48,12 +58,17 @@ public class DeleteOperation extends BaseOperation { @NonNull @Override - public DeleteResult execute(DeleteKeyringParcel deleteKeyringParcel, + public OperationResult execute(DeleteKeyringParcel deleteKeyringParcel, CryptoInputParcel cryptoInputParcel) { long[] masterKeyIds = deleteKeyringParcel.mMasterKeyIds; boolean isSecret = deleteKeyringParcel.mIsSecret; + return onlyDeleteKey(masterKeyIds, isSecret); + } + + private DeleteResult onlyDeleteKey(long[] masterKeyIds, boolean isSecret) { + OperationLog log = new OperationLog(); if (masterKeyIds.length == 0) { @@ -113,7 +128,6 @@ public class DeleteOperation extends BaseOperation { } return new DeleteResult(result, log, success, fail); - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index eafbff4bc..f8f7e79a3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -21,7 +21,10 @@ import android.content.Context; import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.operations.results.EditKeyResult; +import org.sufficientlysecure.keychain.operations.results.ExportResult; +import org.sufficientlysecure.keychain.operations.results.InputPendingResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; @@ -34,6 +37,7 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.service.ContactSyncAdapterService; +import org.sufficientlysecure.keychain.service.ExportKeyringParcel; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; @@ -58,8 +62,16 @@ public class EditKeyOperation extends BaseOperation { super(context, providerHelper, progressable, cancelled); } + /** + * Saves an edited key, and uploads it to a server atomically or otherwise as + * specified in saveParcel + * + * @param saveParcel primary input to the operation + * @param cryptoInput input that changes if user interaction is required + * @return the result of the operation + */ @NonNull - public OperationResult execute(SaveKeyringParcel saveParcel, CryptoInputParcel cryptoInput) { + public InputPendingResult execute(SaveKeyringParcel saveParcel, CryptoInputParcel cryptoInput) { OperationLog log = new OperationLog(); log.add(LogType.MSG_ED, 0); @@ -120,6 +132,24 @@ public class EditKeyOperation extends BaseOperation { // It's a success, so this must be non-null now UncachedKeyRing ring = modifyResult.getRing(); + if (saveParcel.isUpload()) { + ExportKeyringParcel exportKeyringParcel = + new ExportKeyringParcel(saveParcel.getUploadKeyserver(), ring); + ExportResult uploadResult = + new ExportOperation(mContext, mProviderHelper, mProgressable) + .execute(exportKeyringParcel, cryptoInput); + if (uploadResult.isPending()) { + return uploadResult; + } else if (!uploadResult.success() && saveParcel.isUploadAtomic()) { + // if atomic, update fail implies edit operation should also fail and not save + log.add(uploadResult, 2); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, saveParcel.mMasterKeyId); + } else { + // upload succeeded or not atomic so we continue + log.add(uploadResult, 2); + } + } + // Save the new keyring. SaveKeyringResult saveResult = mProviderHelper .saveSecretKeyRing(ring, new ProgressScaler(mProgressable, 60, 95, 100)); @@ -160,5 +190,4 @@ public class EditKeyOperation extends BaseOperation { return new EditKeyResult(EditKeyResult.RESULT_OK, log, ring.getMasterKeyId()); } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java index 56ed4ef58..0dec35949 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java @@ -34,6 +34,7 @@ import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.TextUtils; import org.spongycastle.bcpg.ArmoredOutputStream; @@ -42,6 +43,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; import org.sufficientlysecure.keychain.operations.results.ExportResult; +import org.sufficientlysecure.keychain.operations.results.InputPendingResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; @@ -128,6 +130,18 @@ public class ExportOperation extends BaseOperation { } } + /** + * returns null if no user input required for upload, an InputPendingResult otherwise + */ + @Nullable + public InputPendingResult getUploadPendingInput() { + if (!OrbotHelper.isOrbotInRequiredState(mContext)) { + return new ExportResult(null, + RequiredInputParcel.createOrbotRequiredOperation()); + } + return null; + } + public ExportResult exportToFile(long[] masterKeyIds, boolean exportSecret, String outputFile) { OperationLog log = new OperationLog(); @@ -351,10 +365,15 @@ public class ExportOperation extends BaseOperation { HkpKeyserver hkpKeyserver = new HkpKeyserver(exportInput.mKeyserver); try { - CanonicalizedPublicKeyRing keyring - = mProviderHelper.getCanonicalizedPublicKeyRing( - exportInput.mCanonicalizedPublicKeyringUri); - return uploadKeyRingToServer(hkpKeyserver, keyring, proxy); + if (exportInput.mCanonicalizedPublicKeyringUri != null) { + CanonicalizedPublicKeyRing keyring + = mProviderHelper.getCanonicalizedPublicKeyRing( + exportInput.mCanonicalizedPublicKeyringUri); + return uploadKeyRingToServer(hkpKeyserver, keyring, proxy); + } else { + return uploadKeyRingToServer(hkpKeyserver, exportInput.mUncachedKeyRing, + proxy); + } } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "error uploading key", e); return new ExportResult(ExportResult.RESULT_ERROR, new OperationLog()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java new file mode 100644 index 000000000..157e36e04 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java @@ -0,0 +1,124 @@ +package org.sufficientlysecure.keychain.operations; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.support.annotation.NonNull; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.operations.results.DeleteResult; +import org.sufficientlysecure.keychain.operations.results.InputPendingResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.operations.results.RevokeResult; +import org.sufficientlysecure.keychain.pgp.Progressable; +import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; +import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; +import org.sufficientlysecure.keychain.util.Log; + +public class RevokeOperation extends BaseOperation { + + public RevokeOperation(Context context, ProviderHelper providerHelper, Progressable progressable) { + super(context, providerHelper, progressable); + } + + @NonNull + @Override + public OperationResult execute(RevokeKeyringParcel revokeKeyringParcel, + CryptoInputParcel cryptoInputParcel) { + + long masterKeyId = revokeKeyringParcel.mMasterKeyId; + + OperationResult.OperationLog log = new OperationResult.OperationLog(); + log.add(OperationResult.LogType.MSG_REVOKE, 0, + KeyFormattingUtils.beautifyKeyId(masterKeyId)); + + try { + + Uri secretUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(masterKeyId); + CachedPublicKeyRing keyRing = mProviderHelper.getCachedPublicKeyRing(secretUri); + + // check if this is a master secret key we can work with + switch (keyRing.getSecretKeyType(masterKeyId)) { + case GNU_DUMMY: + log.add(OperationResult.LogType.MSG_EK_ERROR_DUMMY, 1); + return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId); + } + + SaveKeyringParcel saveKeyringParcel = getRevokedSaveKeyringParcel(masterKeyId, + keyRing.getFingerprint()); + + // all revoke operations are made atomic as of now + saveKeyringParcel.setUpdateOptions(revokeKeyringParcel.mUpload, true, + revokeKeyringParcel.mKeyserver); + + InputPendingResult revokeAndUploadResult = new EditKeyOperation(mContext, + mProviderHelper, mProgressable, mCancelled) + .execute(saveKeyringParcel, cryptoInputParcel); + + if (revokeAndUploadResult.isPending()) { + return revokeAndUploadResult; + } + + log.add(revokeAndUploadResult, 1); + + if (revokeAndUploadResult.success()) { + log.add(OperationResult.LogType.MSG_REVOKE_OK, 1); + return new RevokeResult(RevokeResult.RESULT_OK, log, masterKeyId); + } else { + log.add(OperationResult.LogType.MSG_REVOKE_KEY_FAIL, 1); + return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId); + } + + } catch (PgpKeyNotFoundException | ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, "could not find key to revoke", e); + log.add(OperationResult.LogType.MSG_REVOKE_KEY_FAIL, 1); + return new RevokeResult(RevokeResult.RESULT_ERROR, log, masterKeyId); + } + } + + private SaveKeyringParcel getRevokedSaveKeyringParcel(long masterKeyId, byte[] fingerprint) { + final String[] SUBKEYS_PROJECTION = new String[]{ + KeychainContract.Keys.KEY_ID + }; + final int INDEX_KEY_ID = 0; + + Uri keysUri = KeychainContract.Keys.buildKeysUri(masterKeyId); + Cursor subKeyCursor = + mContext.getContentResolver().query(keysUri, SUBKEYS_PROJECTION, null, null, null); + + SaveKeyringParcel saveKeyringParcel = + new SaveKeyringParcel(masterKeyId, fingerprint); + + // add all subkeys, for revocation + while (subKeyCursor != null && subKeyCursor.moveToNext()) { + saveKeyringParcel.mRevokeSubKeys.add(subKeyCursor.getLong(INDEX_KEY_ID)); + } + if (subKeyCursor != null) { + subKeyCursor.close(); + } + + final String[] USER_IDS_PROJECTION = new String[]{ + KeychainContract.UserPackets.USER_ID + }; + final int INDEX_USER_ID = 0; + + Uri userIdsUri = KeychainContract.UserPackets.buildUserIdsUri(masterKeyId); + Cursor userIdCursor = mContext.getContentResolver().query( + userIdsUri, USER_IDS_PROJECTION, null, null, null); + + while (userIdCursor != null && userIdCursor.moveToNext()) { + saveKeyringParcel.mRevokeUserIds.add(userIdCursor.getString(INDEX_USER_ID)); + } + if (userIdCursor != null) { + userIdCursor.close(); + } + + return saveKeyringParcel; + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java index 52ff8bf44..52c6e1491 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java @@ -21,8 +21,10 @@ package org.sufficientlysecure.keychain.operations.results; import android.app.Activity; import android.content.Intent; import android.os.Parcel; +import android.support.annotation.Nullable; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; import org.sufficientlysecure.keychain.ui.util.Notify; @@ -30,7 +32,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener; import org.sufficientlysecure.keychain.ui.util.Notify.Showable; import org.sufficientlysecure.keychain.ui.util.Notify.Style; -public class DeleteResult extends OperationResult { +public class DeleteResult extends InputPendingResult { final public int mOk, mFail; @@ -40,6 +42,18 @@ public class DeleteResult extends OperationResult { mFail = fail; } + /** + * used when more input is required + * @param log operation log upto point of required input, if any + * @param requiredInput represents input required + */ + public DeleteResult(@Nullable OperationLog log, RequiredInputParcel requiredInput) { + super(log, requiredInput); + // values are not to be used + mOk = -1; + mFail = -1; + } + /** Construct from a parcel - trivial because we have no extra data. */ public DeleteResult(Parcel source) { super(source); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java index 842b75c3b..b9407a864 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java @@ -20,7 +20,7 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; -public class EditKeyResult extends OperationResult { +public class EditKeyResult extends InputPendingResult { public final Long mMasterKeyId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java index 0b7aa6d03..5b982ca61 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import android.os.Parcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; public class InputPendingResult extends OperationResult { @@ -30,26 +31,33 @@ public class InputPendingResult extends OperationResult { public static final int RESULT_PENDING = RESULT_ERROR + 8; final RequiredInputParcel mRequiredInput; + // in case operation needs to add to/changes the cryptoInputParcel sent to it + final CryptoInputParcel mCryptoInputParcel; public InputPendingResult(int result, OperationLog log) { super(result, log); mRequiredInput = null; + mCryptoInputParcel = null; } - public InputPendingResult(OperationLog log, RequiredInputParcel requiredInput) { + public InputPendingResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { super(RESULT_PENDING, log); mRequiredInput = requiredInput; + mCryptoInputParcel = cryptoInputParcel; } public InputPendingResult(Parcel source) { super(source); mRequiredInput = source.readParcelable(getClass().getClassLoader()); + mCryptoInputParcel = source.readParcelable(getClass().getClassLoader()); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeParcelable(mRequiredInput, 0); + dest.writeParcelable(mCryptoInputParcel, 0); } public boolean isPending() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 88d04350c..5105b7fdc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -760,6 +760,13 @@ public abstract class OperationResult implements Parcelable { MSG_DEL_OK (LogLevel.OK, R.plurals.msg_del_ok), MSG_DEL_FAIL (LogLevel.WARN, R.plurals.msg_del_fail), + MSG_REVOKE_ERROR_EMPTY (LogLevel.ERROR, R.string.msg_revoke_error_empty), + MSG_REVOKE_ERROR_MULTI_SECRET (LogLevel.DEBUG, R.string.msg_revoke_error_multi_secret), + MSG_REVOKE_ERROR_NOT_FOUND (LogLevel.DEBUG, R.string.msg_revoke_error_multi_secret), + MSG_REVOKE (LogLevel.DEBUG, R.string.msg_revoke_key), + MSG_REVOKE_KEY_FAIL (LogLevel.WARN, R.string.msg_revoke_key_fail), + MSG_REVOKE_OK (LogLevel.OK, R.string.msg_revoke_ok), + // keybase verification MSG_KEYBASE_VERIFICATION(LogLevel.START, R.string.msg_keybase_verification), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java new file mode 100644 index 000000000..4b4892b05 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java @@ -0,0 +1,100 @@ +package org.sufficientlysecure.keychain.operations.results; + +import android.app.Activity; +import android.content.Intent; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.Nullable; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import org.sufficientlysecure.keychain.ui.LogDisplayActivity; +import org.sufficientlysecure.keychain.ui.LogDisplayFragment; +import org.sufficientlysecure.keychain.ui.util.Notify; + +public class RevokeResult extends InputPendingResult { + + public final long mMasterKeyId; + + public RevokeResult(int result, OperationLog log, long masterKeyId) { + super(result, log); + mMasterKeyId = masterKeyId; + } + + /** + * used when more input is required + * @param log operation log upto point of required input, if any + * @param requiredInput represents input required + */ + public RevokeResult(@Nullable OperationLog log, RequiredInputParcel requiredInput) { + super(log, requiredInput); + // we won't use these values + mMasterKeyId = -1; + } + + /** Construct from a parcel - trivial because we have no extra data. */ + public RevokeResult(Parcel source) { + super(source); + mMasterKeyId = source.readLong(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeLong(mMasterKeyId); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public RevokeResult createFromParcel(Parcel in) { + return new RevokeResult(in); + } + + @Override + public RevokeResult[] newArray(int size) { + return new RevokeResult[size]; + } + }; + + @Override + public Notify.Showable createNotify(final Activity activity) { + + int resultType = getResult(); + + String str; + int duration; + Notify.Style style; + + // Not an overall failure + if ((resultType & OperationResult.RESULT_ERROR) == 0) { + + duration = Notify.LENGTH_LONG; + + // New and updated keys + if (resultType == OperationResult.RESULT_OK) { + style = Notify.Style.OK; + str = activity.getString(R.string.revoke_ok); + } else { + duration = 0; + style = Notify.Style.ERROR; + str = "internal error"; + } + + } else { + duration = 0; + style = Notify.Style.ERROR; + str = activity.getString(R.string.revoke_fail); + } + + return Notify.create(activity, str, duration, style, new Notify.ActionListener() { + @Override + public void onAction() { + Intent intent = new Intent( + activity, LogDisplayActivity.class); + intent.putExtra(LogDisplayFragment.EXTRA_RESULT, RevokeResult.this); + activity.startActivity(intent); + } + }, R.string.snackbar_details); + + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index 7be61d9c8..f4a8fa494 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -18,6 +18,8 @@ package org.sufficientlysecure.keychain.pgp; +import android.os.Parcelable; + import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SignatureSubpacketTags; @@ -48,6 +50,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -78,7 +81,7 @@ import java.util.TreeSet; * */ @SuppressWarnings("unchecked") -public class UncachedKeyRing { +public class UncachedKeyRing implements Serializable { final PGPKeyRing mRing; final boolean mIsSecret; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java index ef5b48df3..a8b901ab0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java @@ -23,9 +23,12 @@ import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; + public class ExportKeyringParcel implements Parcelable { public String mKeyserver; public Uri mCanonicalizedPublicKeyringUri; + public UncachedKeyRing mUncachedKeyRing; public boolean mExportSecret; public long mMasterKeyIds[]; @@ -45,6 +48,12 @@ public class ExportKeyringParcel implements Parcelable { mCanonicalizedPublicKeyringUri = keyringUri; } + public ExportKeyringParcel(String keyserver, UncachedKeyRing uncachedKeyRing) { + mExportType = ExportType.UPLOAD_KEYSERVER; + mKeyserver = keyserver; + mUncachedKeyRing = uncachedKeyRing; + } + public ExportKeyringParcel(long[] masterKeyIds, boolean exportSecret, String outputFile) { mExportType = ExportType.EXPORT_FILE; mMasterKeyIds = masterKeyIds; @@ -62,6 +71,7 @@ public class ExportKeyringParcel implements Parcelable { protected ExportKeyringParcel(Parcel in) { mKeyserver = in.readString(); mCanonicalizedPublicKeyringUri = (Uri) in.readValue(Uri.class.getClassLoader()); + mUncachedKeyRing = (UncachedKeyRing) in.readValue(UncachedKeyRing.class.getClassLoader()); mExportSecret = in.readByte() != 0x00; mOutputFile = in.readString(); mOutputUri = (Uri) in.readValue(Uri.class.getClassLoader()); @@ -78,6 +88,7 @@ public class ExportKeyringParcel implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeString(mKeyserver); dest.writeValue(mCanonicalizedPublicKeyringUri); + dest.writeValue(mUncachedKeyRing); dest.writeByte((byte) (mExportSecret ? 0x01 : 0x00)); dest.writeString(mOutputFile); dest.writeValue(mOutputUri); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java index 1cd76b462..dca2a08c2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java @@ -37,6 +37,7 @@ import org.sufficientlysecure.keychain.operations.ExportOperation; import org.sufficientlysecure.keychain.operations.ImportOperation; import org.sufficientlysecure.keychain.operations.KeybaseVerificationOperation; import org.sufficientlysecure.keychain.operations.PromoteKeyOperation; +import org.sufficientlysecure.keychain.operations.RevokeOperation; import org.sufficientlysecure.keychain.operations.SignEncryptOperation; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; @@ -114,6 +115,8 @@ public class KeychainService extends Service implements Progressable { } else if (inputParcel instanceof SaveKeyringParcel) { op = new EditKeyOperation(outerThis, new ProviderHelper(outerThis), outerThis, mActionCanceled); + } else if (inputParcel instanceof RevokeKeyringParcel) { + op = new RevokeOperation(outerThis, new ProviderHelper(outerThis), outerThis); } else if (inputParcel instanceof CertifyActionsParcel) { op = new CertifyOperation(outerThis, new ProviderHelper(outerThis), outerThis, mActionCanceled); @@ -135,7 +138,7 @@ public class KeychainService extends Service implements Progressable { op = new KeybaseVerificationOperation(outerThis, new ProviderHelper(outerThis), outerThis); } else { - return; + throw new AssertionError("Unrecognized input parcel in KeychainService!"); } @SuppressWarnings("unchecked") // this is unchecked, we make sure it's the correct op above! diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java new file mode 100644 index 000000000..b5da31c59 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java @@ -0,0 +1,47 @@ +package org.sufficientlysecure.keychain.service; + +import android.os.Parcel; +import android.os.Parcelable; + +public class RevokeKeyringParcel implements Parcelable { + + final public long mMasterKeyId; + final public boolean mUpload; + final public String mKeyserver; + + public RevokeKeyringParcel(long masterKeyId, boolean upload, String keyserver) { + mMasterKeyId = masterKeyId; + mUpload = upload; + mKeyserver = keyserver; + } + + protected RevokeKeyringParcel(Parcel in) { + mMasterKeyId = in.readLong(); + mUpload = in.readByte() != 0x00; + mKeyserver = in.readString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(mMasterKeyId); + dest.writeByte((byte) (mUpload ? 0x01 : 0x00)); + dest.writeString(mKeyserver); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public RevokeKeyringParcel createFromParcel(Parcel in) { + return new RevokeKeyringParcel(in); + } + + @Override + public RevokeKeyringParcel[] newArray(int size) { + return new RevokeKeyringParcel[size]; + } + }; +} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 679f4f817..fcb95493b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -65,6 +65,11 @@ public class SaveKeyringParcel implements Parcelable { public Passphrase mCardPin; public Passphrase mCardAdminPin; + // private because they have to be set together with setUpdateOptions + private boolean mUpload; + private boolean mUploadAtomic; + private String mKeyserver; + public SaveKeyringParcel() { reset(); } @@ -86,6 +91,27 @@ public class SaveKeyringParcel implements Parcelable { mRevokeSubKeys = new ArrayList<>(); mCardPin = null; mCardAdminPin = null; + mUpload = false; + mUploadAtomic = false; + mKeyserver = null; + } + + public void setUpdateOptions(boolean upload, boolean uploadAtomic, String keysever) { + mUpload = upload; + mUploadAtomic = uploadAtomic; + mKeyserver = keysever; + } + + public boolean isUpload() { + return mUpload; + } + + public boolean isUploadAtomic() { + return mUploadAtomic; + } + + public String getUploadKeyserver() { + return mKeyserver; } public boolean isEmpty() { @@ -234,6 +260,10 @@ public class SaveKeyringParcel implements Parcelable { mCardPin = source.readParcelable(Passphrase.class.getClassLoader()); mCardAdminPin = source.readParcelable(Passphrase.class.getClassLoader()); + + mUpload = source.readByte() != 0; + mUploadAtomic = source.readByte() != 0; + mKeyserver = source.readString(); } @Override @@ -259,6 +289,10 @@ public class SaveKeyringParcel implements Parcelable { destination.writeParcelable(mCardPin, flags); destination.writeParcelable(mCardAdminPin, flags); + + destination.writeByte((byte) (mUpload ? 1 : 0)); + destination.writeByte((byte) (mUploadAtomic ? 1 : 0)); + destination.writeString(mKeyserver); } public static final Creator CREATOR = new Creator() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java index 96f54dd2f..d4cebe67c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java @@ -36,6 +36,8 @@ public class CryptoInputParcel implements Parcelable { final Date mSignatureTime; final Passphrase mPassphrase; // used to supply an explicit proxy to operations that require it + // this is not final so it can be added to an existing CryptoInputParcel + // (e.g) CertifyOperation with upload might require both passphrase and orbot to be enabled private ParcelableProxy mParcelableProxy; // this map contains both decrypted session keys and signed hashes to be @@ -45,30 +47,25 @@ public class CryptoInputParcel implements Parcelable { public CryptoInputParcel() { mSignatureTime = new Date(); mPassphrase = null; - mParcelableProxy = null; } public CryptoInputParcel(Date signatureTime, Passphrase passphrase) { mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = passphrase; - mParcelableProxy = null; } public CryptoInputParcel(Passphrase passphrase) { mSignatureTime = new Date(); mPassphrase = passphrase; - mParcelableProxy = null; } public CryptoInputParcel(Date signatureTime) { mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = null; - mParcelableProxy = null; } public CryptoInputParcel(ParcelableProxy parcelableProxy) { - mSignatureTime = new Date(); // just for compatibility with parcel-ing - mPassphrase = null; + this(); mParcelableProxy = parcelableProxy; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java index e378296a5..8eef8de8d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java @@ -15,7 +15,7 @@ import java.util.Date; public class RequiredInputParcel implements Parcelable { public enum RequiredInputType { - PASSPHRASE, PASSPHRASE_SYMMETRIC, NFC_SIGN, NFC_DECRYPT, NFC_MOVE_KEY_TO_CARD, ENABLE_ORBOT + PASSPHRASE, PASSPHRASE_SYMMETRIC, NFC_SIGN, NFC_DECRYPT, NFC_MOVE_KEY_TO_CARD, ENABLE_ORBOT, } public Date mSignatureTime; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java new file mode 100644 index 000000000..064d34e38 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -0,0 +1,231 @@ +package org.sufficientlysecure.keychain.ui; + +import android.app.Dialog; +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.os.RemoteException; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.DeleteResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.HashMap; + +public class DeleteKeyDialogActivity extends FragmentActivity + implements CryptoOperationHelper.Callback { + public static final String EXTRA_DELETE_MASTER_KEY_IDS = "extra_delete_master_key_ids"; + + private CryptoOperationHelper mDeleteOpHelper; + + private long[] mMasterKeyIds; + private boolean mHasSecret; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mDeleteOpHelper = new CryptoOperationHelper<>(DeleteKeyDialogActivity.this, + DeleteKeyDialogActivity.this, R.string.progress_deleting); + mDeleteOpHelper.onRestoreInstanceState(savedInstanceState); + + mMasterKeyIds = getIntent().getLongArrayExtra(EXTRA_DELETE_MASTER_KEY_IDS); + + Handler deleteDialogHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + if (msg.what == DeleteKeyDialogFragment.MESSAGE_PERFORM_DELETE) { + mHasSecret = msg.getData().getBoolean(DeleteKeyDialogFragment.MSG_HAS_SECRET); + mDeleteOpHelper.cryptoOperation(); + } + } + }; + + Messenger messenger = new Messenger(deleteDialogHandler); + + DeleteKeyDialogFragment deleteKeyDialogFragment + = DeleteKeyDialogFragment.newInstance(messenger, mMasterKeyIds); + + deleteKeyDialogFragment.show(getSupportFragmentManager(), "deleteKeyDialog"); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mDeleteOpHelper.onSaveInstanceState(outState); + } + + @Override + public DeleteKeyringParcel createOperationInput() { + return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret); + } + + @Override + public void onCryptoOperationSuccess(DeleteResult result) { + handleResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(DeleteResult result) { + handleResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + + public void handleResult(DeleteResult result) { + Intent intent = new Intent(); + intent.putExtra(OperationResult.EXTRA_RESULT, result); + setResult(RESULT_OK, intent); + finish(); + } + + public static class DeleteKeyDialogFragment extends DialogFragment { + + public static final String MSG_HAS_SECRET = "msg_has_secret"; + + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids"; + + public static final int MESSAGE_PERFORM_DELETE = 1; + + private TextView mMainMessage; + private View mInflateView; + + private Messenger mMessenger; + /** + * Creates new instance of this delete file dialog fragment + */ + public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] masterKeyIds) { + DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); + Bundle args = new Bundle(); + + args.putParcelable(ARG_MESSENGER, messenger); + args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds); + + frag.setArguments(args); + + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final FragmentActivity activity = getActivity(); + mMessenger = getArguments().getParcelable(ARG_MESSENGER); + + final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); + + ContextThemeWrapper theme = new ContextThemeWrapper(activity, + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(theme); + + // Setup custom View to display in AlertDialog + LayoutInflater inflater = activity.getLayoutInflater(); + mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null); + builder.setView(mInflateView); + + mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage); + + final boolean hasSecret; + + // If only a single key has been selected + if (masterKeyIds.length == 1) { + long masterKeyId = masterKeyIds[0]; + + try { + HashMap data = new ProviderHelper(activity).getUnifiedData( + masterKeyId, new String[]{ + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.HAS_ANY_SECRET + }, new int[]{ + ProviderHelper.FIELD_TYPE_STRING, + ProviderHelper.FIELD_TYPE_INTEGER + } + ); + String name; + KeyRing.UserId mainUserId = KeyRing.splitUserId((String) data.get(KeychainContract.KeyRings.USER_ID)); + if (mainUserId.name != null) { + name = mainUserId.name; + } else { + name = getString(R.string.user_id_no_name); + } + hasSecret = ((Long) data.get(KeychainContract.KeyRings.HAS_ANY_SECRET)) == 1; + + if (hasSecret) { + // show title only for secret key deletions, + // see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior + builder.setTitle(getString(R.string.title_delete_secret_key, name)); + mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name)); + } else { + mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name)); + } + } catch (ProviderHelper.NotFoundException e) { + dismiss(); + return null; + } + } else { + mMainMessage.setText(R.string.key_deletion_confirmation_multi); + hasSecret = false; + } + + builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + Bundle data = new Bundle(); + data.putBoolean(MSG_HAS_SECRET, hasSecret); + Message msg = Message.obtain(); + msg.setData(data); + msg.what = MESSAGE_PERFORM_DELETE; + try { + mMessenger.send(msg); + } catch (RemoteException e) { + Log.e(Constants.TAG, "messenger error", e); + } + } + }); + + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + getActivity().finish(); + } + }); + + return builder.show(); + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 4e9c5a836..f750c6d97 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -410,6 +410,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment { static final int REQUEST_ACTION = 1; + private static final int REQUEST_DELETE = 2; + private static final int REQUEST_VIEW_KEY = 3; private KeyListAdapter mAdapter; private StickyListHeadersListView mStickyList; @@ -336,7 +338,7 @@ public class KeyListFragment extends LoaderFragment Intent viewIntent = new Intent(getActivity(), ViewKeyActivity.class); viewIntent.setData( KeyRings.buildGenericKeyRingUri(mAdapter.getMasterKeyId(position))); - startActivity(viewIntent); + startActivityForResult(viewIntent, REQUEST_VIEW_KEY); } protected void encrypt(ActionMode mode, long[] masterKeyIds) { @@ -362,30 +364,9 @@ public class KeyListFragment extends LoaderFragment return; } - // Message is received after key is deleted - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.arg1 == DeleteKeyDialogFragment.MESSAGE_OKAY) { - Bundle data = message.getData(); - if (data != null) { - DeleteResult result = data.getParcelable(DeleteResult.EXTRA_RESULT); - if (result != null) { - result.createNotify(getActivity()).show(); - } - } - mode.finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - masterKeyIds); - - deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog"); + Intent intent = new Intent(getActivity(), DeleteKeyDialogActivity.class); + intent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, masterKeyIds); + startActivityForResult(intent, REQUEST_DELETE); } @@ -620,14 +601,35 @@ public class KeyListFragment extends LoaderFragment mConsolidateOpHelper.handleActivityResult(requestCode, resultCode, data); } - if (requestCode == REQUEST_ACTION) { - // if a result has been returned, display a notify - if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { - OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); - result.createNotify(getActivity()).show(); - } else { - super.onActivityResult(requestCode, resultCode, data); - } + switch (requestCode) { + case REQUEST_DELETE: + mActionMode.finish(); + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + break; + + case REQUEST_ACTION: + // if a result has been returned, display a notify + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + break; + + case REQUEST_VIEW_KEY: + if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { + OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); + result.createNotify(getActivity()).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + } + break; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java new file mode 100644 index 000000000..b60003419 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.Spinner; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.DeleteResult; +import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.operations.results.RevokeResult; +import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; +import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Preferences; + +public class RevokeDeleteDialogActivity extends FragmentActivity { + + public static final String EXTRA_MASTER_KEY_ID = "extra_master_key_id"; + public static final String EXTRA_KEYSERVER = "extra_keyserver"; + + private final int REVOKE_OP_ID = 1; + private final int DELETE_OP_ID = 2; + private CryptoOperationHelper mRevokeOpHelper; + private CryptoOperationHelper mDeleteOpHelper; + + private long mMasterKeyId; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mRevokeOpHelper = new CryptoOperationHelper<>(this, + getRevocationCallback(), R.string.progress_revoking_uploading, REVOKE_OP_ID); + mRevokeOpHelper.onRestoreInstanceState(savedInstanceState); + + mDeleteOpHelper = new CryptoOperationHelper<>(this, + getDeletionCallback(), R.string.progress_deleting, DELETE_OP_ID); + mDeleteOpHelper.onRestoreInstanceState(savedInstanceState); + + mMasterKeyId = getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, -1); + + RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(); + fragment.show(getSupportFragmentManager(), "deleteRevokeDialog"); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); + mRevokeOpHelper.handleActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mRevokeOpHelper.onSaveInstanceState(outState); + mDeleteOpHelper.onSaveInstanceState(outState); + } + + private void returnResult(OperationResult result) { + Intent intent = new Intent(); + intent.putExtra(OperationResult.EXTRA_RESULT, result); + setResult(RESULT_OK, intent); + finish(); + } + + private CryptoOperationHelper.Callback getRevocationCallback() { + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + @Override + public RevokeKeyringParcel createOperationInput() { + return new RevokeKeyringParcel(mMasterKeyId, true, + getIntent().getStringExtra(EXTRA_KEYSERVER)); + } + + @Override + public void onCryptoOperationSuccess(RevokeResult result) { + returnResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(RevokeResult result) { + returnResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + return callback; + } + + private CryptoOperationHelper.Callback getDeletionCallback() { + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + @Override + public DeleteKeyringParcel createOperationInput() { + return new DeleteKeyringParcel(new long[]{mMasterKeyId}, true); + } + + @Override + public void onCryptoOperationSuccess(DeleteResult result) { + returnResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(DeleteResult result) { + returnResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + return callback; + } + + private void startRevocationOperation() { + mRevokeOpHelper.cryptoOperation(); + } + + private void startDeletionOperation() { + mDeleteOpHelper.cryptoOperation(); + } + + public static class RevokeDeleteDialogFragment extends DialogFragment { + + public static RevokeDeleteDialogFragment newInstance() { + RevokeDeleteDialogFragment frag = new RevokeDeleteDialogFragment(); + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + + final String CHOICE_REVOKE = getString(R.string.del_rev_dialog_choice_rev_upload); + final String CHOICE_DELETE = getString(R.string.del_rev_dialog_choice_delete); + + // if the dialog is displayed from the application class, design is missing + // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay + ContextThemeWrapper theme = new ContextThemeWrapper(activity, + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); + alert.setTitle(R.string.del_rev_dialog_title); + + LayoutInflater inflater = LayoutInflater.from(theme); + View view = inflater.inflate(R.layout.del_rev_dialog, null); + alert.setView(view); + + final Spinner spinner = (Spinner) view.findViewById(R.id.spinner); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + activity.setResult(RESULT_CANCELED); + activity.finish(); + } + }); + + alert.setPositiveButton(R.string.del_rev_dialog_btn_revoke, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + String choice = spinner.getSelectedItem().toString(); + if (choice.equals(CHOICE_REVOKE)) { + ((RevokeDeleteDialogActivity) activity) + .startRevocationOperation(); + } else if (choice.equals(CHOICE_DELETE)) { + ((RevokeDeleteDialogActivity) activity) + .startDeletionOperation(); + } else { + throw new AssertionError( + "Unsupported delete type in RevokeDeleteDialogFragment"); + } + } + }); + + final AlertDialog alertDialog = alert.show(); + + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, int pos, long id) { + + String choice = parent.getItemAtPosition(pos).toString(); + + if (choice.equals(CHOICE_REVOKE)) { + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setText(R.string.del_rev_dialog_btn_revoke); + } else if (choice.equals(CHOICE_DELETE)) { + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setText(R.string.del_rev_dialog_btn_delete); + } else { + throw new AssertionError( + "Unsupported delete type in RevokeDeleteDialogFragment"); + } + } + + public void onNothingSelected(AdapterView parent) { + } + }); + + return alertDialog; + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 9ed46d517..32b5c76b7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -68,7 +68,6 @@ import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; -import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; @@ -85,7 +84,6 @@ import org.sufficientlysecure.keychain.util.Preferences; import java.io.IOException; import java.util.ArrayList; - public class ViewKeyActivity extends BaseNfcActivity implements LoaderManager.LoaderCallbacks, CryptoOperationHelper.Callback { @@ -97,6 +95,8 @@ public class ViewKeyActivity extends BaseNfcActivity implements static final int REQUEST_QR_FINGERPRINT = 1; static final int REQUEST_BACKUP = 2; static final int REQUEST_CERTIFY = 3; + static final int REQUEST_DELETE = 4; + static final int REQUEST_REVOKE_DELETE = 5; public static final String EXTRA_DISPLAY_RESULT = "display_result"; @@ -419,27 +419,24 @@ public class ViewKeyActivity extends BaseNfcActivity implements } private void deleteKey() { - new Handler().post(new Runnable() { - @Override - public void run() { - // Message is received after key is deleted - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.arg1 == MessageStatus.OKAY.ordinal()) { - setResult(RESULT_CANCELED); - finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - new long[]{ mMasterKeyId }); - deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog"); - } - }); + if (mIsSecret && !mIsRevoked) { + Intent revokeDeleteIntent = new Intent(this, RevokeDeleteDialogActivity.class); + + revokeDeleteIntent.putExtra(RevokeDeleteDialogActivity.EXTRA_MASTER_KEY_ID, + mMasterKeyId); + revokeDeleteIntent.putExtra(RevokeDeleteDialogActivity.EXTRA_KEYSERVER, + Preferences.getPreferences(this).getPreferredKeyserver()); + + startActivityForResult(revokeDeleteIntent, REQUEST_REVOKE_DELETE); + + } else { + Intent deleteIntent = new Intent(this, DeleteKeyDialogActivity.class); + + deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, + new long[]{mMasterKeyId}); + + startActivityForResult(deleteIntent, REQUEST_DELETE); + } } @Override @@ -487,6 +484,13 @@ public class ViewKeyActivity extends BaseNfcActivity implements } return; } + + case REQUEST_REVOKE_DELETE: + case REQUEST_DELETE: { + setResult(RESULT_OK, data); + finish(); + return; + } } super.onActivityResult(requestCode, resultCode, data); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index 91ea969d7..c03c301a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.NfcOperationActivity; import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; +import org.sufficientlysecure.keychain.ui.RevokeDeleteDialogActivity; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -119,17 +120,13 @@ public class CryptoOperationHelper - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.dialog; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.operations.results.DeleteResult; -import org.sufficientlysecure.keychain.operations.results.OperationResult; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; -import org.sufficientlysecure.keychain.service.ServiceProgressHandler; -import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.HashMap; - -public class DeleteKeyDialogFragment extends DialogFragment - implements CryptoOperationHelper.Callback { - private static final String ARG_MESSENGER = "messenger"; - private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids"; - - public static final int MESSAGE_OKAY = 1; - public static final int MESSAGE_ERROR = 0; - - private TextView mMainMessage; - private View mInflateView; - - private Messenger mMessenger; - - // for CryptoOperationHelper.Callback - private long[] mMasterKeyIds; - private boolean mHasSecret; - private CryptoOperationHelper mDeleteOpHelper; - - /** - * Creates new instance of this delete file dialog fragment - */ - public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] masterKeyIds) { - DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); - Bundle args = new Bundle(); - - args.putParcelable(ARG_MESSENGER, messenger); - args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds); - - frag.setArguments(args); - - return frag; - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (mDeleteOpHelper != null) { - mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); - } - super.onActivityResult(requestCode, resultCode, data); - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final FragmentActivity activity = getActivity(); - mMessenger = getArguments().getParcelable(ARG_MESSENGER); - - final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); - - CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(activity); - - // Setup custom View to display in AlertDialog - LayoutInflater inflater = activity.getLayoutInflater(); - mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null); - builder.setView(mInflateView); - - mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage); - - final boolean hasSecret; - - // If only a single key has been selected - if (masterKeyIds.length == 1) { - long masterKeyId = masterKeyIds[0]; - - try { - HashMap data = new ProviderHelper(activity).getUnifiedData( - masterKeyId, new String[]{ - KeyRings.USER_ID, - KeyRings.HAS_ANY_SECRET - }, new int[]{ - ProviderHelper.FIELD_TYPE_STRING, - ProviderHelper.FIELD_TYPE_INTEGER - } - ); - String name; - KeyRing.UserId mainUserId = KeyRing.splitUserId((String) data.get(KeyRings.USER_ID)); - if (mainUserId.name != null) { - name = mainUserId.name; - } else { - name = getString(R.string.user_id_no_name); - } - hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1; - - if (hasSecret) { - // show title only for secret key deletions, - // see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior - builder.setTitle(getString(R.string.title_delete_secret_key, name)); - mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name)); - } else { - mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name)); - } - } catch (ProviderHelper.NotFoundException e) { - dismiss(); - return null; - } - } else { - mMainMessage.setText(R.string.key_deletion_confirmation_multi); - hasSecret = false; - } - - builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - mMasterKeyIds = masterKeyIds; - mHasSecret = hasSecret; - - mDeleteOpHelper = new CryptoOperationHelper<> - (1, DeleteKeyDialogFragment.this, DeleteKeyDialogFragment.this, - R.string.progress_deleting); - mDeleteOpHelper.cryptoOperation(); - // do NOT dismiss here, it'll give - // OperationHelper a null fragmentManager - // dismiss(); - } - }); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - dismiss(); - } - }); - - return builder.show(); - } - - @Override - public DeleteKeyringParcel createOperationInput() { - return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret); - } - - @Override - public void onCryptoOperationSuccess(DeleteResult result) { - handleResult(result); - } - - @Override - public void onCryptoOperationCancelled() { - - } - - @Override - public void onCryptoOperationError(DeleteResult result) { - handleResult(result); - } - - @Override - public boolean onCryptoSetProgress(String msg, int progress, int max) { - return false; - } - - public void handleResult(DeleteResult result) { - try { - Bundle data = new Bundle(); - data.putParcelable(OperationResult.EXTRA_RESULT, result); - Message msg = Message.obtain(); - msg.arg1 = ServiceProgressHandler.MessageStatus.OKAY.ordinal(); - msg.setData(data); - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "messenger error", e); - } - dismiss(); - } -} -- cgit v1.2.3 From d1409fd5c89bc10dd0c39a228049e4c2f669c65a Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Fri, 10 Jul 2015 00:26:48 +0530 Subject: use only one DeleteDialogActivity --- .../operations/results/OperationResult.java | 2 +- .../keychain/ui/DeleteKeyDialogActivity.java | 279 ++++++++++++++++----- .../keychain/ui/KeyListFragment.java | 9 +- .../keychain/ui/RevokeDeleteDialogActivity.java | 258 ------------------- .../keychain/ui/ViewKeyActivity.java | 28 +-- .../keychain/ui/base/CryptoOperationHelper.java | 11 +- 6 files changed, 241 insertions(+), 346 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index 5105b7fdc..c65412a1f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -764,7 +764,7 @@ public abstract class OperationResult implements Parcelable { MSG_REVOKE_ERROR_MULTI_SECRET (LogLevel.DEBUG, R.string.msg_revoke_error_multi_secret), MSG_REVOKE_ERROR_NOT_FOUND (LogLevel.DEBUG, R.string.msg_revoke_error_multi_secret), MSG_REVOKE (LogLevel.DEBUG, R.string.msg_revoke_key), - MSG_REVOKE_KEY_FAIL (LogLevel.WARN, R.string.msg_revoke_key_fail), + MSG_REVOKE_KEY_FAIL (LogLevel.ERROR, R.string.msg_revoke_key_fail), MSG_REVOKE_OK (LogLevel.OK, R.string.msg_revoke_ok), // keybase verification diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index 064d34e38..b89c476d6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -1,5 +1,7 @@ package org.sufficientlysecure.keychain.ui; +import android.app.Activity; +import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; @@ -8,32 +10,40 @@ import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; +import android.widget.AdapterView; +import android.widget.Spinner; import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.DeleteResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.operations.results.RevokeResult; import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; +import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; import org.sufficientlysecure.keychain.util.Log; import java.util.HashMap; -public class DeleteKeyDialogActivity extends FragmentActivity - implements CryptoOperationHelper.Callback { +public class DeleteKeyDialogActivity extends FragmentActivity { public static final String EXTRA_DELETE_MASTER_KEY_IDS = "extra_delete_master_key_ids"; + public static final String EXTRA_HAS_SECRET = "extra_has_secret"; + public static final String EXTRA_KEYSERVER = "extra_keyserver"; private CryptoOperationHelper mDeleteOpHelper; + private CryptoOperationHelper mRevokeOpHelper; private long[] mMasterKeyIds; private boolean mHasSecret; @@ -42,95 +52,168 @@ public class DeleteKeyDialogActivity extends FragmentActivity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mDeleteOpHelper = new CryptoOperationHelper<>(DeleteKeyDialogActivity.this, - DeleteKeyDialogActivity.this, R.string.progress_deleting); - mDeleteOpHelper.onRestoreInstanceState(savedInstanceState); + mDeleteOpHelper = new CryptoOperationHelper<>(1, DeleteKeyDialogActivity.this, + getDeletionCallback(), R.string.progress_deleting); + + mRevokeOpHelper = new CryptoOperationHelper<>(2, this, + getRevocationCallback(), R.string.progress_revoking_uploading); mMasterKeyIds = getIntent().getLongArrayExtra(EXTRA_DELETE_MASTER_KEY_IDS); + mHasSecret = getIntent().getBooleanExtra(EXTRA_HAS_SECRET, false); - Handler deleteDialogHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - if (msg.what == DeleteKeyDialogFragment.MESSAGE_PERFORM_DELETE) { - mHasSecret = msg.getData().getBoolean(DeleteKeyDialogFragment.MSG_HAS_SECRET); - mDeleteOpHelper.cryptoOperation(); + if (mMasterKeyIds.length > 1 && mHasSecret) { + throw new AssertionError("Secret keys can be deleted only one at a time!" + + " Should be checked before reaching DeleteKeyDialogActivity."); + } + + if (mMasterKeyIds.length == 1 && mHasSecret) { + // if mMasterKeyIds.length == 0 we let the DeleteOperation respond + try { + HashMap data = new ProviderHelper(this).getUnifiedData( + mMasterKeyIds[0], new String[]{ + KeychainContract.KeyRings.USER_ID, + KeychainContract.KeyRings.IS_REVOKED + }, new int[]{ + ProviderHelper.FIELD_TYPE_STRING, + ProviderHelper.FIELD_TYPE_INTEGER + } + ); + if ((long) data.get(KeychainContract.KeyRings.IS_REVOKED) > 0) { + showNormalDeleteDialog(); + } else { + showRevokeDeleteDialog(); } + } catch (ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, + "Secret key to delete not found at DeleteKeyDialogActivity for " + + mMasterKeyIds[0], e); + finish(); + return; } - }; + } else { + showNormalDeleteDialog(); + } + } - Messenger messenger = new Messenger(deleteDialogHandler); + private void showNormalDeleteDialog() { DeleteKeyDialogFragment deleteKeyDialogFragment - = DeleteKeyDialogFragment.newInstance(messenger, mMasterKeyIds); + = DeleteKeyDialogFragment.newInstance(mMasterKeyIds); deleteKeyDialogFragment.show(getSupportFragmentManager(), "deleteKeyDialog"); - } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); } - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mDeleteOpHelper.onSaveInstanceState(outState); - } + private void showRevokeDeleteDialog() { - @Override - public DeleteKeyringParcel createOperationInput() { - return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret); + RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(); + fragment.show(getSupportFragmentManager(), "deleteRevokeDialog"); } - @Override - public void onCryptoOperationSuccess(DeleteResult result) { - handleResult(result); + private void startRevocationOperation() { + mRevokeOpHelper.cryptoOperation(); } - @Override - public void onCryptoOperationCancelled() { - setResult(RESULT_CANCELED); - finish(); + private void startDeletionOperation() { + mDeleteOpHelper.cryptoOperation(); } - @Override - public void onCryptoOperationError(DeleteResult result) { - handleResult(result); + private CryptoOperationHelper.Callback getRevocationCallback() { + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + @Override + public RevokeKeyringParcel createOperationInput() { + return new RevokeKeyringParcel(mMasterKeyIds[0], true, + getIntent().getStringExtra(EXTRA_KEYSERVER)); + } + + @Override + public void onCryptoOperationSuccess(RevokeResult result) { + returnResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(RevokeResult result) { + returnResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + return callback; } - @Override - public boolean onCryptoSetProgress(String msg, int progress, int max) { - return false; + private CryptoOperationHelper.Callback getDeletionCallback() { + + CryptoOperationHelper.Callback callback + = new CryptoOperationHelper.Callback() { + @Override + public DeleteKeyringParcel createOperationInput() { + return new DeleteKeyringParcel(mMasterKeyIds, true); + } + + @Override + public void onCryptoOperationSuccess(DeleteResult result) { + returnResult(result); + } + + @Override + public void onCryptoOperationCancelled() { + setResult(RESULT_CANCELED); + finish(); + } + + @Override + public void onCryptoOperationError(DeleteResult result) { + returnResult(result); + } + + @Override + public boolean onCryptoSetProgress(String msg, int progress, int max) { + return false; + } + }; + + return callback; } - public void handleResult(DeleteResult result) { + private void returnResult(OperationResult result) { Intent intent = new Intent(); intent.putExtra(OperationResult.EXTRA_RESULT, result); setResult(RESULT_OK, intent); finish(); } - public static class DeleteKeyDialogFragment extends DialogFragment { + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); + mRevokeOpHelper.handleActivityResult(requestCode, resultCode, data); + } - public static final String MSG_HAS_SECRET = "msg_has_secret"; + public static class DeleteKeyDialogFragment extends DialogFragment { - private static final String ARG_MESSENGER = "messenger"; private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids"; - public static final int MESSAGE_PERFORM_DELETE = 1; - private TextView mMainMessage; private View mInflateView; - private Messenger mMessenger; /** * Creates new instance of this delete file dialog fragment */ - public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] masterKeyIds) { + public static DeleteKeyDialogFragment newInstance(long[] masterKeyIds) { DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); Bundle args = new Bundle(); - args.putParcelable(ARG_MESSENGER, messenger); args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds); frag.setArguments(args); @@ -138,10 +221,10 @@ public class DeleteKeyDialogActivity extends FragmentActivity return frag; } + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final FragmentActivity activity = getActivity(); - mMessenger = getArguments().getParcelable(ARG_MESSENGER); final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); @@ -151,7 +234,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(theme); // Setup custom View to display in AlertDialog - LayoutInflater inflater = activity.getLayoutInflater(); + LayoutInflater inflater = LayoutInflater.from(theme); mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null); builder.setView(mInflateView); @@ -196,23 +279,13 @@ public class DeleteKeyDialogActivity extends FragmentActivity } } else { mMainMessage.setText(R.string.key_deletion_confirmation_multi); - hasSecret = false; } builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Bundle data = new Bundle(); - data.putBoolean(MSG_HAS_SECRET, hasSecret); - Message msg = Message.obtain(); - msg.setData(data); - msg.what = MESSAGE_PERFORM_DELETE; - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.e(Constants.TAG, "messenger error", e); - } + ((DeleteKeyDialogActivity) getActivity()).startDeletionOperation(); } }); @@ -228,4 +301,88 @@ public class DeleteKeyDialogActivity extends FragmentActivity } } + public static class RevokeDeleteDialogFragment extends DialogFragment { + + public static RevokeDeleteDialogFragment newInstance() { + RevokeDeleteDialogFragment frag = new RevokeDeleteDialogFragment(); + return frag; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + + final String CHOICE_REVOKE = getString(R.string.del_rev_dialog_choice_rev_upload); + final String CHOICE_DELETE = getString(R.string.del_rev_dialog_choice_delete); + + // if the dialog is displayed from the application class, design is missing + // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay + ContextThemeWrapper theme = new ContextThemeWrapper(activity, + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); + alert.setTitle(R.string.del_rev_dialog_title); + + LayoutInflater inflater = LayoutInflater.from(theme); + View view = inflater.inflate(R.layout.del_rev_dialog, null); + alert.setView(view); + + final Spinner spinner = (Spinner) view.findViewById(R.id.spinner); + + alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + activity.setResult(RESULT_CANCELED); + activity.finish(); + } + }); + + alert.setPositiveButton(R.string.del_rev_dialog_btn_revoke, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + String choice = spinner.getSelectedItem().toString(); + if (choice.equals(CHOICE_REVOKE)) { + ((DeleteKeyDialogActivity) activity) + .startRevocationOperation(); + } else if (choice.equals(CHOICE_DELETE)) { + ((DeleteKeyDialogActivity) activity) + .startDeletionOperation(); + } else { + throw new AssertionError( + "Unsupported delete type in RevokeDeleteDialogFragment"); + } + } + }); + + final AlertDialog alertDialog = alert.show(); + + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, int pos, long id) { + + String choice = parent.getItemAtPosition(pos).toString(); + + if (choice.equals(CHOICE_REVOKE)) { + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setText(R.string.del_rev_dialog_btn_revoke); + } else if (choice.equals(CHOICE_DELETE)) { + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + .setText(R.string.del_rev_dialog_btn_delete); + } else { + throw new AssertionError( + "Unsupported delete type in RevokeDeleteDialogFragment"); + } + } + + public void onNothingSelected(AdapterView parent) { + } + }); + + return alertDialog; + } + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index c53220d69..b89b9d6ee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -366,6 +366,11 @@ public class KeyListFragment extends LoaderFragment Intent intent = new Intent(getActivity(), DeleteKeyDialogActivity.class); intent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, masterKeyIds); + intent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, hasSecret); + if (hasSecret) { + intent.putExtra(DeleteKeyDialogActivity.EXTRA_KEYSERVER, + Preferences.getPreferences(getActivity()).getPreferredKeyserver()); + } startActivityForResult(intent, REQUEST_DELETE); } @@ -603,7 +608,9 @@ public class KeyListFragment extends LoaderFragment switch (requestCode) { case REQUEST_DELETE: - mActionMode.finish(); + if (mActionMode != null) { + mActionMode.finish(); + } if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); result.createNotify(getActivity()).show(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java deleted file mode 100644 index b60003419..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RevokeDeleteDialogActivity.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2015 Dominik Schürmann - * Copyright (C) 2015 Adithya Abraham Philip - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.os.Handler; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.AdapterView; -import android.widget.Spinner; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.operations.results.DeleteResult; -import org.sufficientlysecure.keychain.operations.results.OperationResult; -import org.sufficientlysecure.keychain.operations.results.RevokeResult; -import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; -import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; -import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; -import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; -import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Preferences; - -public class RevokeDeleteDialogActivity extends FragmentActivity { - - public static final String EXTRA_MASTER_KEY_ID = "extra_master_key_id"; - public static final String EXTRA_KEYSERVER = "extra_keyserver"; - - private final int REVOKE_OP_ID = 1; - private final int DELETE_OP_ID = 2; - private CryptoOperationHelper mRevokeOpHelper; - private CryptoOperationHelper mDeleteOpHelper; - - private long mMasterKeyId; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mRevokeOpHelper = new CryptoOperationHelper<>(this, - getRevocationCallback(), R.string.progress_revoking_uploading, REVOKE_OP_ID); - mRevokeOpHelper.onRestoreInstanceState(savedInstanceState); - - mDeleteOpHelper = new CryptoOperationHelper<>(this, - getDeletionCallback(), R.string.progress_deleting, DELETE_OP_ID); - mDeleteOpHelper.onRestoreInstanceState(savedInstanceState); - - mMasterKeyId = getIntent().getLongExtra(EXTRA_MASTER_KEY_ID, -1); - - RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(); - fragment.show(getSupportFragmentManager(), "deleteRevokeDialog"); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data); - mRevokeOpHelper.handleActivityResult(requestCode, resultCode, data); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mRevokeOpHelper.onSaveInstanceState(outState); - mDeleteOpHelper.onSaveInstanceState(outState); - } - - private void returnResult(OperationResult result) { - Intent intent = new Intent(); - intent.putExtra(OperationResult.EXTRA_RESULT, result); - setResult(RESULT_OK, intent); - finish(); - } - - private CryptoOperationHelper.Callback getRevocationCallback() { - - CryptoOperationHelper.Callback callback - = new CryptoOperationHelper.Callback() { - @Override - public RevokeKeyringParcel createOperationInput() { - return new RevokeKeyringParcel(mMasterKeyId, true, - getIntent().getStringExtra(EXTRA_KEYSERVER)); - } - - @Override - public void onCryptoOperationSuccess(RevokeResult result) { - returnResult(result); - } - - @Override - public void onCryptoOperationCancelled() { - setResult(RESULT_CANCELED); - finish(); - } - - @Override - public void onCryptoOperationError(RevokeResult result) { - returnResult(result); - } - - @Override - public boolean onCryptoSetProgress(String msg, int progress, int max) { - return false; - } - }; - - return callback; - } - - private CryptoOperationHelper.Callback getDeletionCallback() { - - CryptoOperationHelper.Callback callback - = new CryptoOperationHelper.Callback() { - @Override - public DeleteKeyringParcel createOperationInput() { - return new DeleteKeyringParcel(new long[]{mMasterKeyId}, true); - } - - @Override - public void onCryptoOperationSuccess(DeleteResult result) { - returnResult(result); - } - - @Override - public void onCryptoOperationCancelled() { - setResult(RESULT_CANCELED); - finish(); - } - - @Override - public void onCryptoOperationError(DeleteResult result) { - returnResult(result); - } - - @Override - public boolean onCryptoSetProgress(String msg, int progress, int max) { - return false; - } - }; - - return callback; - } - - private void startRevocationOperation() { - mRevokeOpHelper.cryptoOperation(); - } - - private void startDeletionOperation() { - mDeleteOpHelper.cryptoOperation(); - } - - public static class RevokeDeleteDialogFragment extends DialogFragment { - - public static RevokeDeleteDialogFragment newInstance() { - RevokeDeleteDialogFragment frag = new RevokeDeleteDialogFragment(); - return frag; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final Activity activity = getActivity(); - - final String CHOICE_REVOKE = getString(R.string.del_rev_dialog_choice_rev_upload); - final String CHOICE_DELETE = getString(R.string.del_rev_dialog_choice_delete); - - // if the dialog is displayed from the application class, design is missing - // hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay - ContextThemeWrapper theme = new ContextThemeWrapper(activity, - R.style.Theme_AppCompat_Light_Dialog); - - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); - alert.setTitle(R.string.del_rev_dialog_title); - - LayoutInflater inflater = LayoutInflater.from(theme); - View view = inflater.inflate(R.layout.del_rev_dialog, null); - alert.setView(view); - - final Spinner spinner = (Spinner) view.findViewById(R.id.spinner); - - alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - activity.setResult(RESULT_CANCELED); - activity.finish(); - } - }); - - alert.setPositiveButton(R.string.del_rev_dialog_btn_revoke, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - - String choice = spinner.getSelectedItem().toString(); - if (choice.equals(CHOICE_REVOKE)) { - ((RevokeDeleteDialogActivity) activity) - .startRevocationOperation(); - } else if (choice.equals(CHOICE_DELETE)) { - ((RevokeDeleteDialogActivity) activity) - .startDeletionOperation(); - } else { - throw new AssertionError( - "Unsupported delete type in RevokeDeleteDialogFragment"); - } - } - }); - - final AlertDialog alertDialog = alert.show(); - - spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - public void onItemSelected(AdapterView parent, View view, int pos, long id) { - - String choice = parent.getItemAtPosition(pos).toString(); - - if (choice.equals(CHOICE_REVOKE)) { - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) - .setText(R.string.del_rev_dialog_btn_revoke); - } else if (choice.equals(CHOICE_DELETE)) { - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) - .setText(R.string.del_rev_dialog_btn_delete); - } else { - throw new AssertionError( - "Unsupported delete type in RevokeDeleteDialogFragment"); - } - } - - public void onNothingSelected(AdapterView parent) { - } - }); - - return alertDialog; - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 32b5c76b7..08ef38746 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -96,7 +96,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements static final int REQUEST_BACKUP = 2; static final int REQUEST_CERTIFY = 3; static final int REQUEST_DELETE = 4; - static final int REQUEST_REVOKE_DELETE = 5; public static final String EXTRA_DISPLAY_RESULT = "display_result"; @@ -419,24 +418,18 @@ public class ViewKeyActivity extends BaseNfcActivity implements } private void deleteKey() { - if (mIsSecret && !mIsRevoked) { - Intent revokeDeleteIntent = new Intent(this, RevokeDeleteDialogActivity.class); - - revokeDeleteIntent.putExtra(RevokeDeleteDialogActivity.EXTRA_MASTER_KEY_ID, - mMasterKeyId); - revokeDeleteIntent.putExtra(RevokeDeleteDialogActivity.EXTRA_KEYSERVER, + Intent deleteIntent = new Intent(this, DeleteKeyDialogActivity.class); + + deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, + new long[]{mMasterKeyId}); + deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, mIsSecret); + if (mIsSecret) { + // for upload in case key is secret + deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_KEYSERVER, Preferences.getPreferences(this).getPreferredKeyserver()); - - startActivityForResult(revokeDeleteIntent, REQUEST_REVOKE_DELETE); - - } else { - Intent deleteIntent = new Intent(this, DeleteKeyDialogActivity.class); - - deleteIntent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, - new long[]{mMasterKeyId}); - - startActivityForResult(deleteIntent, REQUEST_DELETE); } + + startActivityForResult(deleteIntent, REQUEST_DELETE); } @Override @@ -485,7 +478,6 @@ public class ViewKeyActivity extends BaseNfcActivity implements return; } - case REQUEST_REVOKE_DELETE: case REQUEST_DELETE: { setResult(RESULT_OK, data); finish(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index c03c301a7..4cb3d5841 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -40,7 +40,6 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.NfcOperationActivity; import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; -import org.sufficientlysecure.keychain.ui.RevokeDeleteDialogActivity; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -152,13 +151,11 @@ public class CryptoOperationHelper Date: Fri, 10 Jul 2015 02:02:27 +0530 Subject: prevented passphrase caching on revocation --- .../keychain/operations/EditKeyOperation.java | 2 +- .../keychain/operations/RevokeOperation.java | 3 ++ .../keychain/service/input/CryptoInputParcel.java | 17 +++++++- .../keychain/ui/DeleteKeyDialogActivity.java | 3 +- .../keychain/ui/PassphraseDialogActivity.java | 48 ++++++++++++++++------ .../keychain/ui/base/CryptoOperationHelper.java | 3 +- 6 files changed, 59 insertions(+), 17 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index f8f7e79a3..6a1c01dd1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -161,7 +161,7 @@ public class EditKeyOperation extends BaseOperation { } // There is a new passphrase - cache it - if (saveParcel.mNewUnlock != null) { + if (saveParcel.mNewUnlock != null && cryptoInput.mCachePassphrase) { log.add(LogType.MSG_ED_CACHING_NEW, 1); // NOTE: Don't cache empty passphrases! Important for MOVE_KEY_TO_CARD diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java index 157e36e04..0fc3f1bc3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java @@ -32,6 +32,9 @@ public class RevokeOperation extends BaseOperation { public OperationResult execute(RevokeKeyringParcel revokeKeyringParcel, CryptoInputParcel cryptoInputParcel) { + // we don't cache passphrases during revocation + cryptoInputParcel.mCachePassphrase = false; + long masterKeyId = revokeKeyringParcel.mMasterKeyId; OperationResult.OperationLog log = new OperationResult.OperationLog(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java index d4cebe67c..9ba9601e5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java @@ -34,12 +34,15 @@ import java.util.Map; public class CryptoInputParcel implements Parcelable { final Date mSignatureTime; - final Passphrase mPassphrase; + public Passphrase mPassphrase; // used to supply an explicit proxy to operations that require it // this is not final so it can be added to an existing CryptoInputParcel // (e.g) CertifyOperation with upload might require both passphrase and orbot to be enabled private ParcelableProxy mParcelableProxy; + // specifies whether passphrases should be cached + public boolean mCachePassphrase = true; + // this map contains both decrypted session keys and signed hashes to be // used in the crypto operation described by this parcel. private HashMap mCryptoData = new HashMap<>(); @@ -47,21 +50,25 @@ public class CryptoInputParcel implements Parcelable { public CryptoInputParcel() { mSignatureTime = new Date(); mPassphrase = null; + mCachePassphrase = true; } public CryptoInputParcel(Date signatureTime, Passphrase passphrase) { mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = passphrase; + mCachePassphrase = true; } public CryptoInputParcel(Passphrase passphrase) { mSignatureTime = new Date(); mPassphrase = passphrase; + mCachePassphrase = true; } public CryptoInputParcel(Date signatureTime) { mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = null; + mCachePassphrase = true; } public CryptoInputParcel(ParcelableProxy parcelableProxy) { @@ -69,10 +76,17 @@ public class CryptoInputParcel implements Parcelable { mParcelableProxy = parcelableProxy; } + public CryptoInputParcel(boolean cachePassphrase) { + mSignatureTime = new Date(); + mPassphrase = null; + mCachePassphrase = cachePassphrase; + } + protected CryptoInputParcel(Parcel source) { mSignatureTime = new Date(source.readLong()); mPassphrase = source.readParcelable(getClass().getClassLoader()); mParcelableProxy = source.readParcelable(getClass().getClassLoader()); + mCachePassphrase = source.readByte() != 0; { int count = source.readInt(); @@ -96,6 +110,7 @@ public class CryptoInputParcel implements Parcelable { dest.writeLong(mSignatureTime.getTime()); dest.writeParcelable(mPassphrase, 0); dest.writeParcelable(mParcelableProxy, 0); + dest.writeByte((byte) (mCachePassphrase ? 1 : 0)); dest.writeInt(mCryptoData.size()); for (HashMap.Entry entry : mCryptoData.entrySet()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index b89c476d6..98d3cf7b0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; import org.sufficientlysecure.keychain.util.Log; @@ -111,7 +112,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { } private void startRevocationOperation() { - mRevokeOpHelper.cryptoOperation(); + mRevokeOpHelper.cryptoOperation(new CryptoInputParcel(false)); } private void startDeletionOperation() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java index 004d1d127..c9f6423d6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java @@ -72,11 +72,14 @@ public class PassphraseDialogActivity extends FragmentActivity { public static final String EXTRA_REQUIRED_INPUT = "required_input"; public static final String EXTRA_SUBKEY_ID = "secret_key_id"; + public static final String EXTRA_CRYPTO_INPUT = "crypto_input"; // special extra for OpenPgpService public static final String EXTRA_SERVICE_INTENT = "data"; private long mSubKeyId; + private CryptoInputParcel mCryptoInputParcel; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -90,6 +93,8 @@ public class PassphraseDialogActivity extends FragmentActivity { ); } + mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT); + // this activity itself has no content view (see manifest) if (getIntent().hasExtra(EXTRA_SUBKEY_ID)) { @@ -330,11 +335,16 @@ public class PassphraseDialogActivity extends FragmentActivity { public void onClick(View v) { final Passphrase passphrase = new Passphrase(mPassphraseEditText); + CryptoInputParcel cryptoInputParcel = + ((PassphraseDialogActivity) getActivity()).mCryptoInputParcel; + // Early breakout if we are dealing with a symmetric key if (mSecretRing == null) { - PassphraseCacheService.addCachedPassphrase(getActivity(), - Constants.key.symmetric, Constants.key.symmetric, passphrase, - getString(R.string.passp_cache_notif_pwd)); + if (cryptoInputParcel.mCachePassphrase) { + PassphraseCacheService.addCachedPassphrase(getActivity(), + Constants.key.symmetric, Constants.key.symmetric, passphrase, + getString(R.string.passp_cache_notif_pwd)); + } finishCaching(passphrase); return; @@ -387,15 +397,24 @@ public class PassphraseDialogActivity extends FragmentActivity { return; } - // cache the new passphrase - Log.d(Constants.TAG, "Everything okay! Caching entered passphrase"); + // cache the new passphrase as specified in CryptoInputParcel + Log.d(Constants.TAG, "Everything okay!"); - try { - PassphraseCacheService.addCachedPassphrase(getActivity(), - mSecretRing.getMasterKeyId(), mSubKeyId, passphrase, - mSecretRing.getPrimaryUserIdWithFallback()); - } catch (PgpKeyNotFoundException e) { - Log.e(Constants.TAG, "adding of a passphrase failed", e); + CryptoInputParcel cryptoInputParcel + = ((PassphraseDialogActivity) getActivity()).mCryptoInputParcel; + + if (cryptoInputParcel.mCachePassphrase) { + Log.d(Constants.TAG, "Caching entered passphrase"); + + try { + PassphraseCacheService.addCachedPassphrase(getActivity(), + mSecretRing.getMasterKeyId(), mSubKeyId, passphrase, + mSecretRing.getPrimaryUserIdWithFallback()); + } catch (PgpKeyNotFoundException e) { + Log.e(Constants.TAG, "adding of a passphrase failed", e); + } + } else { + Log.d(Constants.TAG, "Not caching entered passphrase!"); } finishCaching(passphrase); @@ -411,9 +430,12 @@ public class PassphraseDialogActivity extends FragmentActivity { return; } - CryptoInputParcel inputParcel = new CryptoInputParcel(null, passphrase); + CryptoInputParcel inputParcel = + ((PassphraseDialogActivity) getActivity()).mCryptoInputParcel; + inputParcel.mPassphrase = passphrase; if (mServiceIntent != null) { - CryptoInputParcelCacheService.addCryptoInputParcel(getActivity(), mServiceIntent, inputParcel); + CryptoInputParcelCacheService.addCryptoInputParcel(getActivity(), mServiceIntent, + inputParcel); getActivity().setResult(RESULT_OK, mServiceIntent); } else { // also return passphrase back to activity diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index 4cb3d5841..398b3e778 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -118,7 +118,7 @@ public class CryptoOperationHelper Date: Fri, 10 Jul 2015 02:31:17 +0530 Subject: allowed operations to modify CryptoInputParcel they receive --- .../keychain/operations/CertifyOperation.java | 9 ++++++--- .../keychain/operations/ExportOperation.java | 14 +------------- .../keychain/operations/ImportOperation.java | 2 +- .../keychain/operations/KeybaseVerificationOperation.java | 2 +- .../keychain/operations/SignEncryptOperation.java | 4 ++-- .../keychain/operations/results/CertifyResult.java | 6 ++++-- .../keychain/operations/results/DecryptVerifyResult.java | 5 +++-- .../keychain/operations/results/DeleteResult.java | 6 ++++-- .../keychain/operations/results/ExportResult.java | 6 ++++-- .../keychain/operations/results/GetKeyResult.java | 6 ++++-- .../keychain/operations/results/ImportKeyResult.java | 5 +++-- .../keychain/operations/results/InputPendingResult.java | 2 +- .../operations/results/KeybaseVerificationResult.java | 6 ++++-- .../keychain/operations/results/PgpEditKeyResult.java | 6 ++++-- .../keychain/operations/results/PgpSignEncryptResult.java | 6 ++++-- .../keychain/operations/results/RevokeResult.java | 6 ++++-- .../keychain/operations/results/SignEncryptResult.java | 7 +++++-- .../sufficientlysecure/keychain/pgp/PgpDecryptVerify.java | 11 +++++++---- .../sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 6 +++--- .../keychain/pgp/PgpSignEncryptOperation.java | 4 ++-- .../keychain/ui/adapter/ImportKeysListCloudLoader.java | 4 +++- .../keychain/ui/base/CryptoOperationHelper.java | 7 +++---- 22 files changed, 73 insertions(+), 57 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java index d0377cc24..eeed24db0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java @@ -103,7 +103,10 @@ public class CertifyOperation extends BaseOperation { if (passphrase == null) { return new CertifyResult(log, RequiredInputParcel.createRequiredSignPassphrase( - certificationKey.getKeyId(), certificationKey.getKeyId(), null) + certificationKey.getKeyId(), + certificationKey.getKeyId(), + null), + cryptoInput ); } break; @@ -189,7 +192,7 @@ public class CertifyOperation extends BaseOperation { if (!allRequiredInput.isEmpty()) { log.add(LogType.MSG_CRT_NFC_RETURN, 1); - return new CertifyResult(log, allRequiredInput.build()); + return new CertifyResult(log, allRequiredInput.build(), cryptoInput); } log.add(LogType.MSG_CRT_SAVING, 1); @@ -211,7 +214,7 @@ public class CertifyOperation extends BaseOperation { // explicit proxy not set if (!OrbotHelper.isOrbotInRequiredState(mContext)) { return new CertifyResult(null, - RequiredInputParcel.createOrbotRequiredOperation()); + RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput); } proxy = Preferences.getPreferences(mContext).getProxyPrefs() .parcelableProxy.getProxy(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java index 0dec35949..5b13fa629 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java @@ -130,18 +130,6 @@ public class ExportOperation extends BaseOperation { } } - /** - * returns null if no user input required for upload, an InputPendingResult otherwise - */ - @Nullable - public InputPendingResult getUploadPendingInput() { - if (!OrbotHelper.isOrbotInRequiredState(mContext)) { - return new ExportResult(null, - RequiredInputParcel.createOrbotRequiredOperation()); - } - return null; - } - public ExportResult exportToFile(long[] masterKeyIds, boolean exportSecret, String outputFile) { OperationLog log = new OperationLog(); @@ -355,7 +343,7 @@ public class ExportOperation extends BaseOperation { // explicit proxy not set if (!OrbotHelper.isOrbotInRequiredState(mContext)) { return new ExportResult(null, - RequiredInputParcel.createOrbotRequiredOperation()); + RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput); } proxy = Preferences.getPreferences(mContext).getProxyPrefs() .parcelableProxy.getProxy(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java index 256f1bb82..4acfd6e30 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java @@ -404,7 +404,7 @@ public class ImportOperation extends BaseOperation { if(!OrbotHelper.isOrbotInRequiredState(mContext)) { // show dialog to enable/install dialog return new ImportKeyResult(null, - RequiredInputParcel.createOrbotRequiredOperation()); + RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput); } proxy = Preferences.getPreferences(mContext).getProxyPrefs().parcelableProxy .getProxy(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java index 42bd3ace2..30f37dd4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java @@ -69,7 +69,7 @@ public class KeybaseVerificationOperation extends BaseOperation { RequiredInputParcel requiredInput = result.getRequiredInputParcel(); // Passphrase returns immediately, nfc are aggregated if (requiredInput.mType == RequiredInputType.PASSPHRASE) { - return new SignEncryptResult(log, requiredInput, results); + return new SignEncryptResult(log, requiredInput, results, cryptoInput); } if (pendingInputBuilder == null) { pendingInputBuilder = new NfcSignOperationsBuilder(requiredInput.mSignatureTime, @@ -173,7 +173,7 @@ public class SignEncryptOperation extends BaseOperation { } while (!inputUris.isEmpty()); if (pendingInputBuilder != null && !pendingInputBuilder.isEmpty()) { - return new SignEncryptResult(log, pendingInputBuilder.build(), results); + return new SignEncryptResult(log, pendingInputBuilder.build(), results, cryptoInput); } if (!outputUris.isEmpty()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java index a9f8170d9..cf73f019c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.os.Parcel; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; @@ -38,8 +39,9 @@ public class CertifyResult extends InputPendingResult { super(result, log); } - public CertifyResult(OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public CertifyResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); } public CertifyResult(int result, OperationLog log, int certifyOk, int certifyError, int uploadOk, int uploadError) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java index 25a86f137..972fbb0aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java @@ -45,8 +45,9 @@ public class DecryptVerifyResult extends InputPendingResult { super(result, log); } - public DecryptVerifyResult(OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public DecryptVerifyResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); } public DecryptVerifyResult(Parcel source) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java index 52c6e1491..c7c48ed56 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java @@ -24,6 +24,7 @@ import android.os.Parcel; import android.support.annotation.Nullable; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; @@ -47,8 +48,9 @@ public class DeleteResult extends InputPendingResult { * @param log operation log upto point of required input, if any * @param requiredInput represents input required */ - public DeleteResult(@Nullable OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public DeleteResult(@Nullable OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); // values are not to be used mOk = -1; mFail = -1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java index 199a3f565..e21ef949f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; public class ExportResult extends InputPendingResult { @@ -36,8 +37,9 @@ public class ExportResult extends InputPendingResult { } - public ExportResult(OperationLog log, RequiredInputParcel requiredInputParcel) { - super(log, requiredInputParcel); + public ExportResult(OperationLog log, RequiredInputParcel requiredInputParcel, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInputParcel, cryptoInputParcel); // we won't use these values mOkPublic = -1; mOkSecret = -1; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/GetKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/GetKeyResult.java index 15f03e439..bdc4d9a47 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/GetKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/GetKeyResult.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; public class GetKeyResult extends InputPendingResult { @@ -38,8 +39,9 @@ public class GetKeyResult extends InputPendingResult { super(result, log); } - public GetKeyResult(OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public GetKeyResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); } public static final int RESULT_ERROR_NO_VALID_KEYS = RESULT_ERROR + 8; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java index ca7079078..5f5090bee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java @@ -96,8 +96,9 @@ public class ImportKeyResult extends InputPendingResult { mImportedMasterKeyIds = importedMasterKeyIds; } - public ImportKeyResult(OperationLog log, RequiredInputParcel requiredInputParcel) { - super(log, requiredInputParcel); + public ImportKeyResult(OperationLog log, RequiredInputParcel requiredInputParcel, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInputParcel, cryptoInputParcel); // just assign default values, we won't use them anyway mNewKeys = 0; mUpdatedKeys = 0; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java index 5b982ca61..f055c450c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java @@ -32,7 +32,7 @@ public class InputPendingResult extends OperationResult { final RequiredInputParcel mRequiredInput; // in case operation needs to add to/changes the cryptoInputParcel sent to it - final CryptoInputParcel mCryptoInputParcel; + public final CryptoInputParcel mCryptoInputParcel; public InputPendingResult(int result, OperationLog log) { super(result, log); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java index 173f7f575..84648d32c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java @@ -24,6 +24,7 @@ import android.os.Parcelable; import com.textuality.keybase.lib.KeybaseException; import com.textuality.keybase.lib.prover.Prover; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; public class KeybaseVerificationResult extends InputPendingResult { @@ -46,8 +47,9 @@ public class KeybaseVerificationResult extends InputPendingResult { mPresenceLabel = prover.getPresenceLabel(); } - public KeybaseVerificationResult(OperationLog log, RequiredInputParcel requiredInputParcel) { - super(log, requiredInputParcel); + public KeybaseVerificationResult(OperationLog log, RequiredInputParcel requiredInputParcel, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInputParcel, cryptoInputParcel); mProofUrl = null; mPresenceUrl = null; mPresenceLabel = null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java index 38edbf6ee..30307ba46 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java @@ -22,6 +22,7 @@ import android.os.Parcel; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; @@ -37,8 +38,9 @@ public class PgpEditKeyResult extends InputPendingResult { mRingMasterKeyId = ring != null ? ring.getMasterKeyId() : Constants.key.none; } - public PgpEditKeyResult(OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public PgpEditKeyResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); mRingMasterKeyId = Constants.key.none; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java index acb265462..2b33b8ace 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; @@ -38,8 +39,9 @@ public class PgpSignEncryptResult extends InputPendingResult { super(result, log); } - public PgpSignEncryptResult(OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public PgpSignEncryptResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); } public PgpSignEncryptResult(Parcel source) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java index 4b4892b05..160c030fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java @@ -7,6 +7,7 @@ import android.os.Parcelable; import android.support.annotation.Nullable; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.LogDisplayActivity; import org.sufficientlysecure.keychain.ui.LogDisplayFragment; @@ -26,8 +27,9 @@ public class RevokeResult extends InputPendingResult { * @param log operation log upto point of required input, if any * @param requiredInput represents input required */ - public RevokeResult(@Nullable OperationLog log, RequiredInputParcel requiredInput) { - super(log, requiredInput); + public RevokeResult(@Nullable OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); // we won't use these values mMasterKeyId = -1; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java index b05921b0d..39213b796 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java @@ -21,6 +21,7 @@ import android.os.Parcel; import java.util.ArrayList; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; @@ -29,8 +30,10 @@ public class SignEncryptResult extends InputPendingResult { ArrayList mResults; byte[] mResultBytes; - public SignEncryptResult(OperationLog log, RequiredInputParcel requiredInput, ArrayList results) { - super(log, requiredInput); + public SignEncryptResult(OperationLog log, RequiredInputParcel requiredInput, + ArrayList results, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); mResults = results; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 7b61968a3..e264b4678 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -459,7 +459,8 @@ public class PgpDecryptVerify extends BaseOperation log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); return new DecryptVerifyResult(log, RequiredInputParcel.createRequiredDecryptPassphrase( - secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId())); + secretKeyRing.getMasterKeyId(), secretEncryptionKey.getKeyId()), + cryptoInput); } } @@ -498,7 +499,8 @@ public class PgpDecryptVerify extends BaseOperation if (passphrase == null) { log.add(LogType.MSG_DC_PENDING_PASSPHRASE, indent + 1); return new DecryptVerifyResult(log, - RequiredInputParcel.createRequiredSymmetricPassphrase()); + RequiredInputParcel.createRequiredSymmetricPassphrase(), + cryptoInput); } } else { @@ -544,7 +546,7 @@ public class PgpDecryptVerify extends BaseOperation } catch (PGPDataValidationException e) { log.add(LogType.MSG_DC_ERROR_SYM_PASSPHRASE, indent +1); return new DecryptVerifyResult(log, - RequiredInputParcel.createRequiredSymmetricPassphrase()); + RequiredInputParcel.createRequiredSymmetricPassphrase(), cryptoInput); } encryptedData = encryptedDataSymmetric; @@ -580,7 +582,8 @@ public class PgpDecryptVerify extends BaseOperation return new DecryptVerifyResult(log, RequiredInputParcel.createNfcDecryptOperation( secretEncryptionKey.getRing().getMasterKeyId(), secretEncryptionKey.getKeyId(), encryptedDataAsymmetric.getSessionKey()[0] - )); + ), + cryptoInput); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 5eaa03394..565a3bb79 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -469,7 +469,7 @@ public class PgpKeyOperation { log.add(LogType.MSG_MF_REQUIRE_PASSPHRASE, indent); return new PgpEditKeyResult(log, RequiredInputParcel.createRequiredSignPassphrase( masterSecretKey.getKeyID(), masterSecretKey.getKeyID(), - cryptoInput.getSignatureTime())); + cryptoInput.getSignatureTime()), cryptoInput); } // read masterKeyFlags, and use the same as before. @@ -1105,12 +1105,12 @@ public class PgpKeyOperation { if (!nfcSignOps.isEmpty()) { log.add(LogType.MSG_MF_REQUIRE_DIVERT, indent); - return new PgpEditKeyResult(log, nfcSignOps.build()); + return new PgpEditKeyResult(log, nfcSignOps.build(), cryptoInput); } if (!nfcKeyToCardOps.isEmpty()) { log.add(LogType.MSG_MF_REQUIRE_DIVERT, indent); - return new PgpEditKeyResult(log, nfcKeyToCardOps.build()); + return new PgpEditKeyResult(log, nfcKeyToCardOps.build(), cryptoInput); } log.add(LogType.MSG_MF_SUCCESS, indent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 0448e1425..a878b4b29 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -200,7 +200,7 @@ public class PgpSignEncryptOperation extends BaseOperation { log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1); return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredSignPassphrase( signingKeyRing.getMasterKeyId(), signingKey.getKeyId(), - cryptoInput.getSignatureTime())); + cryptoInput.getSignatureTime()), cryptoInput); } if (!signingKey.unlock(localPassphrase)) { log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent); @@ -513,7 +513,7 @@ public class PgpSignEncryptOperation extends BaseOperation { log.add(LogType.MSG_PSE_PENDING_NFC, indent); return new PgpSignEncryptResult(log, RequiredInputParcel.createNfcSignOperation( signingKey.getRing().getMasterKeyId(), signingKey.getKeyId(), - e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime())); + e.hashToSign, e.hashAlgo, cryptoInput.getSignatureTime()), cryptoInput); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java index adf46caf8..4b779e75c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java @@ -27,6 +27,7 @@ import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.Keyserver; import org.sufficientlysecure.keychain.operations.results.GetKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ParcelableProxy; @@ -121,7 +122,8 @@ public class ImportKeysListCloudLoader // user needs to enable/install orbot mEntryList.clear(); GetKeyResult pendingResult = new GetKeyResult(null, - RequiredInputParcel.createOrbotRequiredOperation()); + RequiredInputParcel.createOrbotRequiredOperation(), + new CryptoInputParcel()); mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, pendingResult); return; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index 398b3e778..f703ebbde 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -269,7 +269,7 @@ public class CryptoOperationHelper Date: Fri, 10 Jul 2015 05:21:56 +0530 Subject: added retry on upload failure --- .../keychain/operations/EditKeyOperation.java | 6 +- .../keychain/operations/ExportOperation.java | 3 + .../keychain/operations/results/EditKeyResult.java | 9 +++ .../keychain/service/input/CryptoInputParcel.java | 1 + .../service/input/RequiredInputParcel.java | 6 ++ .../keychain/ui/UploadRetryDialogActivity.java | 68 ++++++++++++++++++++++ .../keychain/ui/base/CryptoOperationHelper.java | 25 ++++++-- 7 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index 6a1c01dd1..8c1bbc0c2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.service.ExportKeyringParcel; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ProgressScaler; @@ -137,13 +138,14 @@ public class EditKeyOperation extends BaseOperation { new ExportKeyringParcel(saveParcel.getUploadKeyserver(), ring); ExportResult uploadResult = new ExportOperation(mContext, mProviderHelper, mProgressable) - .execute(exportKeyringParcel, cryptoInput); + .execute(exportKeyringParcel, cryptoInput); if (uploadResult.isPending()) { return uploadResult; } else if (!uploadResult.success() && saveParcel.isUploadAtomic()) { // if atomic, update fail implies edit operation should also fail and not save log.add(uploadResult, 2); - return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, saveParcel.mMasterKeyId); + return new EditKeyResult(log, RequiredInputParcel.createRetryUploadOperation(), + cryptoInput); } else { // upload succeeded or not atomic so we continue log.add(uploadResult, 2); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java index 5b13fa629..b8b2aebf5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java @@ -91,6 +91,8 @@ public class ExportOperation extends BaseOperation { } public ExportResult uploadKeyRingToServer(HkpKeyserver server, UncachedKeyRing keyring, Proxy proxy) { + mProgressable.setProgress(R.string.progress_uploading, 0, 1); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); ArmoredOutputStream aos = null; OperationLog log = new OperationLog(); @@ -119,6 +121,7 @@ public class ExportOperation extends BaseOperation { log.add(LogType.MSG_EXPORT_ERROR_UPLOAD, 1); return new ExportResult(ExportResult.RESULT_ERROR, log); } finally { + mProgressable.setProgress(R.string.progress_uploading, 1, 1); try { if (aos != null) { aos.close(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java index b9407a864..6098d59d5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java @@ -20,6 +20,9 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; +import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; + public class EditKeyResult extends InputPendingResult { public final Long mMasterKeyId; @@ -29,6 +32,12 @@ public class EditKeyResult extends InputPendingResult { mMasterKeyId = masterKeyId; } + public EditKeyResult(OperationLog log, RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInputParcel) { + super(log, requiredInput, cryptoInputParcel); + mMasterKeyId = null; + } + public EditKeyResult(Parcel source) { super(source); mMasterKeyId = source.readInt() != 0 ? source.readLong() : null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java index 9ba9601e5..e553b9b0f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.service.input; import android.os.Parcel; import android.os.Parcelable; +import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.util.ParcelableProxy; import org.sufficientlysecure.keychain.util.Passphrase; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java index 8eef8de8d..8c9d54769 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java @@ -16,6 +16,7 @@ public class RequiredInputParcel implements Parcelable { public enum RequiredInputType { PASSPHRASE, PASSPHRASE_SYMMETRIC, NFC_SIGN, NFC_DECRYPT, NFC_MOVE_KEY_TO_CARD, ENABLE_ORBOT, + UPLOAD_FAIL_RETRY } public Date mSignatureTime; @@ -77,6 +78,11 @@ public class RequiredInputParcel implements Parcelable { return mSubKeyId; } + public static RequiredInputParcel createRetryUploadOperation() { + return new RequiredInputParcel(RequiredInputType.UPLOAD_FAIL_RETRY, + null, null, null, 0L, 0L); + } + public static RequiredInputParcel createOrbotRequiredOperation() { return new RequiredInputParcel(RequiredInputType.ENABLE_ORBOT, null, null, null, 0L, 0L); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java new file mode 100644 index 000000000..8575d5035 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java @@ -0,0 +1,68 @@ +package org.sufficientlysecure.keychain.ui; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.ContextThemeWrapper; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; + +public class UploadRetryDialogActivity extends FragmentActivity { + + public static final String EXTRA_CRYPTO_INPUT = "extra_crypto_input"; + + public static final String RESULT_CRYPTO_INPUT = "result_crypto_input"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + UploadRetryDialogFragment.newInstance().show(getSupportFragmentManager(), + "uploadRetryDialog"); + } + + public static class UploadRetryDialogFragment extends DialogFragment { + public static UploadRetryDialogFragment newInstance() { + return new UploadRetryDialogFragment(); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + ContextThemeWrapper theme = new ContextThemeWrapper(getActivity(), + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(theme); + dialogBuilder.setTitle(R.string.retry_up_dialog_title); + dialogBuilder.setMessage(R.string.retry_up_dialog_message); + + dialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getActivity().setResult(RESULT_CANCELED); + getActivity().finish(); + } + }); + + dialogBuilder.setPositiveButton(R.string.retry_up_dialog_btn_reupload, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.putExtra(RESULT_CRYPTO_INPUT, getActivity() + .getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT)); + getActivity().setResult(RESULT_OK, intent); + getActivity().finish(); + } + }); + + return dialogBuilder.show(); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index f703ebbde..b6e294579 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.NfcOperationActivity; import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; +import org.sufficientlysecure.keychain.ui.UploadRetryDialogActivity; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -76,6 +77,7 @@ public class CryptoOperationHelper Date: Fri, 10 Jul 2015 06:17:31 +0530 Subject: added licenses, cleaned up code, fixed warnings --- .../keychain/operations/DeleteOperation.java | 9 --- .../keychain/operations/EditKeyOperation.java | 13 ++-- .../keychain/operations/ExportOperation.java | 3 - .../keychain/operations/RevokeOperation.java | 20 ++++- .../operations/results/DecryptVerifyResult.java | 1 - .../operations/results/InputPendingResult.java | 2 - .../keychain/operations/results/RevokeResult.java | 21 ++++++ .../operations/results/SignEncryptResult.java | 3 +- .../keychain/pgp/PgpSignEncryptOperation.java | 1 - .../keychain/pgp/UncachedKeyRing.java | 2 - .../keychain/service/ExportKeyringParcel.java | 1 + .../keychain/service/RevokeKeyringParcel.java | 19 +++++ .../keychain/service/SaveKeyringParcel.java | 1 + .../keychain/service/input/CryptoInputParcel.java | 1 - .../service/input/RequiredInputParcel.java | 1 - .../keychain/ui/DeleteKeyDialogActivity.java | 46 ++++++----- .../keychain/ui/EditKeyFragment.java | 1 - .../keychain/ui/KeyListFragment.java | 9 +-- .../keychain/ui/RetryUploadDialogActivity.java | 88 ++++++++++++++++++++++ .../keychain/ui/UploadRetryDialogActivity.java | 68 ----------------- .../keychain/ui/ViewKeyActivity.java | 5 +- .../ui/adapter/ImportKeysListCloudLoader.java | 11 +-- .../keychain/ui/base/CryptoOperationHelper.java | 8 +- 23 files changed, 196 insertions(+), 138 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RetryUploadDialogActivity.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java index 63c613aa6..56bd3b786 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java @@ -18,29 +18,20 @@ package org.sufficientlysecure.keychain.operations; import android.content.Context; -import android.net.Uri; import android.support.annotation.NonNull; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; import org.sufficientlysecure.keychain.operations.results.DeleteResult; -import org.sufficientlysecure.keychain.operations.results.InputPendingResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.Progressable; -import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; -import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ContactSyncAdapterService; import org.sufficientlysecure.keychain.service.DeleteKeyringParcel; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; -import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.util.Log; /** An operation which implements a high level keyring delete operation. * diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index 8c1bbc0c2..44106bba8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -21,11 +21,9 @@ import android.content.Context; import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.operations.results.EditKeyResult; import org.sufficientlysecure.keychain.operations.results.ExportResult; import org.sufficientlysecure.keychain.operations.results.InputPendingResult; -import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.PgpEditKeyResult; @@ -47,8 +45,9 @@ import org.sufficientlysecure.keychain.util.ProgressScaler; import java.util.concurrent.atomic.AtomicBoolean; -/** An operation which implements a high level key edit operation. - * +/** + * An operation which implements a high level key edit operation. + *

* This operation provides a higher level interface to the edit and * create key operations in PgpKeyOperation. It takes care of fetching * and saving the key before and after the operation. @@ -67,7 +66,7 @@ public class EditKeyOperation extends BaseOperation { * Saves an edited key, and uploads it to a server atomically or otherwise as * specified in saveParcel * - * @param saveParcel primary input to the operation + * @param saveParcel primary input to the operation * @param cryptoInput input that changes if user interaction is required * @return the result of the operation */ @@ -137,8 +136,8 @@ public class EditKeyOperation extends BaseOperation { ExportKeyringParcel exportKeyringParcel = new ExportKeyringParcel(saveParcel.getUploadKeyserver(), ring); ExportResult uploadResult = - new ExportOperation(mContext, mProviderHelper, mProgressable) - .execute(exportKeyringParcel, cryptoInput); + new ExportOperation(mContext, mProviderHelper, mProgressable) + .execute(exportKeyringParcel, cryptoInput); if (uploadResult.isPending()) { return uploadResult; } else if (!uploadResult.success() && saveParcel.isUploadAtomic()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java index b8b2aebf5..a5b70a41f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java @@ -18,7 +18,6 @@ package org.sufficientlysecure.keychain.operations; - import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -34,7 +33,6 @@ import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.text.TextUtils; import org.spongycastle.bcpg.ArmoredOutputStream; @@ -43,7 +41,6 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.HkpKeyserver; import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; import org.sufficientlysecure.keychain.operations.results.ExportResult; -import org.sufficientlysecure.keychain.operations.results.InputPendingResult; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java index 0fc3f1bc3..ecf64e1af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2013-2015 Dominik Schürmann + * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + package org.sufficientlysecure.keychain.operations; import android.content.Context; @@ -6,7 +25,6 @@ import android.net.Uri; import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.operations.results.DeleteResult; import org.sufficientlysecure.keychain.operations.results.InputPendingResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.RevokeResult; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java index 972fbb0aa..f9a738d56 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java @@ -24,7 +24,6 @@ import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.util.Passphrase; public class DecryptVerifyResult extends InputPendingResult { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java index f055c450c..d767382ae 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java @@ -18,8 +18,6 @@ package org.sufficientlysecure.keychain.operations.results; -import java.util.ArrayList; - import android.os.Parcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java index 160c030fd..b737f6e50 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2013-2015 Dominik Schürmann + * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + package org.sufficientlysecure.keychain.operations.results; import android.app.Activity; @@ -24,9 +43,11 @@ public class RevokeResult extends InputPendingResult { /** * used when more input is required + * * @param log operation log upto point of required input, if any * @param requiredInput represents input required */ + @SuppressWarnings("unused") // standard pattern across all results, we might need it later public RevokeResult(@Nullable OperationLog log, RequiredInputParcel requiredInput, CryptoInputParcel cryptoInputParcel) { super(log, requiredInput, cryptoInputParcel); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java index 39213b796..0e0c5d598 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java @@ -19,11 +19,10 @@ package org.sufficientlysecure.keychain.operations.results; import android.os.Parcel; -import java.util.ArrayList; - import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; +import java.util.ArrayList; public class SignEncryptResult extends InputPendingResult { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index a878b4b29..8fb41a909 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -43,7 +43,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java index f4a8fa494..a7baddf8b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java @@ -18,8 +18,6 @@ package org.sufficientlysecure.keychain.pgp; -import android.os.Parcelable; - import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.SignatureSubpacketTags; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java index a8b901ab0..24c002bbd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java @@ -61,6 +61,7 @@ public class ExportKeyringParcel implements Parcelable { mOutputFile = outputFile; } + @SuppressWarnings("unused") // TODO: is it used? public ExportKeyringParcel(long[] masterKeyIds, boolean exportSecret, Uri outputUri) { mExportType = ExportType.EXPORT_URI; mMasterKeyIds = masterKeyIds; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java index b5da31c59..02e8fda46 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2013-2015 Dominik Schürmann + * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + package org.sufficientlysecure.keychain.service; import android.os.Parcel; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index fcb95493b..6959fca56 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -242,6 +242,7 @@ public class SaveKeyringParcel implements Parcelable { } } + @SuppressWarnings("unchecked") // we verify the reads against writes in writeToParcel public SaveKeyringParcel(Parcel source) { mMasterKeyId = source.readInt() != 0 ? source.readLong() : null; mFingerprint = source.createByteArray(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java index e553b9b0f..9ba9601e5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java @@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.service.input; import android.os.Parcel; import android.os.Parcelable; -import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.util.ParcelableProxy; import org.sufficientlysecure.keychain.util.Passphrase; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java index 8c9d54769..e4dac3227 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java @@ -3,7 +3,6 @@ package org.sufficientlysecure.keychain.service.input; import android.os.Parcel; import android.os.Parcelable; -import org.spongycastle.util.Arrays; import org.sufficientlysecure.keychain.util.Passphrase; import java.nio.ByteBuffer; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index 98d3cf7b0..bf91d3064 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2013-2015 Dominik Schürmann + * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + package org.sufficientlysecure.keychain.ui; import android.app.Activity; @@ -6,12 +25,7 @@ import android.app.Dialog; 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.os.RemoteException; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.view.ContextThemeWrapper; @@ -47,7 +61,6 @@ public class DeleteKeyDialogActivity extends FragmentActivity { private CryptoOperationHelper mRevokeOpHelper; private long[] mMasterKeyIds; - private boolean mHasSecret; @Override protected void onCreate(Bundle savedInstanceState) { @@ -60,14 +73,14 @@ public class DeleteKeyDialogActivity extends FragmentActivity { getRevocationCallback(), R.string.progress_revoking_uploading); mMasterKeyIds = getIntent().getLongArrayExtra(EXTRA_DELETE_MASTER_KEY_IDS); - mHasSecret = getIntent().getBooleanExtra(EXTRA_HAS_SECRET, false); + boolean hasSecret = getIntent().getBooleanExtra(EXTRA_HAS_SECRET, false); - if (mMasterKeyIds.length > 1 && mHasSecret) { + if (mMasterKeyIds.length > 1 && hasSecret) { throw new AssertionError("Secret keys can be deleted only one at a time!" + " Should be checked before reaching DeleteKeyDialogActivity."); } - if (mMasterKeyIds.length == 1 && mHasSecret) { + if (mMasterKeyIds.length == 1 && hasSecret) { // if mMasterKeyIds.length == 0 we let the DeleteOperation respond try { HashMap data = new ProviderHelper(this).getUnifiedData( @@ -89,7 +102,6 @@ public class DeleteKeyDialogActivity extends FragmentActivity { "Secret key to delete not found at DeleteKeyDialogActivity for " + mMasterKeyIds[0], e); finish(); - return; } } else { showNormalDeleteDialog(); @@ -121,8 +133,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { private CryptoOperationHelper.Callback getRevocationCallback() { - CryptoOperationHelper.Callback callback - = new CryptoOperationHelper.Callback() { + return new CryptoOperationHelper.Callback() { @Override public RevokeKeyringParcel createOperationInput() { return new RevokeKeyringParcel(mMasterKeyIds[0], true, @@ -150,14 +161,11 @@ public class DeleteKeyDialogActivity extends FragmentActivity { return false; } }; - - return callback; } private CryptoOperationHelper.Callback getDeletionCallback() { - CryptoOperationHelper.Callback callback - = new CryptoOperationHelper.Callback() { + return new CryptoOperationHelper.Callback() { @Override public DeleteKeyringParcel createOperationInput() { return new DeleteKeyringParcel(mMasterKeyIds, true); @@ -184,8 +192,6 @@ public class DeleteKeyDialogActivity extends FragmentActivity { return false; } }; - - return callback; } private void returnResult(OperationResult result) { @@ -305,10 +311,10 @@ public class DeleteKeyDialogActivity extends FragmentActivity { public static class RevokeDeleteDialogFragment extends DialogFragment { public static RevokeDeleteDialogFragment newInstance() { - RevokeDeleteDialogFragment frag = new RevokeDeleteDialogFragment(); - return frag; + return new RevokeDeleteDialogFragment(); } + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index f750c6d97..4e9c5a836 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -410,7 +410,6 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment 1) { Notify.create(getActivity(), R.string.secret_cannot_multiple, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RetryUploadDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RetryUploadDialogActivity.java new file mode 100644 index 000000000..85f2096db --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RetryUploadDialogActivity.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013-2015 Dominik Schürmann + * Copyright (C) 2015 Vincent Breitmoser + * Copyright (C) 2015 Adithya Abraham Philip + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.view.ContextThemeWrapper; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; + +public class RetryUploadDialogActivity extends FragmentActivity { + + public static final String EXTRA_CRYPTO_INPUT = "extra_crypto_input"; + + public static final String RESULT_CRYPTO_INPUT = "result_crypto_input"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + UploadRetryDialogFragment.newInstance().show(getSupportFragmentManager(), + "uploadRetryDialog"); + } + + public static class UploadRetryDialogFragment extends DialogFragment { + public static UploadRetryDialogFragment newInstance() { + return new UploadRetryDialogFragment(); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + ContextThemeWrapper theme = new ContextThemeWrapper(getActivity(), + R.style.Theme_AppCompat_Light_Dialog); + + CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(theme); + dialogBuilder.setTitle(R.string.retry_up_dialog_title); + dialogBuilder.setMessage(R.string.retry_up_dialog_message); + + dialogBuilder.setNegativeButton(R.string.retry_up_dialog_btn_cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getActivity().setResult(RESULT_CANCELED); + getActivity().finish(); + } + }); + + dialogBuilder.setPositiveButton(R.string.retry_up_dialog_btn_reupload, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(); + intent.putExtra(RESULT_CRYPTO_INPUT, getActivity() + .getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT)); + getActivity().setResult(RESULT_OK, intent); + getActivity().finish(); + } + }); + + return dialogBuilder.show(); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java deleted file mode 100644 index 8575d5035..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadRetryDialogActivity.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.sufficientlysecure.keychain.ui; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.view.ContextThemeWrapper; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; - -public class UploadRetryDialogActivity extends FragmentActivity { - - public static final String EXTRA_CRYPTO_INPUT = "extra_crypto_input"; - - public static final String RESULT_CRYPTO_INPUT = "result_crypto_input"; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - UploadRetryDialogFragment.newInstance().show(getSupportFragmentManager(), - "uploadRetryDialog"); - } - - public static class UploadRetryDialogFragment extends DialogFragment { - public static UploadRetryDialogFragment newInstance() { - return new UploadRetryDialogFragment(); - } - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - - ContextThemeWrapper theme = new ContextThemeWrapper(getActivity(), - R.style.Theme_AppCompat_Light_Dialog); - - CustomAlertDialogBuilder dialogBuilder = new CustomAlertDialogBuilder(theme); - dialogBuilder.setTitle(R.string.retry_up_dialog_title); - dialogBuilder.setMessage(R.string.retry_up_dialog_message); - - dialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - getActivity().setResult(RESULT_CANCELED); - getActivity().finish(); - } - }); - - dialogBuilder.setPositiveButton(R.string.retry_up_dialog_btn_reupload, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(); - intent.putExtra(RESULT_CRYPTO_INPUT, getActivity() - .getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT)); - getActivity().setResult(RESULT_OK, intent); - getActivity().finish(); - } - }); - - return dialogBuilder.show(); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 08ef38746..938dbc9f2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -31,8 +31,6 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.os.Message; -import android.os.Messenger; import android.provider.ContactsContract; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentManager; @@ -52,7 +50,9 @@ import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; + import com.getbase.floatingactionbutton.FloatingActionButton; + import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; @@ -65,7 +65,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.ImportKeyringParcel; -import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.util.FormattingUtils; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java index 4b779e75c..e77c92923 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java @@ -49,12 +49,13 @@ public class ImportKeysListCloudLoader private AsyncTaskResultWrapper> mEntryListWrapper; /** - * Pass a parcelableProxy to specify an explicit proxy, otherwise will fetch from preferences + * Searches a keyserver as specified in cloudPrefs, using an explicit proxy if passed * - * @param context - * @param serverQuery - * @param cloudPrefs - * @param parcelableProxy + * @param serverQuery string to search on servers for. If is a fingerprint, + * will enforce fingerprint check + * @param cloudPrefs contains keyserver to search on, whether to search on the keyserver, + * and whether to search keybase.io + * @param parcelableProxy explicit proxy to use. If null, will retrieve from preferences */ public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs, @Nullable ParcelableProxy parcelableProxy) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index b6e294579..932b6c007 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -40,7 +40,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.NfcOperationActivity; import org.sufficientlysecure.keychain.ui.OrbotRequiredDialogActivity; import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; -import org.sufficientlysecure.keychain.ui.UploadRetryDialogActivity; +import org.sufficientlysecure.keychain.ui.RetryUploadDialogActivity; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.util.Log; @@ -148,8 +148,8 @@ public class CryptoOperationHelper Date: Fri, 10 Jul 2015 07:18:00 +0530 Subject: made key deletion require double confirmation --- .../org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index bf91d3064..57b74f1be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -357,7 +357,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { .startRevocationOperation(); } else if (choice.equals(CHOICE_DELETE)) { ((DeleteKeyDialogActivity) activity) - .startDeletionOperation(); + .showNormalDeleteDialog(); } else { throw new AssertionError( "Unsupported delete type in RevokeDeleteDialogFragment"); -- cgit v1.2.3 From 0cec75fc9d47c4728678418727559e523295ae21 Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Fri, 10 Jul 2015 07:47:38 +0530 Subject: show key name on revoke/delete dialog --- .../keychain/ui/DeleteKeyDialogActivity.java | 29 +++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index 57b74f1be..ec9d7d74c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -92,10 +92,20 @@ public class DeleteKeyDialogActivity extends FragmentActivity { ProviderHelper.FIELD_TYPE_INTEGER } ); + + String name; + KeyRing.UserId mainUserId = KeyRing.splitUserId( + (String) data.get(KeychainContract.KeyRings.USER_ID)); + if (mainUserId.name != null) { + name = mainUserId.name; + } else { + name = getString(R.string.user_id_no_name); + } + if ((long) data.get(KeychainContract.KeyRings.IS_REVOKED) > 0) { showNormalDeleteDialog(); } else { - showRevokeDeleteDialog(); + showRevokeDeleteDialog(name); } } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, @@ -117,9 +127,9 @@ public class DeleteKeyDialogActivity extends FragmentActivity { } - private void showRevokeDeleteDialog() { + private void showRevokeDeleteDialog(String keyname) { - RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(); + RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(keyname); fragment.show(getSupportFragmentManager(), "deleteRevokeDialog"); } @@ -310,8 +320,14 @@ public class DeleteKeyDialogActivity extends FragmentActivity { public static class RevokeDeleteDialogFragment extends DialogFragment { - public static RevokeDeleteDialogFragment newInstance() { - return new RevokeDeleteDialogFragment(); + public static final String ARG_KEY_NAME = "arg_key_name"; + + public static RevokeDeleteDialogFragment newInstance(String keyName) { + Bundle args = new Bundle(); + args.putString(ARG_KEY_NAME, keyName); + RevokeDeleteDialogFragment frag = new RevokeDeleteDialogFragment(); + frag.setArguments(args); + return frag; } @NonNull @@ -328,7 +344,8 @@ public class DeleteKeyDialogActivity extends FragmentActivity { R.style.Theme_AppCompat_Light_Dialog); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); - alert.setTitle(R.string.del_rev_dialog_title); + alert.setTitle(getString(R.string.del_rev_dialog_title, + getArguments().get(ARG_KEY_NAME))); LayoutInflater inflater = LayoutInflater.from(theme); View view = inflater.inflate(R.layout.del_rev_dialog, null); -- cgit v1.2.3 From 8bbc5513d447d186497023ca3f0c474541419389 Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Fri, 10 Jul 2015 08:29:29 +0530 Subject: corrected DeleteKeyDialogActivity finishing on cancel --- .../keychain/ui/DeleteKeyDialogActivity.java | 30 +++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index ec9d7d74c..148ca3346 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -310,12 +310,19 @@ public class DeleteKeyDialogActivity extends FragmentActivity { @Override public void onClick(DialogInterface dialog, int id) { - getActivity().finish(); + dialog.cancel(); } }); return builder.show(); } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + getActivity().setResult(RESULT_CANCELED); + getActivity().finish(); + } } public static class RevokeDeleteDialogFragment extends DialogFragment { @@ -343,27 +350,25 @@ public class DeleteKeyDialogActivity extends FragmentActivity { ContextThemeWrapper theme = new ContextThemeWrapper(activity, R.style.Theme_AppCompat_Light_Dialog); - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(theme); - alert.setTitle(getString(R.string.del_rev_dialog_title, + CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(theme); + builder.setTitle(getString(R.string.del_rev_dialog_title, getArguments().get(ARG_KEY_NAME))); LayoutInflater inflater = LayoutInflater.from(theme); View view = inflater.inflate(R.layout.del_rev_dialog, null); - alert.setView(view); + builder.setView(view); final Spinner spinner = (Spinner) view.findViewById(R.id.spinner); - alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dialog.cancel(); - activity.setResult(RESULT_CANCELED); - activity.finish(); } }); - alert.setPositiveButton(R.string.del_rev_dialog_btn_revoke, + builder.setPositiveButton(R.string.del_rev_dialog_btn_revoke, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { @@ -382,7 +387,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { } }); - final AlertDialog alertDialog = alert.show(); + final AlertDialog alertDialog = builder.show(); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView parent, View view, int pos, long id) { @@ -407,6 +412,13 @@ public class DeleteKeyDialogActivity extends FragmentActivity { return alertDialog; } + + @Override + public void onCancel(DialogInterface dialog) { + super.onCancel(dialog); + getActivity().setResult(RESULT_CANCELED); + getActivity().finish(); + } } } -- cgit v1.2.3 From c59196a6f1e5dd4e3b2ac864067cc7f469de01ac Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Sat, 11 Jul 2015 03:55:50 +0530 Subject: upload only public key in revocation --- .../keychain/operations/EditKeyOperation.java | 14 +++++++++++++- .../keychain/operations/results/OperationResult.java | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java index 44106bba8..f5ba88502 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java @@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.ProgressScaler; +import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -133,11 +134,22 @@ public class EditKeyOperation extends BaseOperation { UncachedKeyRing ring = modifyResult.getRing(); if (saveParcel.isUpload()) { + UncachedKeyRing publicKeyRing; + try { + publicKeyRing = ring.extractPublicKeyRing(); + } catch (IOException e) { + log.add(LogType.MSG_ED_ERROR_EXTRACTING_PUBLIC_UPLOAD, 1); + return new EditKeyResult(EditKeyResult.RESULT_ERROR, log, null); + } + ExportKeyringParcel exportKeyringParcel = - new ExportKeyringParcel(saveParcel.getUploadKeyserver(), ring); + new ExportKeyringParcel(saveParcel.getUploadKeyserver(), + publicKeyRing); + ExportResult uploadResult = new ExportOperation(mContext, mProviderHelper, mProgressable) .execute(exportKeyringParcel, cryptoInput); + if (uploadResult.isPending()) { return uploadResult; } else if (!uploadResult.success() && saveParcel.isUploadAtomic()) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index c65412a1f..d4b3c433f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -571,6 +571,8 @@ public abstract class OperationResult implements Parcelable { MSG_ED_CACHING_NEW (LogLevel.DEBUG, R.string.msg_ed_caching_new), MSG_ED_ERROR_NO_PARCEL (LogLevel.ERROR, R.string.msg_ed_error_no_parcel), MSG_ED_ERROR_KEY_NOT_FOUND (LogLevel.ERROR, R.string.msg_ed_error_key_not_found), + MSG_ED_ERROR_EXTRACTING_PUBLIC_UPLOAD (LogLevel.ERROR, + R.string.msg_ed_error_extract_public_upload), MSG_ED_FETCHING (LogLevel.DEBUG, R.string.msg_ed_fetching), MSG_ED_SUCCESS (LogLevel.OK, R.string.msg_ed_success), -- cgit v1.2.3 From c1d2beb55986138a21a40cc6ba6d64684e1798dc Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Sat, 11 Jul 2015 16:31:29 +0530 Subject: made PassphraseDialogActivity compatible with null CryptoInputParcel --- .../keychain/ui/NfcOperationActivity.java | 20 ++++++++++++++++---- .../keychain/ui/PassphraseDialogActivity.java | 5 +++++ .../keychain/ui/base/CryptoOperationHelper.java | 4 ++-- 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java index 8802cd621..e9066b76c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java @@ -43,11 +43,12 @@ import java.util.Arrays; public class NfcOperationActivity extends BaseNfcActivity { public static final String EXTRA_REQUIRED_INPUT = "required_input"; + public static final String EXTRA_CRYPTO_INPUT = "crypto_input"; // passthrough for OpenPgpService public static final String EXTRA_SERVICE_INTENT = "data"; - public static final String RESULT_DATA = "result_data"; + public static final String RESULT_CRYPTO_INPUT = "result_data"; public ViewAnimator vAnimator; public TextView vErrorText; @@ -67,6 +68,14 @@ public class NfcOperationActivity extends BaseNfcActivity { getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + mInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT); + + if (mInputParcel == null) { + // for compatibility when used from OpenPgpService + // (or any place other than CryptoOperationHelper) + mInputParcel = new CryptoInputParcel(mRequiredInput.mSignatureTime); + } + setTitle(R.string.nfc_text); vAnimator = (ViewAnimator) findViewById(R.id.view_animator); @@ -112,8 +121,6 @@ public class NfcOperationActivity extends BaseNfcActivity { @Override protected void doNfcInBackground() throws IOException { - mInputParcel = new CryptoInputParcel(mRequiredInput.mSignatureTime); - switch (mRequiredInput.mType) { case NFC_DECRYPT: { for (int i = 0; i < mRequiredInput.mInputData.length; i++) { @@ -218,11 +225,16 @@ public class NfcOperationActivity extends BaseNfcActivity { @Override protected void onNfcPostExecute() throws IOException { if (mServiceIntent != null) { + // if we're triggered by OpenPgpService CryptoInputParcelCacheService.addCryptoInputParcel(this, mServiceIntent, mInputParcel); + mServiceIntent.putExtra(EXTRA_CRYPTO_INPUT, + getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT)); setResult(RESULT_OK, mServiceIntent); } else { Intent result = new Intent(); - result.putExtra(NfcOperationActivity.RESULT_DATA, mInputParcel); + result.putExtra(RESULT_CRYPTO_INPUT, mInputParcel); + // send back the CryptoInputParcel we receive, to conform with the pattern in + // CryptoOperationHelper setResult(RESULT_OK, result); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java index c9f6423d6..d68b39fc1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java @@ -95,6 +95,11 @@ public class PassphraseDialogActivity extends FragmentActivity { mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT); + if (mCryptoInputParcel == null) { + // not all usages of PassphraseActivity are from CryptoInputOperation + mCryptoInputParcel = new CryptoInputParcel(); + } + // this activity itself has no content view (see manifest) if (getIntent().hasExtra(EXTRA_SUBKEY_ID)) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java index 932b6c007..b33128978 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java @@ -120,13 +120,13 @@ public class CryptoOperationHelper Date: Mon, 13 Jul 2015 03:23:56 +0530 Subject: added revocation tag NO_REASON to all revocations via PgpKeyOperation --- .../java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java | 7 +++++++ .../sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 565a3bb79..c82cbce8f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -22,6 +22,7 @@ import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.bcpg.S2K; import org.spongycastle.bcpg.sig.Features; import org.spongycastle.bcpg.sig.KeyFlags; +import org.spongycastle.bcpg.sig.RevocationReasonTags; import org.spongycastle.jce.spec.ElGamalParameterSpec; import org.spongycastle.openpgp.PGPException; import org.spongycastle.openpgp.PGPKeyFlags; @@ -1525,6 +1526,9 @@ public class PgpKeyOperation { throws IOException, PGPException, SignatureException { PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); + // we use the tag NO_REASON since gnupg does not care about the tag while verifying + // signatures with a revoked key, the warning is the same + subHashedPacketsGen.setRevocationReason(true, RevocationReasonTags.NO_REASON, ""); subHashedPacketsGen.setSignatureCreationTime(true, creationTime); sGen.setHashedSubpackets(subHashedPacketsGen.generate()); sGen.init(PGPSignature.CERTIFICATION_REVOCATION, masterPrivateKey); @@ -1537,6 +1541,9 @@ public class PgpKeyOperation { throws IOException, PGPException, SignatureException { PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); + // we use the tag NO_REASON since gnupg does not care about the tag while verifying + // signatures with a revoked key, the warning is the same + subHashedPacketsGen.setRevocationReason(true, RevocationReasonTags.NO_REASON, ""); subHashedPacketsGen.setSignatureCreationTime(true, creationTime); sGen.setHashedSubpackets(subHashedPacketsGen.generate()); // Generate key revocation or subkey revocation, depending on master/subkey-ness diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index 148ca3346..924d62199 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -20,7 +20,7 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.app.AlertDialog; +import android.support.v7.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; -- cgit v1.2.3 From 771d65476647c4df0d88e95f8df80b201eeb9bf3 Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Wed, 15 Jul 2015 07:26:45 +0530 Subject: made mSignatureTime optional in CryptoOperationHelper --- .../keychain/remote/OpenPgpService.java | 32 ++++++++++++++-------- .../keychain/service/input/CryptoInputParcel.java | 32 +++++++++++++++++----- .../keychain/ui/CertifyKeyFragment.java | 4 ++- .../keychain/ui/CreateKeyFinalFragment.java | 4 ++- .../keychain/ui/DeleteKeyDialogActivity.java | 3 +- .../keychain/ui/EditKeyFragment.java | 4 ++- .../keychain/ui/EncryptFilesFragment.java | 10 ++++--- .../keychain/ui/EncryptTextFragment.java | 6 ++-- .../keychain/ui/NfcOperationActivity.java | 9 +++++- .../keychain/ui/PassphraseDialogActivity.java | 7 ++++- 10 files changed, 80 insertions(+), 31 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index af99f01c9..2568d68b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -64,6 +64,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Date; import java.util.HashSet; public class OpenPgpService extends RemoteService { @@ -164,7 +165,9 @@ public class OpenPgpService extends RemoteService { } private static PendingIntent getRequiredInputPendingIntent(Context context, - Intent data, RequiredInputParcel requiredInput) { + Intent data, + RequiredInputParcel requiredInput, + CryptoInputParcel cryptoInput) { switch (requiredInput.mType) { case NFC_MOVE_KEY_TO_CARD: @@ -175,6 +178,7 @@ public class OpenPgpService extends RemoteService { // pass params through to activity that it can be returned again later to repeat pgp operation intent.putExtra(NfcOperationActivity.EXTRA_SERVICE_INTENT, data); intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput); + intent.putExtra(NfcOperationActivity.EXTRA_CRYPTO_INPUT, cryptoInput); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); } @@ -185,6 +189,7 @@ public class OpenPgpService extends RemoteService { // pass params through to activity that it can be returned again later to repeat pgp operation intent.putExtra(PassphraseDialogActivity.EXTRA_SERVICE_INTENT, data); intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput); + intent.putExtra(PassphraseDialogActivity.EXTRA_CRYPTO_INPUT, cryptoInput); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); } @@ -279,12 +284,12 @@ public class OpenPgpService extends RemoteService { CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data); if (inputParcel == null) { - inputParcel = new CryptoInputParcel(); + inputParcel = new CryptoInputParcel(new Date()); } // override passphrase in input parcel if given by API call if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { - inputParcel = new CryptoInputParcel(inputParcel.getSignatureTime(), - new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE))); + inputParcel.mPassphrase = + new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); } // execute PGP operation! @@ -294,7 +299,8 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel(); - PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput); + PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, + requiredInput, pgpResult.mCryptoInputParcel); // return PendingIntent to be executed by client Intent result = new Intent(); @@ -434,12 +440,12 @@ public class OpenPgpService extends RemoteService { CryptoInputParcel inputParcel = CryptoInputParcelCacheService.getCryptoInputParcel(this, data); if (inputParcel == null) { - inputParcel = new CryptoInputParcel(); + inputParcel = new CryptoInputParcel(new Date()); } // override passphrase in input parcel if given by API call if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { - inputParcel = new CryptoInputParcel(inputParcel.getSignatureTime(), - new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE))); + inputParcel.mPassphrase = + new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); } PgpSignEncryptOperation op = new PgpSignEncryptOperation(this, new ProviderHelper(getContext()), null); @@ -449,7 +455,8 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel(); - PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput); + PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, + requiredInput, pgpResult.mCryptoInputParcel); // return PendingIntent to be executed by client Intent result = new Intent(); @@ -519,8 +526,8 @@ public class OpenPgpService extends RemoteService { } // override passphrase in input parcel if given by API call if (data.hasExtra(OpenPgpApi.EXTRA_PASSPHRASE)) { - cryptoInput = new CryptoInputParcel(cryptoInput.getSignatureTime(), - new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE))); + cryptoInput.mPassphrase = + new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE)); } byte[] detachedSignature = data.getByteArrayExtra(OpenPgpApi.EXTRA_DETACHED_SIGNATURE); @@ -543,7 +550,8 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { // prepare and return PendingIntent to be executed by client RequiredInputParcel requiredInput = pgpResult.getRequiredInputParcel(); - PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, requiredInput); + PendingIntent pIntent = getRequiredInputPendingIntent(getBaseContext(), data, + requiredInput, pgpResult.mCryptoInputParcel); Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_INTENT, pIntent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java index 9ba9601e5..0d8569fe6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java @@ -33,7 +33,9 @@ import java.util.Map; */ public class CryptoInputParcel implements Parcelable { - final Date mSignatureTime; + private Date mSignatureTime; + private boolean mHasSignature; + public Passphrase mPassphrase; // used to supply an explicit proxy to operations that require it // this is not final so it can be added to an existing CryptoInputParcel @@ -48,24 +50,25 @@ public class CryptoInputParcel implements Parcelable { private HashMap mCryptoData = new HashMap<>(); public CryptoInputParcel() { - mSignatureTime = new Date(); + mSignatureTime = null; mPassphrase = null; mCachePassphrase = true; } public CryptoInputParcel(Date signatureTime, Passphrase passphrase) { + mHasSignature = true; mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = passphrase; mCachePassphrase = true; } public CryptoInputParcel(Passphrase passphrase) { - mSignatureTime = new Date(); mPassphrase = passphrase; mCachePassphrase = true; } public CryptoInputParcel(Date signatureTime) { + mHasSignature = true; mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = null; mCachePassphrase = true; @@ -76,14 +79,22 @@ public class CryptoInputParcel implements Parcelable { mParcelableProxy = parcelableProxy; } - public CryptoInputParcel(boolean cachePassphrase) { - mSignatureTime = new Date(); + public CryptoInputParcel(Date signatureTime, boolean cachePassphrase) { + mHasSignature = true; + mSignatureTime = signatureTime == null ? new Date() : signatureTime; mPassphrase = null; mCachePassphrase = cachePassphrase; } + public CryptoInputParcel(boolean cachePassphrase) { + mCachePassphrase = cachePassphrase; + } + protected CryptoInputParcel(Parcel source) { - mSignatureTime = new Date(source.readLong()); + mHasSignature = source.readByte() != 0; + if (mHasSignature) { + mSignatureTime = new Date(source.readLong()); + } mPassphrase = source.readParcelable(getClass().getClassLoader()); mParcelableProxy = source.readParcelable(getClass().getClassLoader()); mCachePassphrase = source.readByte() != 0; @@ -107,7 +118,10 @@ public class CryptoInputParcel implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeLong(mSignatureTime.getTime()); + dest.writeByte((byte) (mHasSignature ? 1 : 0)); + if (mHasSignature) { + dest.writeLong(mSignatureTime.getTime()); + } dest.writeParcelable(mPassphrase, 0); dest.writeParcelable(mParcelableProxy, 0); dest.writeByte((byte) (mCachePassphrase ? 1 : 0)); @@ -123,6 +137,10 @@ public class CryptoInputParcel implements Parcelable { mParcelableProxy = parcelableProxy; } + public void addSignatureTime(Date signatureTime) { + mSignatureTime = signatureTime; + } + public void addCryptoData(byte[] hash, byte[] signedHash) { mCryptoData.put(ByteBuffer.wrap(hash), signedHash); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 467eab785..65baf0593 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -49,6 +49,7 @@ import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.CertifyActionsParcel; import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.adapter.MultiUserIdsAdapter; import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment; import org.sufficientlysecure.keychain.ui.util.Notify; @@ -57,6 +58,7 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; import java.util.ArrayList; +import java.util.Date; public class CertifyKeyFragment extends CachingCryptoOperationFragment @@ -165,7 +167,7 @@ public class CertifyKeyFragment Notify.create(getActivity(), getString(R.string.select_key_to_certify), Notify.Style.ERROR).show(); } else { - cryptoOperation(); + cryptoOperation(new CryptoInputParcel(new Date())); } } }); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 65bdca5c4..739eb3e35 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui; +import java.util.Date; import java.util.Iterator; import android.app.Activity; @@ -47,6 +48,7 @@ import org.sufficientlysecure.keychain.service.ExportKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel; +import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.util.Log; @@ -393,7 +395,7 @@ public class CreateKeyFinalFragment extends Fragment { mMoveToCardOpHelper = new CryptoOperationHelper<>(2, this, callback, R.string.progress_modify); - mMoveToCardOpHelper.cryptoOperation(); + mMoveToCardOpHelper.cryptoOperation(new CryptoInputParcel(new Date())); } private void uploadKey(final EditKeyResult saveKeyResult) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index 924d62199..1b4083a94 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -50,6 +50,7 @@ import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; import org.sufficientlysecure.keychain.util.Log; +import java.util.Date; import java.util.HashMap; public class DeleteKeyDialogActivity extends FragmentActivity { @@ -134,7 +135,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { } private void startRevocationOperation() { - mRevokeOpHelper.cryptoOperation(new CryptoInputParcel(false)); + mRevokeOpHelper.cryptoOperation(new CryptoInputParcel(new Date(), false)); } private void startDeletionOperation() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 4e9c5a836..4769e68d8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -68,6 +68,8 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; +import java.util.Date; + public class EditKeyFragment extends QueueingCryptoOperationFragment implements LoaderManager.LoaderCallbacks { @@ -151,7 +153,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment * For the full specs, see http://g10code.com/docs/openpgp-card-2.0.pdf + * NOTE: If no CryptoInputParcel is passed via EXTRA_CRYPTO_INPUT, the CryptoInputParcel is created + * internally and is NOT meant to be used by signing operations before adding signature time */ public class NfcOperationActivity extends BaseNfcActivity { @@ -73,7 +76,8 @@ public class NfcOperationActivity extends BaseNfcActivity { if (mInputParcel == null) { // for compatibility when used from OpenPgpService // (or any place other than CryptoOperationHelper) - mInputParcel = new CryptoInputParcel(mRequiredInput.mSignatureTime); + // NOTE: This CryptoInputParcel cannot be used for signing without adding signature time + mInputParcel = new CryptoInputParcel(); } setTitle(R.string.nfc_text); @@ -131,6 +135,9 @@ public class NfcOperationActivity extends BaseNfcActivity { break; } case NFC_SIGN: { + if (mInputParcel.getSignatureTime() == null) { + mInputParcel.addSignatureTime(new Date()); + } for (int i = 0; i < mRequiredInput.mInputData.length; i++) { byte[] hash = mRequiredInput.mInputData[i]; int algo = mRequiredInput.mSignAlgos[i]; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java index d68b39fc1..8b482584d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java @@ -66,6 +66,8 @@ import org.sufficientlysecure.keychain.util.Preferences; /** * We can not directly create a dialog on the application context. * This activity encapsulates a DialogFragment to emulate a dialog. + * NOTE: If no CryptoInputParcel is passed via EXTRA_CRYPTO_INPUT, the CryptoInputParcel is created + * internally and is NOT meant to be used by signing operations before adding a signature time */ public class PassphraseDialogActivity extends FragmentActivity { public static final String RESULT_CRYPTO_INPUT = "result_data"; @@ -97,6 +99,8 @@ public class PassphraseDialogActivity extends FragmentActivity { if (mCryptoInputParcel == null) { // not all usages of PassphraseActivity are from CryptoInputOperation + // NOTE: This CryptoInputParcel cannot be used for signing operations without setting + // signature time mCryptoInputParcel = new CryptoInputParcel(); } @@ -123,7 +127,8 @@ public class PassphraseDialogActivity extends FragmentActivity { SecretKeyType.PASSPHRASE_EMPTY) { // also return passphrase back to activity Intent returnIntent = new Intent(); - returnIntent.putExtra(RESULT_CRYPTO_INPUT, new CryptoInputParcel(new Passphrase(""))); + mCryptoInputParcel.mPassphrase = new Passphrase(""); + returnIntent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel); setResult(RESULT_OK, returnIntent); finish(); return; -- cgit v1.2.3 From fe0b083bc5fdcd3cd4543945ef22bcec7a2876f4 Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Wed, 15 Jul 2015 20:16:07 +0530 Subject: fixed multi-deletion bug, moved logic into DeleteKeyDialogActivity --- .../keychain/operations/results/DeleteResult.java | 5 +++- .../operations/results/OperationResult.java | 2 +- .../keychain/ui/DeleteKeyDialogActivity.java | 29 +++++++++++++--------- .../keychain/ui/KeyListFragment.java | 7 ------ 4 files changed, 22 insertions(+), 21 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java index c7c48ed56..1a8f10d4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java @@ -125,7 +125,10 @@ public class DeleteResult extends InputPendingResult { } else { duration = 0; style = Style.ERROR; - if (mFail == 0) { + if (mLog.getLast().mType == LogType.MSG_DEL_ERROR_MULTI_SECRET) { + str = activity.getString(R.string.secret_cannot_multiple); + } + else if (mFail == 0) { str = activity.getString(R.string.delete_nothing); } else { str = activity.getResources().getQuantityString(R.plurals.delete_fail, mFail); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index d4b3c433f..04013e9ed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -754,7 +754,7 @@ public abstract class OperationResult implements Parcelable { MSG_GET_QUERY_FAILED(LogLevel.ERROR, R.string.msg_download_query_failed), MSG_DEL_ERROR_EMPTY (LogLevel.ERROR, R.string.msg_del_error_empty), - MSG_DEL_ERROR_MULTI_SECRET (LogLevel.DEBUG, R.string.msg_del_error_multi_secret), + MSG_DEL_ERROR_MULTI_SECRET (LogLevel.ERROR, R.string.msg_del_error_multi_secret), MSG_DEL (LogLevel.START, R.plurals.msg_del), MSG_DEL_KEY (LogLevel.DEBUG, R.string.msg_del_key), MSG_DEL_KEY_FAIL (LogLevel.WARN, R.string.msg_del_key_fail), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java index 1b4083a94..4c1dbd1ee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java @@ -48,6 +48,7 @@ import org.sufficientlysecure.keychain.service.RevokeKeyringParcel; import org.sufficientlysecure.keychain.service.input.CryptoInputParcel; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; +import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import java.util.Date; @@ -62,6 +63,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { private CryptoOperationHelper mRevokeOpHelper; private long[] mMasterKeyIds; + private boolean mHasSecret; @Override protected void onCreate(Bundle savedInstanceState) { @@ -74,14 +76,17 @@ public class DeleteKeyDialogActivity extends FragmentActivity { getRevocationCallback(), R.string.progress_revoking_uploading); mMasterKeyIds = getIntent().getLongArrayExtra(EXTRA_DELETE_MASTER_KEY_IDS); - boolean hasSecret = getIntent().getBooleanExtra(EXTRA_HAS_SECRET, false); - - if (mMasterKeyIds.length > 1 && hasSecret) { - throw new AssertionError("Secret keys can be deleted only one at a time!" + - " Should be checked before reaching DeleteKeyDialogActivity."); + mHasSecret = getIntent().getBooleanExtra(EXTRA_HAS_SECRET, false); + + if (mMasterKeyIds.length > 1 && mHasSecret) { + // secret keys can only be deleted individually + OperationResult.OperationLog log = new OperationResult.OperationLog(); + log.add(OperationResult.LogType.MSG_DEL_ERROR_MULTI_SECRET, 0); + returnResult(new DeleteResult(OperationResult.RESULT_ERROR, log, 0, + mMasterKeyIds.length)); } - if (mMasterKeyIds.length == 1 && hasSecret) { + if (mMasterKeyIds.length == 1 && mHasSecret) { // if mMasterKeyIds.length == 0 we let the DeleteOperation respond try { HashMap data = new ProviderHelper(this).getUnifiedData( @@ -122,7 +127,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { private void showNormalDeleteDialog() { DeleteKeyDialogFragment deleteKeyDialogFragment - = DeleteKeyDialogFragment.newInstance(mMasterKeyIds); + = DeleteKeyDialogFragment.newInstance(mMasterKeyIds, mHasSecret); deleteKeyDialogFragment.show(getSupportFragmentManager(), "deleteKeyDialog"); @@ -179,7 +184,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { return new CryptoOperationHelper.Callback() { @Override public DeleteKeyringParcel createOperationInput() { - return new DeleteKeyringParcel(mMasterKeyIds, true); + return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret); } @Override @@ -221,6 +226,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { public static class DeleteKeyDialogFragment extends DialogFragment { private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids"; + private static final String ARG_HAS_SECRET = "has_secret"; private TextView mMainMessage; private View mInflateView; @@ -228,11 +234,12 @@ public class DeleteKeyDialogActivity extends FragmentActivity { /** * Creates new instance of this delete file dialog fragment */ - public static DeleteKeyDialogFragment newInstance(long[] masterKeyIds) { + public static DeleteKeyDialogFragment newInstance(long[] masterKeyIds, boolean hasSecret) { DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); Bundle args = new Bundle(); args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds); + args.putBoolean(ARG_HAS_SECRET, hasSecret); frag.setArguments(args); @@ -245,6 +252,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity { final FragmentActivity activity = getActivity(); final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS); + final boolean hasSecret = getArguments().getBoolean(ARG_HAS_SECRET); ContextThemeWrapper theme = new ContextThemeWrapper(activity, R.style.Theme_AppCompat_Light_Dialog); @@ -258,8 +266,6 @@ public class DeleteKeyDialogActivity extends FragmentActivity { mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage); - final boolean hasSecret; - // If only a single key has been selected if (masterKeyIds.length == 1) { long masterKeyId = masterKeyIds[0]; @@ -281,7 +287,6 @@ public class DeleteKeyDialogActivity extends FragmentActivity { } else { name = getString(R.string.user_id_no_name); } - hasSecret = ((Long) data.get(KeychainContract.KeyRings.HAS_ANY_SECRET)) == 1; if (hasSecret) { // show title only for secret key deletions, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index a42dfef23..95e047b0f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -352,13 +352,6 @@ public class KeyListFragment extends LoaderFragment * @param hasSecret must contain whether the list of masterKeyIds contains a secret key or not */ public void showDeleteKeyDialog(long[] masterKeyIds, boolean hasSecret) { - // Can only work on singular secret keys - if (hasSecret && masterKeyIds.length > 1) { - Notify.create(getActivity(), R.string.secret_cannot_multiple, - Notify.Style.ERROR).show(); - return; - } - Intent intent = new Intent(getActivity(), DeleteKeyDialogActivity.class); intent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, masterKeyIds); intent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, hasSecret); -- cgit v1.2.3