aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service
diff options
context:
space:
mode:
authormar-v-in <github@rvin.mooo.com>2014-06-18 21:43:54 +0200
committermar-v-in <github@rvin.mooo.com>2014-06-18 21:43:54 +0200
commitd9c937bbe762736d9f0c45d5ba0083555c8da2e1 (patch)
treee5cbd2300622e555283867f39767bf34b9dd5796 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service
parente106079b90f7d596a254b223b6e8741fc6d94785 (diff)
parent825f37eee4be6a4dc527391e6238668e6d147a36 (diff)
downloadopen-keychain-d9c937bbe762736d9f0c45d5ba0083555c8da2e1.tar.gz
open-keychain-d9c937bbe762736d9f0c45d5ba0083555c8da2e1.tar.bz2
open-keychain-d9c937bbe762736d9f0c45d5ba0083555c8da2e1.zip
Merge branch 'master' into improve-file
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java170
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java128
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java318
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java92
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java8
6 files changed, 464 insertions, 274 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
index 8db9294df..6c4d59a77 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/ContactSyncAdapterService.java
@@ -30,10 +30,14 @@ import org.sufficientlysecure.keychain.helper.ContactHelper;
import org.sufficientlysecure.keychain.helper.EmailKeyHelper;
import org.sufficientlysecure.keychain.util.Log;
+import java.util.concurrent.atomic.AtomicBoolean;
+
public class ContactSyncAdapterService extends Service {
private class ContactSyncAdapter extends AbstractThreadedSyncAdapter {
+ private final AtomicBoolean importDone = new AtomicBoolean(false);
+
public ContactSyncAdapter() {
super(ContactSyncAdapterService.this, true);
}
@@ -41,6 +45,8 @@ public class ContactSyncAdapterService extends Service {
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
final SyncResult syncResult) {
+ importDone.set(false);
+ KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(),
new Handler.Callback() {
@Override
@@ -48,11 +54,16 @@ public class ContactSyncAdapterService extends Service {
Bundle data = msg.getData();
switch (msg.arg1) {
case KeychainIntentServiceHandler.MESSAGE_OKAY:
+ Log.d(Constants.TAG, "Syncing... Done.");
+ synchronized (importDone) {
+ importDone.set(true);
+ importDone.notifyAll();
+ }
return true;
case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS:
if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) &&
data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) {
- Log.d(Constants.TAG, "Progress: " +
+ Log.d(Constants.TAG, "Syncing... Progress: " +
data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" +
data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX));
return false;
@@ -63,7 +74,14 @@ public class ContactSyncAdapterService extends Service {
}
}
})));
- KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
+ synchronized (importDone) {
+ try {
+ if (!importDone.get()) importDone.wait();
+ } catch (InterruptedException e) {
+ Log.w(Constants.TAG, e);
+ return;
+ }
+ }
ContactHelper.writeKeysToContacts(ContactSyncAdapterService.this);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
index 776419b4a..e1514b16f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -44,7 +44,6 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
-import org.sufficientlysecure.keychain.pgp.UncachedSecretKey;
import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.WrappedSecretKey;
import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing;
@@ -53,6 +52,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ProgressScaler;
@@ -87,9 +87,6 @@ public class KeychainIntentService extends IntentService
public static final String ACTION_DECRYPT_VERIFY = Constants.INTENT_PREFIX + "DECRYPT_VERIFY";
public static final String ACTION_SAVE_KEYRING = Constants.INTENT_PREFIX + "SAVE_KEYRING";
- public static final String ACTION_GENERATE_KEY = Constants.INTENT_PREFIX + "GENERATE_KEY";
- public static final String ACTION_GENERATE_DEFAULT_RSA_KEYS = Constants.INTENT_PREFIX
- + "GENERATE_DEFAULT_RSA_KEYS";
public static final String ACTION_DELETE_FILE_SECURELY = Constants.INTENT_PREFIX
+ "DELETE_FILE_SECURELY";
@@ -131,14 +128,7 @@ public class KeychainIntentService extends IntentService
// save keyring
public static final String SAVE_KEYRING_PARCEL = "save_parcel";
- public static final String SAVE_KEYRING_CAN_SIGN = "can_sign";
-
-
- // generate key
- public static final String GENERATE_KEY_ALGORITHM = "algorithm";
- public static final String GENERATE_KEY_KEY_SIZE = "key_size";
- public static final String GENERATE_KEY_SYMMETRIC_PASSPHRASE = "passphrase";
- public static final String GENERATE_KEY_MASTER_KEY = "master_key";
+ public static final String SAVE_KEYRING_PASSPHRASE = "passphrase";
// delete file securely
public static final String DELETE_FILE = "deleteFile";
@@ -168,9 +158,6 @@ public class KeychainIntentService extends IntentService
/*
* possible data keys as result send over messenger
*/
- // keys
- public static final String RESULT_NEW_KEY = "new_key";
- public static final String RESULT_KEY_USAGES = "new_key_usages";
// encrypt
public static final String RESULT_BYTES = "encrypted_data";
@@ -179,14 +166,11 @@ public class KeychainIntentService extends IntentService
public static final String RESULT_DECRYPTED_BYTES = "decrypted_data";
public static final String RESULT_DECRYPT_VERIFY_RESULT = "signature";
- // import
- public static final String RESULT_IMPORT_ADDED = "added";
- public static final String RESULT_IMPORT_UPDATED = "updated";
- public static final String RESULT_IMPORT_BAD = "bad";
-
// export
public static final String RESULT_EXPORT = "exported";
+ public static final String RESULT = "result";
+
Messenger mMessenger;
private boolean mIsCanceled;
@@ -335,133 +319,36 @@ public class KeychainIntentService extends IntentService
} else if (ACTION_SAVE_KEYRING.equals(action)) {
try {
/* Input */
- OldSaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL);
- String oldPassphrase = saveParcel.oldPassphrase;
- String newPassphrase = saveParcel.newPassphrase;
- boolean canSign = true;
-
- if (data.containsKey(SAVE_KEYRING_CAN_SIGN)) {
- canSign = data.getBoolean(SAVE_KEYRING_CAN_SIGN);
- }
-
- if (newPassphrase == null) {
- newPassphrase = oldPassphrase;
- }
-
- long masterKeyId = saveParcel.keys.get(0).getKeyId();
+ SaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL);
+ long masterKeyId = saveParcel.mMasterKeyId;
/* Operation */
ProviderHelper providerHelper = new ProviderHelper(this);
- if (!canSign) {
- setProgress(R.string.progress_building_key, 0, 100);
- WrappedSecretKeyRing keyRing = providerHelper.getWrappedSecretKeyRing(masterKeyId);
- UncachedKeyRing newKeyRing =
- keyRing.changeSecretKeyPassphrase(oldPassphrase, newPassphrase);
- setProgress(R.string.progress_saving_key_ring, 50, 100);
- providerHelper.saveSecretKeyRing(newKeyRing);
- setProgress(R.string.progress_done, 100, 100);
- } else {
- PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100));
- try {
- WrappedSecretKeyRing seckey = providerHelper.getWrappedSecretKeyRing(masterKeyId);
- WrappedPublicKeyRing pubkey = providerHelper.getWrappedPublicKeyRing(masterKeyId);
-
- PgpKeyOperation.Pair<UncachedKeyRing,UncachedKeyRing> pair =
- keyOperations.buildSecretKey(seckey, pubkey, saveParcel); // edit existing
- setProgress(R.string.progress_saving_key_ring, 90, 100);
- providerHelper.saveKeyRing(pair.first, pair.second);
- } catch (ProviderHelper.NotFoundException e) {
- PgpKeyOperation.Pair<UncachedKeyRing,UncachedKeyRing> pair =
- keyOperations.buildNewSecretKey(saveParcel); //new Keyring
- // save the pair
- setProgress(R.string.progress_saving_key_ring, 90, 100);
- providerHelper.saveKeyRing(pair.first, pair.second);
- }
-
- setProgress(R.string.progress_done, 100, 100);
+ PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 10, 50, 100));
+ try {
+ String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE);
+ WrappedSecretKeyRing secRing = providerHelper.getWrappedSecretKeyRing(masterKeyId);
+
+ OperationLog log = new OperationLog();
+ UncachedKeyRing ring = keyOperations.modifySecretKeyRing(secRing, saveParcel,
+ passphrase, log, 0);
+ providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100));
+ } catch (ProviderHelper.NotFoundException e) {
+ // UncachedKeyRing ring = keyOperations.(saveParcel); //new Keyring
+ // save the pair
+ setProgress(R.string.progress_saving_key_ring, 95, 100);
+ // providerHelper.saveSecretKeyRing(ring);
+ sendErrorToHandler(e);
}
- PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase);
- /* Output */
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_GENERATE_KEY.equals(action)) {
- try {
- /* Input */
- int algorithm = data.getInt(GENERATE_KEY_ALGORITHM);
- String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
- int keysize = data.getInt(GENERATE_KEY_KEY_SIZE);
- boolean masterKey = data.getBoolean(GENERATE_KEY_MASTER_KEY);
+ setProgress(R.string.progress_done, 100, 100);
- /* Operation */
- PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100));
- byte[] newKey = keyOperations.createKey(algorithm, keysize, passphrase, masterKey);
-
- /* Output */
- Bundle resultData = new Bundle();
- resultData.putByteArray(RESULT_NEW_KEY, newKey);
-
- OtherHelper.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
- } catch (Exception e) {
- sendErrorToHandler(e);
- }
- } else if (ACTION_GENERATE_DEFAULT_RSA_KEYS.equals(action)) {
- // generate one RSA 4096 key for signing and one subkey for encrypting!
- try {
- /* Input */
- String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
- ArrayList<Integer> keyUsageList = new ArrayList<Integer>();
-
- /* Operation */
- int keysTotal = 3;
- int keysCreated = 0;
- setProgress(
- getApplicationContext().getResources().
- getQuantityString(R.plurals.progress_generating, keysTotal),
- keysCreated,
- keysTotal);
- PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100));
-
- ByteArrayOutputStream os = new ByteArrayOutputStream();
-
- byte[] buf;
-
- buf = keyOperations.createKey(Constants.choice.algorithm.rsa,
- 4096, passphrase, true);
- os.write(buf);
- keyUsageList.add(UncachedSecretKey.CERTIFY_OTHER);
- keysCreated++;
- setProgress(keysCreated, keysTotal);
-
- buf = keyOperations.createKey(Constants.choice.algorithm.rsa,
- 4096, passphrase, false);
- os.write(buf);
- keyUsageList.add(UncachedSecretKey.ENCRYPT_COMMS | UncachedSecretKey.ENCRYPT_STORAGE);
- keysCreated++;
- setProgress(keysCreated, keysTotal);
-
- buf = keyOperations.createKey(Constants.choice.algorithm.rsa,
- 4096, passphrase, false);
- os.write(buf);
- keyUsageList.add(UncachedSecretKey.SIGN_DATA);
- keysCreated++;
- setProgress(keysCreated, keysTotal);
-
- // TODO: default to one master for cert, one sub for encrypt and one sub
- // for sign
+ if (saveParcel.newPassphrase != null) {
+ PassphraseCacheService.addCachedPassphrase(this, masterKeyId, saveParcel.newPassphrase);
+ }
/* Output */
- Bundle resultData = new Bundle();
- resultData.putByteArray(RESULT_NEW_KEY, os.toByteArray());
- resultData.putIntegerArrayList(RESULT_KEY_USAGES, keyUsageList);
-
- OtherHelper.logDebugBundle(resultData, "resultData");
-
- sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
+ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY);
} catch (Exception e) {
sendErrorToHandler(e);
}
@@ -491,7 +378,10 @@ public class KeychainIntentService extends IntentService
List<ParcelableKeyRing> entries = data.getParcelableArrayList(IMPORT_KEY_LIST);
PgpImportExport pgpImportExport = new PgpImportExport(this, this);
- Bundle resultData = pgpImportExport.importKeyRings(entries);
+ OperationResults.ImportResult result = pgpImportExport.importKeyRings(entries);
+
+ Bundle resultData = new Bundle();
+ resultData.putParcelable(RESULT, result);
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData);
} catch (Exception e) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java
deleted file mode 100644
index b722393ad..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OldSaveKeyringParcel.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2014 Ash Hughes <ashes-iontach@hotmail.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;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
-import org.sufficientlysecure.keychain.pgp.UncachedSecretKey;
-import org.sufficientlysecure.keychain.util.IterableIterator;
-import org.sufficientlysecure.keychain.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Calendar;
-
-/** Class for parcelling data between ui and services.
- * This class is outdated and scheduled for removal, pending a rewrite of the
- * EditKeyActivity and save keyring routines.
- */
-@Deprecated
-public class OldSaveKeyringParcel implements Parcelable {
-
- public ArrayList<String> userIds;
- public ArrayList<String> originalIDs;
- public ArrayList<String> deletedIDs;
- public boolean[] newIDs;
- public boolean primaryIDChanged;
- public boolean[] moddedKeys;
- public ArrayList<UncachedSecretKey> deletedKeys;
- public ArrayList<Calendar> keysExpiryDates;
- public ArrayList<Integer> keysUsages;
- public String newPassphrase;
- public String oldPassphrase;
- public boolean[] newKeys;
- public ArrayList<UncachedSecretKey> keys;
- public String originalPrimaryID;
-
- public OldSaveKeyringParcel() {}
-
- private OldSaveKeyringParcel(Parcel source) {
- userIds = (ArrayList<String>) source.readSerializable();
- originalIDs = (ArrayList<String>) source.readSerializable();
- deletedIDs = (ArrayList<String>) source.readSerializable();
- newIDs = source.createBooleanArray();
- primaryIDChanged = source.readByte() != 0;
- moddedKeys = source.createBooleanArray();
- byte[] tmp = source.createByteArray();
- if (tmp == null) {
- deletedKeys = null;
- } else {
- deletedKeys = PgpConversionHelper.BytesToPGPSecretKeyList(tmp);
- }
- keysExpiryDates = (ArrayList<Calendar>) source.readSerializable();
- keysUsages = source.readArrayList(Integer.class.getClassLoader());
- newPassphrase = source.readString();
- oldPassphrase = source.readString();
- newKeys = source.createBooleanArray();
- keys = PgpConversionHelper.BytesToPGPSecretKeyList(source.createByteArray());
- originalPrimaryID = source.readString();
- }
-
- @Override
- public void writeToParcel(Parcel destination, int flags) {
- destination.writeSerializable(userIds); //might not be the best method to store.
- destination.writeSerializable(originalIDs);
- destination.writeSerializable(deletedIDs);
- destination.writeBooleanArray(newIDs);
- destination.writeByte((byte) (primaryIDChanged ? 1 : 0));
- destination.writeBooleanArray(moddedKeys);
- destination.writeByteArray(encodeArrayList(deletedKeys));
- destination.writeSerializable(keysExpiryDates);
- destination.writeList(keysUsages);
- destination.writeString(newPassphrase);
- destination.writeString(oldPassphrase);
- destination.writeBooleanArray(newKeys);
- destination.writeByteArray(encodeArrayList(keys));
- destination.writeString(originalPrimaryID);
- }
-
- public static final Creator<OldSaveKeyringParcel> CREATOR = new Creator<OldSaveKeyringParcel>() {
- public OldSaveKeyringParcel createFromParcel(final Parcel source) {
- return new OldSaveKeyringParcel(source);
- }
-
- public OldSaveKeyringParcel[] newArray(final int size) {
- return new OldSaveKeyringParcel[size];
- }
- };
-
- private static byte[] encodeArrayList(ArrayList<UncachedSecretKey> list) {
- if(list.isEmpty()) {
- return null;
- }
-
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- for(UncachedSecretKey key : new IterableIterator<UncachedSecretKey>(list.iterator())) {
- try {
- key.encodeSecretKey(os);
- } catch (IOException e) {
- Log.e(Constants.TAG, "Error while converting ArrayList<UncachedSecretKey> to byte[]!", e);
- }
- }
- return os.toByteArray();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
new file mode 100644
index 000000000..6e49baf92
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java
@@ -0,0 +1,318 @@
+package org.sufficientlysecure.keychain.service;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.IterableIterator;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.util.ArrayList;
+
+/** Represent the result of an operation.
+ *
+ * This class holds a result and the log of an operation. It can be subclassed
+ * to include typed additional information specific to the operation. To keep
+ * the class structure (somewhat) simple, this class contains an exhaustive
+ * list (ie, enum) of all possible log types, which should in all cases be tied
+ * to string resource ids.
+ *
+ *
+ */
+public class OperationResultParcel implements Parcelable {
+ /** Holds the overall result, the number specifying varying degrees of success. The first bit
+ * is 0 on overall success, 1 on overall failure. All other bits may be used for more specific
+ * conditions. */
+ final int mResult;
+
+ public static final int RESULT_OK = 0;
+ public static final int RESULT_ERROR = 1;
+
+ /// A list of log entries tied to the operation result.
+ final OperationLog mLog;
+
+ public OperationResultParcel(int result, OperationLog log) {
+ mResult = result;
+ mLog = log;
+ }
+
+ public OperationResultParcel(Parcel source) {
+ mResult = source.readInt();
+ mLog = new OperationLog();
+ mLog.addAll(source.createTypedArrayList(LogEntryParcel.CREATOR));
+ }
+
+ public int getResult() {
+ return mResult;
+ }
+
+ public boolean success() {
+ return (mResult & 1) == 0;
+ }
+
+ public OperationLog getLog() {
+ return mLog;
+ }
+
+ /** One entry in the log. */
+ public static class LogEntryParcel implements Parcelable {
+ public final LogLevel mLevel;
+ public final LogType mType;
+ public final String[] mParameters;
+ public final int mIndent;
+
+ public LogEntryParcel(LogLevel level, LogType type, String[] parameters, int indent) {
+ mLevel = level;
+ mType = type;
+ mParameters = parameters;
+ mIndent = indent;
+ }
+ public LogEntryParcel(LogLevel level, LogType type, String[] parameters) {
+ this(level, type, parameters, 0);
+ }
+
+ public LogEntryParcel(Parcel source) {
+ mLevel = LogLevel.values()[source.readInt()];
+ mType = LogType.values()[source.readInt()];
+ mParameters = source.createStringArray();
+ mIndent = source.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mLevel.ordinal());
+ dest.writeInt(mType.ordinal());
+ dest.writeStringArray(mParameters);
+ dest.writeInt(mIndent);
+ }
+
+ public static final Creator<LogEntryParcel> CREATOR = new Creator<LogEntryParcel>() {
+ public LogEntryParcel createFromParcel(final Parcel source) {
+ return new LogEntryParcel(source);
+ }
+
+ public LogEntryParcel[] newArray(final int size) {
+ return new LogEntryParcel[size];
+ }
+ };
+
+ }
+
+ /** This is an enum of all possible log events.
+ *
+ * Element names should generally be prefixed with MSG_XX_ where XX is an
+ * identifier based on the related activity.
+ *
+ * Log messages should occur for each distinguishable action group. For
+ * each such group, one message is displayed followed by warnings or
+ * errors, and optionally subactions. The granularity should generally be
+ * optimistic: No "success" messages are printed except for the outermost
+ * operations - the success of an action group is indicated by the
+ * beginning message of the next action group.
+ *
+ * Log messages should be in present tense, There should be no trailing
+ * punctuation, except for error messages which may end in an exclamation
+ * mark.
+ *
+ */
+ public static enum LogType {
+
+ // import public
+ MSG_IP(R.string.msg_ip),
+ MSG_IP_APPLY_BATCH (R.string.msg_ip_apply_batch),
+ MSG_IP_BAD_TYPE_SECRET (R.string.msg_ip_bad_type_secret),
+ MSG_IP_DELETE_OLD_FAIL (R.string.msg_ip_delete_old_fail),
+ MSG_IP_DELETE_OLD_OK (R.string.msg_ip_delete_old_ok),
+ MSG_IP_ENCODE_FAIL (R.string.msg_ip_encode_fail),
+ MSG_IP_FAIL_IO_EXC (R.string.msg_ip_fail_io_exc),
+ MSG_IP_FAIL_OP_EXC (R.string.msg_ip_fail_op_exc),
+ MSG_IP_FAIL_REMOTE_EX (R.string.msg_ip_fail_remote_ex),
+ MSG_IP_INSERT_KEYRING (R.string.msg_ip_insert_keyring),
+ MSG_IP_INSERT_SUBKEYS (R.string.msg_ip_insert_keys),
+ MSG_IP_PREPARE (R.string.msg_ip_prepare),
+ MSG_IP_REINSERT_SECRET (R.string.msg_ip_reinsert_secret),
+ MSG_IP_MASTER (R.string.msg_ip_master),
+ MSG_IP_MASTER_EXPIRED (R.string.msg_ip_master_expired),
+ MSG_IP_MASTER_EXPIRES (R.string.msg_ip_master_expires),
+ MSG_IP_MASTER_FLAGS_CES (R.string.msg_ip_master_flags_ces),
+ MSG_IP_MASTER_FLAGS_CEX (R.string.msg_ip_master_flags_cex),
+ MSG_IP_MASTER_FLAGS_CXS (R.string.msg_ip_master_flags_cxs),
+ MSG_IP_MASTER_FLAGS_XES (R.string.msg_ip_master_flags_xes),
+ MSG_IP_MASTER_FLAGS_CXX (R.string.msg_ip_master_flags_cxx),
+ MSG_IP_MASTER_FLAGS_XEX (R.string.msg_ip_master_flags_xex),
+ MSG_IP_MASTER_FLAGS_XXS (R.string.msg_ip_master_flags_xxs),
+ MSG_IP_MASTER_FLAGS_XXX (R.string.msg_ip_master_flags_xxx),
+ MSG_IP_SUBKEY (R.string.msg_ip_subkey),
+ MSG_IP_SUBKEY_EXPIRED (R.string.msg_ip_subkey_expired),
+ MSG_IP_SUBKEY_EXPIRES (R.string.msg_ip_subkey_expires),
+ MSG_IP_SUBKEY_FLAGS_CES (R.string.msg_ip_subkey_flags_ces),
+ MSG_IP_SUBKEY_FLAGS_CEX (R.string.msg_ip_subkey_flags_cex),
+ MSG_IP_SUBKEY_FLAGS_CXS (R.string.msg_ip_subkey_flags_cxs),
+ MSG_IP_SUBKEY_FLAGS_XES (R.string.msg_ip_subkey_flags_xes),
+ MSG_IP_SUBKEY_FLAGS_CXX (R.string.msg_ip_subkey_flags_cxx),
+ MSG_IP_SUBKEY_FLAGS_XEX (R.string.msg_ip_subkey_flags_xex),
+ MSG_IP_SUBKEY_FLAGS_XXS (R.string.msg_ip_subkey_flags_xxs),
+ MSG_IP_SUBKEY_FLAGS_XXX (R.string.msg_ip_subkey_flags_xxx),
+ MSG_IP_SUCCESS (R.string.msg_ip_success),
+ MSG_IP_SUCCESS_IDENTICAL (R.string.msg_ip_success_identical),
+ MSG_IP_UID_CERT_BAD (R.string.msg_ip_uid_cert_bad),
+ MSG_IP_UID_CERT_ERROR (R.string.msg_ip_uid_cert_error),
+ MSG_IP_UID_CERT_GOOD (R.string.msg_ip_uid_cert_good),
+ MSG_IP_UID_CERTS_UNKNOWN (R.string.msg_ip_uid_certs_unknown),
+ MSG_IP_UID_CLASSIFYING (R.string.msg_ip_uid_classifying),
+ MSG_IP_UID_REORDER(R.string.msg_ip_uid_reorder),
+ MSG_IP_UID_PROCESSING (R.string.msg_ip_uid_processing),
+ MSG_IP_UID_REVOKED (R.string.msg_ip_uid_revoked),
+
+ // import secret
+ MSG_IS(R.string.msg_is),
+ MSG_IS_BAD_TYPE_PUBLIC (R.string.msg_is_bad_type_public),
+ MSG_IS_DB_EXCEPTION (R.string.msg_is_db_exception),
+ MSG_IS_FAIL_IO_EXC (R.string.msg_is_io_exc),
+ MSG_IS_IMPORTING_SUBKEYS (R.string.msg_is_importing_subkeys),
+ MSG_IS_PUBRING_GENERATE (R.string.msg_is_pubring_generate),
+ MSG_IS_SUBKEY_NONEXISTENT (R.string.msg_is_subkey_nonexistent),
+ MSG_IS_SUBKEY_OK (R.string.msg_is_subkey_ok),
+ MSG_IS_SUBKEY_STRIPPED (R.string.msg_is_subkey_stripped),
+ MSG_IS_SUCCESS_IDENTICAL (R.string.msg_is_success_identical),
+ MSG_IS_SUCCESS (R.string.msg_is_success),
+
+ // keyring canonicalization
+ MSG_KC_PUBLIC (R.string.msg_kc_public),
+ MSG_KC_SECRET (R.string.msg_kc_secret),
+ MSG_KC_FATAL_NO_UID (R.string.msg_kc_fatal_no_uid),
+ MSG_KC_MASTER (R.string.msg_kc_master),
+ MSG_KC_REVOKE_BAD_ERR (R.string.msg_kc_revoke_bad_err),
+ MSG_KC_REVOKE_BAD_LOCAL (R.string.msg_kc_revoke_bad_local),
+ MSG_KC_REVOKE_BAD_TIME (R.string.msg_kc_revoke_bad_time),
+ MSG_KC_REVOKE_BAD_TYPE (R.string.msg_kc_revoke_bad_type),
+ MSG_KC_REVOKE_BAD (R.string.msg_kc_revoke_bad),
+ MSG_KC_REVOKE_DUP (R.string.msg_kc_revoke_dup),
+ MSG_KC_SUB (R.string.msg_kc_sub),
+ MSG_KC_SUB_BAD(R.string.msg_kc_sub_bad),
+ MSG_KC_SUB_BAD_ERR(R.string.msg_kc_sub_bad_err),
+ MSG_KC_SUB_BAD_LOCAL(R.string.msg_kc_sub_bad_local),
+ MSG_KC_SUB_BAD_KEYID(R.string.msg_kc_sub_bad_keyid),
+ MSG_KC_SUB_BAD_TIME(R.string.msg_kc_sub_bad_time),
+ MSG_KC_SUB_BAD_TYPE(R.string.msg_kc_sub_bad_type),
+ MSG_KC_SUB_PRIMARY_BAD(R.string.msg_kc_sub_primary_bad),
+ MSG_KC_SUB_PRIMARY_BAD_ERR(R.string.msg_kc_sub_primary_bad_err),
+ MSG_KC_SUB_PRIMARY_NONE(R.string.msg_kc_sub_primary_none),
+ MSG_KC_SUB_NO_CERT(R.string.msg_kc_sub_no_cert),
+ MSG_KC_SUB_REVOKE_BAD_ERR (R.string.msg_kc_sub_revoke_bad_err),
+ MSG_KC_SUB_REVOKE_BAD (R.string.msg_kc_sub_revoke_bad),
+ MSG_KC_SUB_REVOKE_DUP (R.string.msg_kc_sub_revoke_dup),
+ MSG_KC_SUCCESS_BAD (R.string.msg_kc_success_bad),
+ MSG_KC_SUCCESS_BAD_AND_RED (R.string.msg_kc_success_bad_and_red),
+ MSG_KC_SUCCESS_REDUNDANT (R.string.msg_kc_success_redundant),
+ MSG_KC_SUCCESS (R.string.msg_kc_success),
+ MSG_KC_UID_BAD_ERR (R.string.msg_kc_uid_bad_err),
+ MSG_KC_UID_BAD_LOCAL (R.string.msg_kc_uid_bad_local),
+ MSG_KC_UID_BAD_TIME (R.string.msg_kc_uid_bad_time),
+ MSG_KC_UID_BAD_TYPE (R.string.msg_kc_uid_bad_type),
+ MSG_KC_UID_BAD (R.string.msg_kc_uid_bad),
+ MSG_KC_UID_DUP (R.string.msg_kc_uid_dup),
+ MSG_KC_UID_FOREIGN (R.string.msg_kc_uid_foreign),
+ MSG_KC_UID_NO_CERT (R.string.msg_kc_uid_no_cert),
+ MSG_KC_UID_REVOKE_DUP (R.string.msg_kc_uid_revoke_dup),
+ MSG_KC_UID_REVOKE_OLD (R.string.msg_kc_uid_revoke_old),
+
+
+ // keyring consolidation
+ MSG_MG_PUBLIC (R.string.msg_mg_public),
+ MSG_MG_SECRET (R.string.msg_mg_secret),
+ MSG_MG_FATAL_ENCODE (R.string.msg_mg_fatal_encode),
+ MSG_MG_HETEROGENEOUS (R.string.msg_mg_heterogeneous),
+ MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey),
+ MSG_MG_FOUND_NEW (R.string.msg_mg_found_new),
+
+ // secret key modify
+ MSG_MF (R.string.msg_mr),
+ MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode),
+ MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp),
+ MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig),
+ MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase),
+ MSG_MF_SUBKEY_CHANGE (R.string.msg_mf_subkey_change),
+ MSG_MF_SUBKEY_MISSING (R.string.msg_mf_subkey_missing),
+ MSG_MF_SUBKEY_NEW_ID (R.string.msg_mf_subkey_new_id),
+ MSG_MF_SUBKEY_NEW (R.string.msg_mf_subkey_new),
+ MSG_MF_SUBKEY_PAST_EXPIRY (R.string.msg_mf_subkey_past_expiry),
+ MSG_MF_SUBKEY_REVOKE (R.string.msg_mf_subkey_revoke),
+ MSG_MF_SUCCESS (R.string.msg_mf_success),
+ MSG_MF_UID_ADD (R.string.msg_mf_uid_add),
+ MSG_MF_UID_PRIMARY (R.string.msg_mf_uid_primary),
+ MSG_MF_UID_REVOKE (R.string.msg_mf_uid_revoke),
+ MSG_MF_UNLOCK_ERROR (R.string.msg_mf_unlock_error),
+ MSG_MF_UNLOCK (R.string.msg_mf_unlock),
+ ;
+
+ private final int mMsgId;
+ LogType(int msgId) {
+ mMsgId = msgId;
+ }
+ public int getMsgId() {
+ return mMsgId;
+ }
+ }
+
+ /** Enumeration of possible log levels. */
+ public static enum LogLevel {
+ DEBUG,
+ INFO,
+ WARN,
+ ERROR, // should occur once at the end of a failed operation
+ START, // should occur once at the start of each independent operation
+ OK, // should occur once at the end of a successful operation
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mResult);
+ dest.writeTypedList(mLog);
+ }
+
+ public static final Creator<OperationResultParcel> CREATOR = new Creator<OperationResultParcel>() {
+ public OperationResultParcel createFromParcel(final Parcel source) {
+ return new OperationResultParcel(source);
+ }
+
+ public OperationResultParcel[] newArray(final int size) {
+ return new OperationResultParcel[size];
+ }
+ };
+
+ public static class OperationLog extends ArrayList<LogEntryParcel> {
+
+ /// Simple convenience method
+ public void add(LogLevel level, LogType type, String[] parameters, int indent) {
+ Log.d(Constants.TAG, type.toString());
+ add(new OperationResultParcel.LogEntryParcel(level, type, parameters, indent));
+ }
+
+ public void add(LogLevel level, LogType type, int indent) {
+ add(new OperationResultParcel.LogEntryParcel(level, type, null, indent));
+ }
+
+ public boolean containsWarnings() {
+ for(LogEntryParcel entry : new IterableIterator<LogEntryParcel>(iterator())) {
+ if (entry.mLevel == LogLevel.WARN || entry.mLevel == LogLevel.ERROR) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java
new file mode 100644
index 000000000..6c44b01f1
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResults.java
@@ -0,0 +1,92 @@
+package org.sufficientlysecure.keychain.service;
+
+import android.os.Parcel;
+
+public abstract class OperationResults {
+
+ public static class ImportResult extends OperationResultParcel {
+
+ public final int mNewKeys, mUpdatedKeys, mBadKeys;
+
+ // At least one new key
+ public static final int RESULT_OK_NEWKEYS = 2;
+ // At least one updated key
+ public static final int RESULT_OK_UPDATED = 4;
+ // At least one key failed (might still be an overall success)
+ public static final int RESULT_WITH_ERRORS = 8;
+ // There are warnings in the log
+ public static final int RESULT_WITH_WARNINGS = 16;
+
+ // No keys to import...
+ public static final int RESULT_FAIL_NOTHING = 32 +1;
+
+ public boolean isOkBoth() {
+ return (mResult & (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED))
+ == (RESULT_OK_NEWKEYS | RESULT_OK_UPDATED);
+ }
+ public boolean isOkNew() {
+ return (mResult & RESULT_OK_NEWKEYS) == RESULT_OK_NEWKEYS;
+ }
+ public boolean isOkUpdated() {
+ return (mResult & RESULT_OK_UPDATED) == RESULT_OK_UPDATED;
+ }
+ public boolean isFailNothing() {
+ return (mResult & RESULT_FAIL_NOTHING) == RESULT_FAIL_NOTHING;
+ }
+
+ public ImportResult(Parcel source) {
+ super(source);
+ mNewKeys = source.readInt();
+ mUpdatedKeys = source.readInt();
+ mBadKeys = source.readInt();
+ }
+
+ public ImportResult(int result, OperationLog log,
+ int newKeys, int updatedKeys, int badKeys) {
+ super(result, log);
+ mNewKeys = newKeys;
+ mUpdatedKeys = updatedKeys;
+ mBadKeys = badKeys;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mNewKeys);
+ dest.writeInt(mUpdatedKeys);
+ dest.writeInt(mBadKeys);
+ }
+
+ public static Creator<ImportResult> CREATOR = new Creator<ImportResult>() {
+ public ImportResult createFromParcel(final Parcel source) {
+ return new ImportResult(source);
+ }
+
+ public ImportResult[] newArray(final int size) {
+ return new ImportResult[size];
+ }
+ };
+
+ }
+
+ public static class SaveKeyringResult extends OperationResultParcel {
+
+ public SaveKeyringResult(int result, OperationLog log) {
+ super(result, log);
+ }
+
+ // Some old key was updated
+ public static final int UPDATED = 2;
+
+ // Public key was saved
+ public static final int SAVED_PUBLIC = 8;
+ // Secret key was saved (not exclusive with public!)
+ public static final int SAVED_SECRET = 16;
+
+ public boolean updated() {
+ return (mResult & UPDATED) == UPDATED;
+ }
+
+ }
+
+}
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 3514ab2e5..c68b7c189 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
@@ -23,16 +23,16 @@ import java.util.HashMap;
public class SaveKeyringParcel implements Parcelable {
// the master key id to be edited
- private final long mMasterKeyId;
+ public final long mMasterKeyId;
// the key fingerprint, for safety
- private final byte[] mFingerprint;
+ public final byte[] mFingerprint;
public String newPassphrase;
public String[] addUserIds;
public SubkeyAdd[] addSubKeys;
- public HashMap<Long, SubkeyChange> changeSubKeys;
+ public SubkeyChange[] changeSubKeys;
public String changePrimaryUserId;
public String[] revokeUserIds;
@@ -76,7 +76,7 @@ public class SaveKeyringParcel implements Parcelable {
addUserIds = source.createStringArray();
addSubKeys = (SubkeyAdd[]) source.readSerializable();
- changeSubKeys = (HashMap<Long,SubkeyChange>) source.readSerializable();
+ changeSubKeys = (SubkeyChange[]) source.readSerializable();
changePrimaryUserId = source.readString();
revokeUserIds = source.createStringArray();