aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-07-15 21:14:53 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-07-15 21:14:53 +0200
commite4b113701cfd12b89a18365491b50f6508184bc2 (patch)
tree19672479027e592e23cba851f07a9fe79e3a33f7 /OpenKeychain/src/main/java/org
parent4cef97be5f4cd75fac252c8d3c739990604000df (diff)
parent1dafd1b629102180d7e6cb7bb31d1959f1ff6665 (diff)
downloadopen-keychain-e4b113701cfd12b89a18365491b50f6508184bc2.tar.gz
open-keychain-e4b113701cfd12b89a18365491b50f6508184bc2.tar.bz2
open-keychain-e4b113701cfd12b89a18365491b50f6508184bc2.zip
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'OpenKeychain/src/main/java/org')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java54
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ExportOperation.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/KeybaseVerificationOperation.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java145
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java23
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ExportResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/GetKeyResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/InputPendingResult.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/KeybaseVerificationResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpEditKeyResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java123
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java32
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainService.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java66
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java35
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/CryptoInputParcel.java54
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java430
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java89
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java60
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/RetryUploadDialogActivity.java88
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java47
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/CryptoOperationHelper.java66
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java211
47 files changed, 1358 insertions, 429 deletions
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<CertifyActionsParcel> {
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<CertifyActionsParcel> {
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<CertifyActionsParcel> {
// 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/DeleteOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java
index ac4a0da11..56bd3b786 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/DeleteOperation.java
@@ -22,6 +22,7 @@ import android.support.annotation.NonNull;
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
+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;
@@ -48,12 +49,17 @@ public class DeleteOperation extends BaseOperation<DeleteKeyringParcel> {
@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 +119,6 @@ public class DeleteOperation extends BaseOperation<DeleteKeyringParcel> {
}
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..f5ba88502 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
@@ -22,7 +22,8 @@ import android.support.annotation.NonNull;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.EditKeyResult;
-import org.sufficientlysecure.keychain.operations.results.OperationResult;
+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.operations.results.PgpEditKeyResult;
@@ -34,16 +35,20 @@ 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;
+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;
-/** An operation which implements a high level key edit operation.
- *
+/**
+ * An operation which implements a high level key edit operation.
+ * <p/>
* 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.
@@ -58,8 +63,16 @@ public class EditKeyOperation extends BaseOperation<SaveKeyringParcel> {
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 +133,36 @@ public class EditKeyOperation extends BaseOperation<SaveKeyringParcel> {
// It's a success, so this must be non-null now
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(),
+ publicKeyRing);
+
+ 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(log, RequiredInputParcel.createRetryUploadOperation(),
+ cryptoInput);
+ } 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));
@@ -131,7 +174,7 @@ public class EditKeyOperation extends BaseOperation<SaveKeyringParcel> {
}
// 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
@@ -160,5 +203,4 @@ public class EditKeyOperation extends BaseOperation<SaveKeyringParcel> {
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..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;
@@ -89,6 +88,8 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> {
}
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();
@@ -117,6 +118,7 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> {
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();
@@ -341,7 +343,7 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> {
// explicit proxy not set
if (!OrbotHelper.isOrbotInRequiredState(mContext)) {
return new ExportResult(null,
- RequiredInputParcel.createOrbotRequiredOperation());
+ RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput);
}
proxy = Preferences.getPreferences(mContext).getProxyPrefs()
.parcelableProxy.getProxy();
@@ -351,10 +353,15 @@ public class ExportOperation extends BaseOperation<ExportKeyringParcel> {
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/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<ImportKeyringParcel> {
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<KeybaseVerificat
// explicit proxy not set
if (!OrbotHelper.isOrbotInRequiredState(mContext)) {
return new KeybaseVerificationResult(null,
- RequiredInputParcel.createOrbotRequiredOperation());
+ RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput);
}
proxy = Preferences.getPreferences(mContext).getProxyPrefs()
.parcelableProxy.getProxy();
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..ecf64e1af
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/RevokeOperation.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.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.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<RevokeKeyringParcel> {
+
+ public RevokeOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
+ super(context, providerHelper, progressable);
+ }
+
+ @NonNull
+ @Override
+ 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();
+ 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/SignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java
index f7f968d16..843a55389 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/SignEncryptOperation.java
@@ -155,7 +155,7 @@ public class SignEncryptOperation extends BaseOperation<SignEncryptParcel> {
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<SignEncryptParcel> {
} 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..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 {
@@ -45,8 +44,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 52ff8bf44..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
@@ -21,8 +21,11 @@ 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.CryptoInputParcel;
+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 +33,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 +43,19 @@ 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,
+ CryptoInputParcel cryptoInputParcel) {
+ super(log, requiredInput, cryptoInputParcel);
+ // 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);
@@ -109,7 +125,10 @@ public class DeleteResult extends OperationResult {
} 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/EditKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/EditKeyResult.java
index 842b75c3b..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,7 +20,10 @@ package org.sufficientlysecure.keychain.operations.results;
import android.os.Parcel;
-public class EditKeyResult extends OperationResult {
+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 OperationResult {
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/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 0b7aa6d03..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,10 +18,9 @@
package org.sufficientlysecure.keychain.operations.results;
-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 +29,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
+ public 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/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/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java
index 88d04350c..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
@@ -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),
@@ -752,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),
@@ -760,6 +762,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.ERROR, 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/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
new file mode 100644
index 000000000..b737f6e50
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/RevokeResult.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.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.CryptoInputParcel;
+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
+ */
+ @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);
+ // 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<RevokeResult> CREATOR = new Parcelable.Creator<RevokeResult>() {
+ @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/operations/results/SignEncryptResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/SignEncryptResult.java
index b05921b0d..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,18 +19,20 @@ 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 {
ArrayList<PgpSignEncryptResult> mResults;
byte[] mResultBytes;
- public SignEncryptResult(OperationLog log, RequiredInputParcel requiredInput, ArrayList<PgpSignEncryptResult> results) {
- super(log, requiredInput);
+ public SignEncryptResult(OperationLog log, RequiredInputParcel requiredInput,
+ ArrayList<PgpSignEncryptResult> 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<PgpDecryptVerifyInputParcel>
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<PgpDecryptVerifyInputParcel>
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<PgpDecryptVerifyInputParcel>
} 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<PgpDecryptVerifyInputParcel>
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..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;
@@ -469,7 +470,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 +1106,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);
@@ -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/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
index 0448e1425..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;
@@ -200,7 +199,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 +512,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/pgp/UncachedKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
index 7be61d9c8..a7baddf8b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
@@ -48,6 +48,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 +79,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/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/ExportKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ExportKeyringParcel.java
index ef5b48df3..24c002bbd 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;
@@ -52,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;
@@ -62,6 +72,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 +89,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..02e8fda46
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/RevokeKeyringParcel.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.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<RevokeKeyringParcel> CREATOR = new Parcelable.Creator<RevokeKeyringParcel>() {
+ @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..6959fca56 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() {
@@ -216,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();
@@ -234,6 +261,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 +290,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<SaveKeyringParcel> CREATOR = new Creator<SaveKeyringParcel>() {
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..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,49 +33,71 @@ import java.util.Map;
*/
public class CryptoInputParcel implements Parcelable {
- final Date mSignatureTime;
- final Passphrase mPassphrase;
+ 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
+ // (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<ByteBuffer, byte[]> mCryptoData = new HashMap<>();
public CryptoInputParcel() {
- mSignatureTime = new Date();
+ mSignatureTime = null;
mPassphrase = null;
- mParcelableProxy = null;
+ mCachePassphrase = true;
}
public CryptoInputParcel(Date signatureTime, Passphrase passphrase) {
+ mHasSignature = true;
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
mPassphrase = passphrase;
- mParcelableProxy = null;
+ mCachePassphrase = true;
}
public CryptoInputParcel(Passphrase passphrase) {
- mSignatureTime = new Date();
mPassphrase = passphrase;
- mParcelableProxy = null;
+ mCachePassphrase = true;
}
public CryptoInputParcel(Date signatureTime) {
+ mHasSignature = true;
mSignatureTime = signatureTime == null ? new Date() : signatureTime;
mPassphrase = null;
- mParcelableProxy = null;
+ mCachePassphrase = true;
}
public CryptoInputParcel(ParcelableProxy parcelableProxy) {
- mSignatureTime = new Date(); // just for compatibility with parcel-ing
- mPassphrase = null;
+ this();
mParcelableProxy = parcelableProxy;
}
+ 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;
{
int count = source.readInt();
@@ -96,9 +118,13 @@ 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));
dest.writeInt(mCryptoData.size());
for (HashMap.Entry<ByteBuffer, byte[]> entry : mCryptoData.entrySet()) {
@@ -111,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/service/input/RequiredInputParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/input/RequiredInputParcel.java
index e378296a5..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;
@@ -15,7 +14,8 @@ 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,
+ UPLOAD_FAIL_RETRY
}
public Date mSignatureTime;
@@ -77,6 +77,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/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<CertifyActionsParcel, CertifyResult>
@@ -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
new file mode 100644
index 000000000..4c1dbd1ee
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DeleteKeyDialogActivity.java
@@ -0,0 +1,430 @@
+/*
+ * Copyright (C) 2013-2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.support.v7.app.AlertDialog;
+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 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.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;
+import java.util.HashMap;
+
+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<DeleteKeyringParcel, DeleteResult> mDeleteOpHelper;
+ private CryptoOperationHelper<RevokeKeyringParcel, RevokeResult> mRevokeOpHelper;
+
+ private long[] mMasterKeyIds;
+ private boolean mHasSecret;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(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);
+
+ 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 && mHasSecret) {
+ // if mMasterKeyIds.length == 0 we let the DeleteOperation respond
+ try {
+ HashMap<String, Object> 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
+ }
+ );
+
+ 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(name);
+ }
+ } catch (ProviderHelper.NotFoundException e) {
+ Log.e(Constants.TAG,
+ "Secret key to delete not found at DeleteKeyDialogActivity for "
+ + mMasterKeyIds[0], e);
+ finish();
+ }
+ } else {
+ showNormalDeleteDialog();
+ }
+ }
+
+ private void showNormalDeleteDialog() {
+
+ DeleteKeyDialogFragment deleteKeyDialogFragment
+ = DeleteKeyDialogFragment.newInstance(mMasterKeyIds, mHasSecret);
+
+ deleteKeyDialogFragment.show(getSupportFragmentManager(), "deleteKeyDialog");
+
+ }
+
+ private void showRevokeDeleteDialog(String keyname) {
+
+ RevokeDeleteDialogFragment fragment = RevokeDeleteDialogFragment.newInstance(keyname);
+ fragment.show(getSupportFragmentManager(), "deleteRevokeDialog");
+ }
+
+ private void startRevocationOperation() {
+ mRevokeOpHelper.cryptoOperation(new CryptoInputParcel(new Date(), false));
+ }
+
+ private void startDeletionOperation() {
+ mDeleteOpHelper.cryptoOperation();
+ }
+
+ private CryptoOperationHelper.Callback<RevokeKeyringParcel, RevokeResult> getRevocationCallback() {
+
+ return new CryptoOperationHelper.Callback<RevokeKeyringParcel, RevokeResult>() {
+ @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;
+ }
+ };
+ }
+
+ private CryptoOperationHelper.Callback<DeleteKeyringParcel, DeleteResult> getDeletionCallback() {
+
+ return new CryptoOperationHelper.Callback<DeleteKeyringParcel, DeleteResult>() {
+ @Override
+ public DeleteKeyringParcel createOperationInput() {
+ return new DeleteKeyringParcel(mMasterKeyIds, mHasSecret);
+ }
+
+ @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;
+ }
+ };
+ }
+
+ private void returnResult(OperationResult result) {
+ Intent intent = new Intent();
+ intent.putExtra(OperationResult.EXTRA_RESULT, result);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mDeleteOpHelper.handleActivityResult(requestCode, resultCode, data);
+ mRevokeOpHelper.handleActivityResult(requestCode, resultCode, data);
+ }
+
+ 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;
+
+ /**
+ * Creates new instance of this delete file dialog fragment
+ */
+ 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);
+
+ return frag;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ 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);
+
+ CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(theme);
+
+ // Setup custom View to display in AlertDialog
+ LayoutInflater inflater = LayoutInflater.from(theme);
+ mInflateView = inflater.inflate(R.layout.view_key_delete_fragment, null);
+ builder.setView(mInflateView);
+
+ mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage);
+
+ // If only a single key has been selected
+ if (masterKeyIds.length == 1) {
+ long masterKeyId = masterKeyIds[0];
+
+ try {
+ HashMap<String, Object> 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);
+ }
+
+ 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);
+ }
+
+ builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+
+ ((DeleteKeyDialogActivity) getActivity()).startDeletionOperation();
+ }
+ });
+
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ 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 {
+
+ 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
+ @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 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);
+ builder.setView(view);
+
+ final Spinner spinner = (Spinner) view.findViewById(R.id.spinner);
+
+ builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
+
+ builder.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)
+ .showNormalDeleteDialog();
+ } else {
+ throw new AssertionError(
+ "Unsupported delete type in RevokeDeleteDialogFragment");
+ }
+ }
+ });
+
+ final AlertDialog alertDialog = builder.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;
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ getActivity().setResult(RESULT_CANCELED);
+ getActivity().finish();
+ }
+ }
+
+}
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<SaveKeyringParcel, OperationResult>
implements LoaderManager.LoaderCallbacks<Cursor> {
@@ -151,7 +153,7 @@ public class EditKeyFragment extends QueueingCryptoOperationFragment<SaveKeyring
if (mDataUri == null) {
returnKeyringParcel();
} else {
- cryptoOperation(new CryptoInputParcel());
+ cryptoOperation(new CryptoInputParcel(new Date()));
}
}
}, new OnClickListener() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
index 84315860c..3dc93872d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.ui;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -57,6 +58,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration;
import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
@@ -279,19 +281,19 @@ public class EncryptFilesFragment
case R.id.encrypt_save: {
hideKeyboard();
mAfterEncryptAction = AfterEncryptAction.SAVE;
- cryptoOperation();
+ cryptoOperation(new CryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_share: {
hideKeyboard();
mAfterEncryptAction = AfterEncryptAction.SHARE;
- cryptoOperation();
+ cryptoOperation(new CryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_copy: {
hideKeyboard();
mAfterEncryptAction = AfterEncryptAction.COPY;
- cryptoOperation();
+ cryptoOperation(new CryptoInputParcel(new Date()));
break;
}
case R.id.check_use_armor: {
@@ -666,7 +668,7 @@ public class EncryptFilesFragment
mOutputUris.add(data.getData());
// make sure this is correct at this point
mAfterEncryptAction = AfterEncryptAction.SAVE;
- cryptoOperation();
+ cryptoOperation(new CryptoInputParcel(new Date()));
}
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
index 7f49b14f8..32257eba5 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java
@@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.base.CachingCryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener;
@@ -48,6 +49,7 @@ import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.ShareHelper;
+import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@@ -168,13 +170,13 @@ public class EncryptTextFragment
case R.id.encrypt_copy: {
hideKeyboard();
mShareAfterEncrypt = false;
- cryptoOperation();
+ cryptoOperation(new CryptoInputParcel(new Date()));
break;
}
case R.id.encrypt_share: {
hideKeyboard();
mShareAfterEncrypt = true;
- cryptoOperation();
+ cryptoOperation(new CryptoInputParcel(new Date()));
break;
}
default: {
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 ee1c8460c..95e047b0f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -33,9 +33,6 @@ import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
@@ -60,7 +57,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
-import org.sufficientlysecure.keychain.operations.results.DeleteResult;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.provider.KeychainContract;
@@ -71,7 +67,6 @@ import org.sufficientlysecure.keychain.service.ConsolidateInputParcel;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
-import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
@@ -91,6 +86,8 @@ public class KeyListFragment extends LoaderFragment
CryptoOperationHelper.Callback<ImportKeyringParcel, ImportKeyResult> {
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;
@@ -220,7 +217,7 @@ public class KeyListFragment extends LoaderFragment
}
case R.id.menu_key_list_multi_delete: {
ids = mAdapter.getCurrentSelectedMasterKeyIds();
- showDeleteKeyDialog(mode, ids, mAdapter.isAnySecretSelected());
+ showDeleteKeyDialog(ids, mAdapter.isAnySecretSelected());
break;
}
}
@@ -336,7 +333,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) {
@@ -354,38 +351,15 @@ public class KeyListFragment extends LoaderFragment
*
* @param hasSecret must contain whether the list of masterKeyIds contains a secret key or not
*/
- public void showDeleteKeyDialog(final ActionMode mode, 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;
+ public void showDeleteKeyDialog(long[] masterKeyIds, boolean hasSecret) {
+ 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());
}
-
- // 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");
+ startActivityForResult(intent, REQUEST_DELETE);
}
@@ -620,14 +594,37 @@ 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:
+ if (mActionMode != null) {
+ 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/NfcOperationActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
index 8802cd621..1584b87ae 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/NfcOperationActivity.java
@@ -33,21 +33,25 @@ import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import java.util.Date;
/**
* This class provides a communication interface to OpenPGP applications on ISO SmartCard compliant
* NFC devices.
* <p/>
* 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 {
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 +71,15 @@ 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)
+ // NOTE: This CryptoInputParcel cannot be used for signing without adding signature time
+ mInputParcel = new CryptoInputParcel();
+ }
+
setTitle(R.string.nfc_text);
vAnimator = (ViewAnimator) findViewById(R.id.view_animator);
@@ -112,8 +125,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++) {
@@ -124,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];
@@ -218,11 +232,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 004d1d127..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,17 +66,22 @@ 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";
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 +95,15 @@ public class PassphraseDialogActivity extends FragmentActivity {
);
}
+ mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
+
+ 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();
+ }
+
// this activity itself has no content view (see manifest)
if (getIntent().hasExtra(EXTRA_SUBKEY_ID)) {
@@ -113,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;
@@ -330,11 +345,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 +407,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 +440,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/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 <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
+ * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+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/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
index 9ed46d517..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,10 +65,8 @@ 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.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 +83,6 @@ import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
import java.util.ArrayList;
-
public class ViewKeyActivity extends BaseNfcActivity implements
LoaderManager.LoaderCallbacks<Cursor>,
CryptoOperationHelper.Callback<ImportKeyringParcel, ImportKeyResult> {
@@ -97,6 +94,7 @@ 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;
public static final String EXTRA_DISPLAY_RESULT = "display_result";
@@ -419,27 +417,18 @@ 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");
- }
- });
+ 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(deleteIntent, REQUEST_DELETE);
}
@Override
@@ -487,6 +476,12 @@ public class ViewKeyActivity extends BaseNfcActivity implements
}
return;
}
+
+ 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/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
index adf46caf8..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
@@ -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;
@@ -48,12 +49,13 @@ public class ImportKeysListCloudLoader
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> 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) {
@@ -121,7 +123,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 91ea969d7..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
@@ -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.RetryUploadDialogActivity;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
@@ -76,6 +77,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
public static final int REQUEST_CODE_PASSPHRASE = 1;
public static final int REQUEST_CODE_NFC = 2;
public static final int REQUEST_CODE_ENABLE_ORBOT = 3;
+ public static final int REQUEST_CODE_RETRY_UPLOAD = 4;
private Integer mProgressMessageResource;
@@ -118,18 +120,14 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
Activity activity = mUseFragment ? mFragment.getActivity() : mActivity;
switch (requiredInput.mType) {
- // TODO: Verify that all started activities add to cryptoInputParcel if necessary (like OrbotRequiredDialogActivity)
- // don't forget to set mRequestedCode!
+ // always use CryptoOperationHelper.startActivityForResult!
case NFC_MOVE_KEY_TO_CARD:
case NFC_DECRYPT:
case NFC_SIGN: {
Intent intent = new Intent(activity, NfcOperationActivity.class);
intent.putExtra(NfcOperationActivity.EXTRA_REQUIRED_INPUT, requiredInput);
- if (mUseFragment) {
- mFragment.startActivityForResult(intent, mId + REQUEST_CODE_NFC);
- } else {
- activity.startActivityForResult(intent, mId + REQUEST_CODE_NFC);
- }
+ intent.putExtra(NfcOperationActivity.EXTRA_CRYPTO_INPUT, cryptoInputParcel);
+ startActivityForResult(intent, REQUEST_CODE_NFC);
return;
}
@@ -137,22 +135,22 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
case PASSPHRASE_SYMMETRIC: {
Intent intent = new Intent(activity, PassphraseDialogActivity.class);
intent.putExtra(PassphraseDialogActivity.EXTRA_REQUIRED_INPUT, requiredInput);
- if (mUseFragment) {
- mFragment.startActivityForResult(intent, mId + REQUEST_CODE_PASSPHRASE);
- } else {
- activity.startActivityForResult(intent, mId + REQUEST_CODE_PASSPHRASE);
- }
+ intent.putExtra(PassphraseDialogActivity.EXTRA_CRYPTO_INPUT, cryptoInputParcel);
+ startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
return;
}
case ENABLE_ORBOT: {
Intent intent = new Intent(activity, OrbotRequiredDialogActivity.class);
intent.putExtra(OrbotRequiredDialogActivity.EXTRA_CRYPTO_INPUT, cryptoInputParcel);
- if (mUseFragment) {
- mFragment.startActivityForResult(intent, mId + REQUEST_CODE_ENABLE_ORBOT);
- } else {
- activity.startActivityForResult(intent, mId + REQUEST_CODE_ENABLE_ORBOT);
- }
+ startActivityForResult(intent, REQUEST_CODE_ENABLE_ORBOT);
+ return;
+ }
+
+ case UPLOAD_FAIL_RETRY: {
+ Intent intent = new Intent(activity, RetryUploadDialogActivity.class);
+ intent.putExtra(RetryUploadDialogActivity.EXTRA_CRYPTO_INPUT, cryptoInputParcel);
+ startActivityForResult(intent, REQUEST_CODE_RETRY_UPLOAD);
return;
}
@@ -162,6 +160,14 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
}
}
+ protected void startActivityForResult(Intent intent, int requestCode) {
+ if (mUseFragment) {
+ mFragment.startActivityForResult(intent, mId + requestCode);
+ } else {
+ mActivity.startActivityForResult(intent, mId + requestCode);
+ }
+ }
+
/**
* Attempts the result of an activity started by this helper. Returns true if requestCode is
* recognized, false otherwise.
@@ -174,6 +180,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
// this wasn't meant for us to handle
return false;
}
+ Log.d(Constants.TAG, "handling activity result in OperationHelper");
// filter out mId from requestCode
requestCode ^= mId;
@@ -188,7 +195,6 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
CryptoInputParcel cryptoInput =
data.getParcelableExtra(PassphraseDialogActivity.RESULT_CRYPTO_INPUT);
cryptoOperation(cryptoInput);
- return true;
}
break;
}
@@ -196,9 +202,8 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
case REQUEST_CODE_NFC: {
if (resultCode == Activity.RESULT_OK && data != null) {
CryptoInputParcel cryptoInput =
- data.getParcelableExtra(NfcOperationActivity.RESULT_DATA);
+ data.getParcelableExtra(NfcOperationActivity.RESULT_CRYPTO_INPUT);
cryptoOperation(cryptoInput);
- return true;
}
break;
}
@@ -209,12 +214,22 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
data.getParcelableExtra(
OrbotRequiredDialogActivity.RESULT_CRYPTO_INPUT);
cryptoOperation(cryptoInput);
- return true;
}
+ break;
+ }
+
+ case REQUEST_CODE_RETRY_UPLOAD: {
+ if (resultCode == Activity.RESULT_OK) {
+ CryptoInputParcel cryptoInput =
+ data.getParcelableExtra(
+ RetryUploadDialogActivity.RESULT_CRYPTO_INPUT);
+ cryptoOperation(cryptoInput);
+ }
+ break;
}
}
- return false;
+ return true;
}
protected void dismissProgress() {
@@ -271,7 +286,7 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
final OperationResult result =
returnData.getParcelable(OperationResult.EXTRA_RESULT);
- onHandleResult(result, cryptoInput);
+ onHandleResult(result);
}
}
@@ -301,15 +316,14 @@ public class CryptoOperationHelper<T extends Parcelable, S extends OperationResu
cryptoOperation(new CryptoInputParcel());
}
- public void onHandleResult(OperationResult result, CryptoInputParcel oldCryptoInput) {
+ public void onHandleResult(OperationResult result) {
Log.d(Constants.TAG, "Handling result in OperationHelper success: " + result.success());
if (result instanceof InputPendingResult) {
InputPendingResult pendingResult = (InputPendingResult) result;
if (pendingResult.isPending()) {
-
RequiredInputParcel requiredInput = pendingResult.getRequiredInputParcel();
- initiateInputActivity(requiredInput, oldCryptoInput);
+ initiateInputActivity(requiredInput, pendingResult.mCryptoInputParcel);
return;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
deleted file mode 100644
index e92f9f78d..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui.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<DeleteKeyringParcel, DeleteResult> {
- 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<DeleteKeyringParcel, DeleteResult> 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<String, Object> 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();
- }
-}