aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-03-24 15:29:02 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2015-03-24 15:29:58 +0100
commitf9ef1160ca764d508dafcb45fbf65f18911fff9c (patch)
tree816564326b238848669d7a0713f48c84791cd13b /OpenKeychain/src/main/java/org
parentfe32e7bff4e724d37903d07cd3b4f0287ec85879 (diff)
parent8b4388e1a2d5cb2b7f0524c18ad3383e3375ba7b (diff)
downloadopen-keychain-f9ef1160ca764d508dafcb45fbf65f18911fff9c.tar.gz
open-keychain-f9ef1160ca764d508dafcb45fbf65f18911fff9c.tar.bz2
open-keychain-f9ef1160ca764d508dafcb45fbf65f18911fff9c.zip
Merge branch 'development' into linked-identities
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
Diffstat (limited to 'OpenKeychain/src/main/java/org')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/CertifyResult.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DeleteResult.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java26
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java70
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java24
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java25
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java47
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java22
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java30
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java33
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java23
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java91
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java62
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java65
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java55
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java56
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java157
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java60
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java23
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java59
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java110
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java44
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java265
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java31
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java12
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubStep1Fragment.java8
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java218
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java218
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java163
84 files changed, 1533 insertions, 1005 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
index 30d855a74..fc1cb8acc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java
@@ -42,6 +42,15 @@ public final class Constants {
// as defined in http://tools.ietf.org/html/rfc3156, section 7
public static final String NFC_MIME = "application/pgp-keys";
+ // as defined in http://tools.ietf.org/html/rfc3156
+ // we don't use application/pgp-encrypted as it only holds the version number
+ public static final String ENCRYPTED_FILES_MIME = "application/octet-stream";
+ public static final String ENCRYPTED_TEXT_MIME = "text/plain";
+
+ public static final String FILE_EXTENSION_PGP_MAIN = ".gpg";
+ public static final String FILE_EXTENSION_PGP_ALTERNATE = ".pgp";
+ public static final String FILE_EXTENSION_ASC = ".asc";
+
// used by QR Codes (Guardian Project, Monkeysphere compatiblity)
public static final String FINGERPRINT_SCHEME = "openpgp4fpr";
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
index a4dc12a37..d26ccbe57 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java
@@ -118,24 +118,21 @@ public class KeychainApplication extends Application {
* @param context
*/
public static void setupAccountAsNeeded(Context context) {
- // only enabled for Jelly Bean because we need some newer methods in our sync adapter
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- try {
- AccountManager manager = AccountManager.get(context);
- Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
- if (accounts == null || accounts.length == 0) {
- Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
- if (manager.addAccountExplicitly(account, null, null)) {
- ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
- ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
- } else {
- Log.e(Constants.TAG, "Adding account failed!");
- }
+ try {
+ AccountManager manager = AccountManager.get(context);
+ Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
+ if (accounts == null || accounts.length == 0) {
+ Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
+ if (manager.addAccountExplicitly(account, null, null)) {
+ ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
+ ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
+ } else {
+ Log.e(Constants.TAG, "Adding account failed!");
}
- } catch (SecurityException e) {
- Log.e(Constants.TAG, "SecurityException when adding the account", e);
- Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
}
+ } catch (SecurityException e) {
+ Log.e(Constants.TAG, "SecurityException when adding the account", e);
+ Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
index 02cb502d0..03439228b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysList.java
@@ -70,6 +70,8 @@ public class ImportKeysList extends ArrayList<ImportKeysListEntry> {
modified = true;
}
+ // keep track if this key result is from a HKP keyserver
+ boolean incomingFromHkpServer = true;
// we’re going to want to try to fetch the key from everywhere we found it, so remember
// all the origins
for (String origin : incoming.getOrigins()) {
@@ -78,13 +80,24 @@ public class ImportKeysList extends ArrayList<ImportKeysListEntry> {
// to work properly, Keybase-sourced entries need to pass along the extra
if (KeybaseKeyserver.ORIGIN.equals(origin)) {
existing.setExtraData(incoming.getExtraData());
+ // one of the origins is not a HKP keyserver
+ incomingFromHkpServer = false;
}
}
+
ArrayList<String> incomingIDs = incoming.getUserIds();
ArrayList<String> existingIDs = existing.getUserIds();
for (String incomingID : incomingIDs) {
if (!existingIDs.contains(incomingID)) {
- existingIDs.add(incomingID);
+ // prepend HKP server results to the start of the list,
+ // so that the UI (for cloud key search, which is picking the first list item)
+ // shows the right main email address, as mail addresses returned by HKP servers
+ // are preferred over keybase.io IDs
+ if (incomingFromHkpServer) {
+ existingIDs.add(0, incomingID);
+ } else {
+ existingIDs.add(incomingID);
+ }
modified = true;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
index 7dac8b1e0..bb86d272f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/ImportKeysListEntry.java
@@ -307,24 +307,22 @@ public class ImportKeysListEntry implements Serializable, Parcelable {
public void updateMergedUserIds() {
mMergedUserIds = new HashMap<>();
for (String userId : mUserIds) {
- String[] userIdSplit = KeyRing.splitUserId(userId);
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
// TODO: comment field?
- // name
- if (userIdSplit[0] != null) {
- // email
- if (userIdSplit[1] != null) {
- if (!mMergedUserIds.containsKey(userIdSplit[0])) {
+ if (userIdSplit.name != null) {
+ if (userIdSplit.email != null) {
+ if (!mMergedUserIds.containsKey(userIdSplit.name)) {
HashSet<String> emails = new HashSet<>();
- emails.add(userIdSplit[1]);
- mMergedUserIds.put(userIdSplit[0], emails);
+ emails.add(userIdSplit.email);
+ mMergedUserIds.put(userIdSplit.name, emails);
} else {
- mMergedUserIds.get(userIdSplit[0]).add(userIdSplit[1]);
+ mMergedUserIds.get(userIdSplit.name).add(userIdSplit.email);
}
} else {
// name only
- mMergedUserIds.put(userIdSplit[0], new HashSet<String>());
+ mMergedUserIds.put(userIdSplit.name, new HashSet<String>());
}
} else {
// fallback
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
index 40dcbd78d..a824e73d7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
@@ -24,6 +24,7 @@ import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -101,7 +102,7 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
}
@Override
- public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
+ public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
try {
long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId);
return getCachedPassphrase(masterKeyId, subKeyId);
@@ -111,7 +112,7 @@ public abstract class BaseOperation implements PassphraseCacheInterface {
}
@Override
- public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
+ public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
try {
return PassphraseCacheService.getCachedPassphrase(
mContext, masterKeyId, subKeyId);
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 ebf0dc70b..4ceb34722 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java
@@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyActio
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -79,7 +80,7 @@ public class CertifyOperation extends BaseOperation {
}
// certification is always with the master key id, so use that one
- String passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
+ Passphrase passphrase = getCachedPassphrase(parcel.mMasterKeyId, parcel.mMasterKeyId);
if (!certificationKey.unlock(passphrase)) {
log.add(LogType.MSG_CRT_ERROR_UNLOCK, 2);
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 bcd842dd0..a179b53ee 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java
@@ -35,6 +35,7 @@ import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -55,7 +56,7 @@ public class EditKeyOperation extends BaseOperation {
super(context, providerHelper, progressable, cancelled);
}
- public EditKeyResult execute(SaveKeyringParcel saveParcel, String passphrase) {
+ public EditKeyResult execute(SaveKeyringParcel saveParcel, Passphrase passphrase) {
OperationLog log = new OperationLog();
log.add(LogType.MSG_ED, 0);
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 94684851a..f56fe4bb9 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
@@ -120,7 +120,7 @@ public class CertifyResult extends OperationResult {
mCertifyError, mCertifyError);
}
- return Notify.createNotify(activity, str, duration, style, new ActionListener() {
+ return Notify.create(activity, str, duration, style, new ActionListener() {
@Override
public void onAction() {
Intent intent = new Intent(
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 86b37fea6..7df37cd9b 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
@@ -22,6 +22,7 @@ import android.os.Parcel;
import org.openintents.openpgp.OpenPgpMetadata;
import org.openintents.openpgp.OpenPgpSignatureResult;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class DecryptVerifyResult extends OperationResult {
@@ -37,7 +38,7 @@ public class DecryptVerifyResult extends OperationResult {
long mNfcSubKeyId;
byte[] mNfcSessionKey;
- String mNfcPassphrase;
+ Passphrase mNfcPassphrase;
OpenPgpSignatureResult mSignatureResult;
OpenPgpMetadata mDecryptMetadata;
@@ -53,7 +54,7 @@ public class DecryptVerifyResult extends OperationResult {
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
}
- public void setNfcState(long subKeyId, byte[] sessionKey, String passphrase) {
+ public void setNfcState(long subKeyId, byte[] sessionKey, Passphrase passphrase) {
mNfcSubKeyId = subKeyId;
mNfcSessionKey = sessionKey;
mNfcPassphrase = passphrase;
@@ -67,7 +68,7 @@ public class DecryptVerifyResult extends OperationResult {
return mNfcSessionKey;
}
- public String getNfcPassphrase() {
+ public Passphrase getNfcPassphrase() {
return mNfcPassphrase;
}
@@ -109,7 +110,7 @@ public class DecryptVerifyResult extends OperationResult {
mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());
mDecryptMetadata = source.readParcelable(OpenPgpMetadata.class.getClassLoader());
mNfcSessionKey = source.readInt() != 0 ? source.createByteArray() : null;
- mNfcPassphrase = source.readString();
+ mNfcPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
}
public int describeContents() {
@@ -127,7 +128,7 @@ public class DecryptVerifyResult extends OperationResult {
} else {
dest.writeInt(0);
}
- dest.writeString(mNfcPassphrase);
+ dest.writeParcelable(mNfcPassphrase, flags);
}
public static final Creator<DecryptVerifyResult> CREATOR = new Creator<DecryptVerifyResult>() {
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 62197541a..50f49add2 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
@@ -116,7 +116,7 @@ public class DeleteResult extends OperationResult {
}
}
- return Notify.createNotify(activity, str, duration, style, new ActionListener() {
+ return Notify.create(activity, str, duration, style, new ActionListener() {
@Override
public void onAction() {
Intent intent = new Intent(
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 2d533ed16..af9f67114 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
@@ -179,7 +179,7 @@ public class ImportKeyResult extends OperationResult {
}
}
- return Notify.createNotify(activity, str, duration, style, new ActionListener() {
+ return Notify.create(activity, str, duration, style, new ActionListener() {
@Override
public void onAction() {
Intent intent = new Intent(
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 7cb5e4904..616b6f062 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
@@ -273,19 +273,19 @@ public abstract class OperationResult implements Parcelable {
}
if (getLog() == null || getLog().isEmpty()) {
- return Notify.createNotify(activity, msgId, Notify.LENGTH_LONG, style);
- }
-
- return Notify.createNotify(activity, msgId, Notify.LENGTH_LONG, style,
- new ActionListener() {
- @Override
- public void onAction() {
- Intent intent = new Intent(
- activity, LogDisplayActivity.class);
- intent.putExtra(LogDisplayFragment.EXTRA_RESULT, OperationResult.this);
- activity.startActivity(intent);
- }
- }, R.string.view_log);
+ return Notify.create(activity, msgId, Notify.LENGTH_LONG, style);
+ }
+
+ return Notify.create(activity, msgId, Notify.LENGTH_LONG, style,
+ new ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intent = new Intent(
+ activity, LogDisplayActivity.class);
+ intent.putExtra(LogDisplayFragment.EXTRA_RESULT, OperationResult.this);
+ activity.startActivity(intent);
+ }
+ }, R.string.view_log);
}
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 de2f64404..cf40001b3 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,8 @@ package org.sufficientlysecure.keychain.operations.results;
import android.os.Parcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
import java.util.Date;
public class PgpSignEncryptResult extends OperationResult {
@@ -36,7 +38,7 @@ public class PgpSignEncryptResult extends OperationResult {
byte[] mNfcHash;
int mNfcAlgo;
Date mNfcTimestamp;
- String mNfcPassphrase;
+ Passphrase mNfcPassphrase;
byte[] mDetachedSignature;
public long getKeyIdPassphraseNeeded() {
@@ -47,7 +49,7 @@ public class PgpSignEncryptResult extends OperationResult {
mKeyIdPassphraseNeeded = keyIdPassphraseNeeded;
}
- public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Date nfcTimestamp, String passphrase) {
+ public void setNfcData(long nfcKeyId, byte[] nfcHash, int nfcAlgo, Date nfcTimestamp, Passphrase passphrase) {
mNfcKeyId = nfcKeyId;
mNfcHash = nfcHash;
mNfcAlgo = nfcAlgo;
@@ -75,7 +77,7 @@ public class PgpSignEncryptResult extends OperationResult {
return mNfcTimestamp;
}
- public String getNfcPassphrase() {
+ public Passphrase getNfcPassphrase() {
return mNfcPassphrase;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java
index 8104c5249..412468a48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedPublicKey.java
@@ -55,8 +55,8 @@ public class CanonicalizedPublicKey extends UncachedPublicKey {
return new IterableIterator<String>(mPublicKey.getUserIDs());
}
- JcePublicKeyKeyEncryptionMethodGenerator getPubKeyEncryptionGenerator() {
- return new JcePublicKeyKeyEncryptionMethodGenerator(mPublicKey);
+ JcePublicKeyKeyEncryptionMethodGenerator getPubKeyEncryptionGenerator(boolean hiddenRecipients) {
+ return new JcePublicKeyKeyEncryptionMethodGenerator(mPublicKey, hiddenRecipients);
}
public boolean canSign() {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
index ab91d7747..6ce77394c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java
@@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
import java.util.Date;
@@ -149,7 +150,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
/**
* Returns true on right passphrase
*/
- public boolean unlock(String passphrase) throws PgpGeneralException {
+ public boolean unlock(Passphrase passphrase) throws PgpGeneralException {
// handle keys on OpenPGP cards like they were unlocked
if (mSecretKey.getS2K() != null
&& mSecretKey.getS2K().getType() == S2K.GNU_DUMMY_S2K
@@ -161,7 +162,7 @@ public class CanonicalizedSecretKey extends CanonicalizedPublicKey {
// try to extract keys using the passphrase
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
mPrivateKey = mSecretKey.extractPrivateKey(keyDecryptor);
mPrivateKeyState = PRIVATE_KEY_STATE_UNLOCKED;
} catch (PGPException e) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java
index 26375219b..825795cc6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java
@@ -44,7 +44,7 @@ public abstract class KeyRing {
abstract public String getPrimaryUserIdWithFallback() throws PgpKeyNotFoundException;
- public String[] getSplitPrimaryUserIdWithFallback() throws PgpKeyNotFoundException {
+ public UserId getSplitPrimaryUserIdWithFallback() throws PgpKeyNotFoundException {
return splitUserId(getPrimaryUserIdWithFallback());
}
@@ -62,55 +62,45 @@ public abstract class KeyRing {
/**
* Splits userId string into naming part, email part, and comment part
- *
- * @param userId
- * @return array with naming (0), email (1), comment (2)
+ * <p/>
+ * User ID matching:
+ * http://fiddle.re/t4p6f
*/
- public static String[] splitUserId(String userId) {
- String[] result = new String[]{null, null, null};
-
- if (userId == null || userId.equals("")) {
- return result;
- }
-
- /*
- * User ID matching:
- * http://fiddle.re/t4p6f
- *
- * test cases:
- * "Max Mustermann (this is a comment) <max@example.com>"
- * "Max Mustermann <max@example.com>"
- * "Max Mustermann (this is a comment)"
- * "Max Mustermann [this is nothing]"
- */
- Matcher matcher = USER_ID_PATTERN.matcher(userId);
- if (matcher.matches()) {
- result[0] = matcher.group(1);
- result[1] = matcher.group(3);
- result[2] = matcher.group(2);
+ public static UserId splitUserId(final String userId) {
+ if (!TextUtils.isEmpty(userId)) {
+ final Matcher matcher = USER_ID_PATTERN.matcher(userId);
+ if (matcher.matches()) {
+ return new UserId(matcher.group(1), matcher.group(3), matcher.group(2));
+ }
}
-
- return result;
+ return new UserId(null, null, null);
}
/**
* Returns a composed user id. Returns null if name is null!
- *
- * @param name
- * @param email
- * @param comment
- * @return
*/
- public static String createUserId(String name, String email, String comment) {
- String userId = name; // consider name a required value
- if (userId != null && !TextUtils.isEmpty(comment)) {
- userId += " (" + comment + ")";
+ public static String createUserId(UserId userId) {
+ String userIdString = userId.name; // consider name a required value
+ if (userIdString != null && !TextUtils.isEmpty(userId.comment)) {
+ userIdString += " (" + userId.comment + ")";
}
- if (userId != null && !TextUtils.isEmpty(email)) {
- userId += " <" + email + ">";
+ if (userIdString != null && !TextUtils.isEmpty(userId.email)) {
+ userIdString += " <" + userId.email + ">";
}
- return userId;
+ return userIdString;
+ }
+
+ public static class UserId {
+ public final String name;
+ public final String email;
+ public final String comment;
+
+ public UserId(String name, String email, String comment) {
+ this.name = name;
+ this.email = email;
+ this.comment = comment;
+ }
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java
index ae1b94a34..88ccccc6a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java
@@ -1,13 +1,33 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.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.pgp;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
public interface PassphraseCacheInterface {
public static class NoSecretKeyException extends Exception {
public NoSecretKeyException() {
}
}
- public String getCachedPassphrase(long subKeyId) throws NoSecretKeyException;
+ public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException;
- public String getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException;
+ public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException;
}
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 14bc56538..364a1067d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
@@ -60,6 +60,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.BufferedInputStream;
@@ -83,7 +84,7 @@ public class PgpDecryptVerify extends BaseOperation {
private OutputStream mOutStream;
private boolean mAllowSymmetricDecryption;
- private String mPassphrase;
+ private Passphrase mPassphrase;
private Set<Long> mAllowedKeyIds;
private boolean mDecryptMetadataOnly;
private byte[] mDecryptedSessionKey;
@@ -118,7 +119,7 @@ public class PgpDecryptVerify extends BaseOperation {
private OutputStream mOutStream = null;
private Progressable mProgressable = null;
private boolean mAllowSymmetricDecryption = true;
- private String mPassphrase = null;
+ private Passphrase mPassphrase = null;
private Set<Long> mAllowedKeyIds = null;
private boolean mDecryptMetadataOnly = false;
private byte[] mDecryptedSessionKey = null;
@@ -159,7 +160,7 @@ public class PgpDecryptVerify extends BaseOperation {
return this;
}
- public Builder setPassphrase(String passphrase) {
+ public Builder setPassphrase(Passphrase passphrase) {
mPassphrase = passphrase;
return this;
}
@@ -572,7 +573,7 @@ public class PgpDecryptVerify extends BaseOperation {
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build();
PBEDataDecryptorFactory decryptorFactory = new JcePBEDataDecryptorFactoryBuilder(
digestCalcProvider).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- mPassphrase.toCharArray());
+ mPassphrase.getCharArray());
clear = encryptedDataSymmetric.getDataStream(decryptorFactory);
encryptedData = encryptedDataSymmetric;
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 8fb5392e3..b3bf92364 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java
@@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.IterableIterator;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Primes;
import org.sufficientlysecure.keychain.util.ProgressScaler;
@@ -316,7 +317,7 @@ public class PgpKeyOperation {
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
subProgressPush(50, 100);
- return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, "", log);
+ return internal(sKR, masterSecretKey, add.mFlags, add.mExpiry, saveParcel, new Passphrase(), log);
} catch (PGPException e) {
log.add(LogType.MSG_CR_ERROR_INTERNAL_PGP, indent);
@@ -348,7 +349,7 @@ public class PgpKeyOperation {
*
*/
public PgpEditKeyResult modifySecretKeyRing(CanonicalizedSecretKeyRing wsKR, SaveKeyringParcel saveParcel,
- String passphrase) {
+ Passphrase passphrase) {
OperationLog log = new OperationLog();
int indent = 0;
@@ -404,7 +405,7 @@ public class PgpKeyOperation {
private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey,
int masterKeyFlags, long masterKeyExpiry,
- SaveKeyringParcel saveParcel, String passphrase,
+ SaveKeyringParcel saveParcel, Passphrase passphrase,
OperationLog log) {
int indent = 1;
@@ -420,7 +421,7 @@ public class PgpKeyOperation {
{
try {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
} catch (PGPException e) {
log.add(LogType.MSG_MF_UNLOCK_ERROR, indent + 1);
@@ -839,7 +840,7 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
- .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
+ .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
@@ -967,7 +968,7 @@ public class PgpKeyOperation {
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,
PGPPrivateKey masterPrivateKey,
- String passphrase,
+ Passphrase passphrase,
ChangeUnlockParcel newUnlock,
OperationLog log, int indent) throws PGPException {
@@ -1051,20 +1052,20 @@ public class PgpKeyOperation {
private static PGPSecretKeyRing applyNewPassphrase(
PGPSecretKeyRing sKR,
PGPPublicKey masterPublicKey,
- String passphrase,
- String newPassphrase,
+ Passphrase passphrase,
+ Passphrase newPassphrase,
OperationLog log, int indent) throws PGPException {
PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
.get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
- Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
+ Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.getCharArray());
// Build key encryptor based on new passphrase
PBESecretKeyEncryptor keyEncryptorNew = new JcePBESecretKeyEncryptorBuilder(
PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- newPassphrase.toCharArray());
+ newPassphrase.getCharArray());
// noinspection unchecked
for (PGPSecretKey sKey : new IterableIterator<PGPSecretKey>(sKR.getSecretKeys())) {
@@ -1295,11 +1296,11 @@ public class PgpKeyOperation {
private static PGPSignature generateSubkeyBindingSignature(
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
- PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, String passphrase)
+ PGPSecretKey sKey, PGPPublicKey pKey, int flags, long expiry, Passphrase passphrase)
throws IOException, PGPException, SignatureException {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
- passphrase.toCharArray());
+ passphrase.getCharArray());
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
pKey, flags, expiry);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java
index 1ed0a4720..4a920685a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java
@@ -1,7 +1,26 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.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.pgp;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.Date;
@@ -11,19 +30,20 @@ public class PgpSignEncryptInput {
protected boolean mEnableAsciiArmorOutput = false;
protected int mCompressionId = CompressionAlgorithmTags.UNCOMPRESSED;
protected long[] mEncryptionMasterKeyIds = null;
- protected String mSymmetricPassphrase = null;
+ protected Passphrase mSymmetricPassphrase = null;
protected int mSymmetricEncryptionAlgorithm = PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED;
protected long mSignatureMasterKeyId = Constants.key.none;
protected Long mSignatureSubKeyId = null;
protected int mSignatureHashAlgorithm = PgpConstants.OpenKeychainHashAlgorithmTags.USE_PREFERRED;
- protected String mSignaturePassphrase = null;
+ protected Passphrase mSignaturePassphrase = null;
protected long mAdditionalEncryptId = Constants.key.none;
protected byte[] mNfcSignedHash = null;
protected Date mNfcCreationTimestamp = null;
protected boolean mFailOnMissingEncryptionKeyIds = false;
protected String mCharset;
protected boolean mCleartextSignature;
- protected boolean mDetachedSignature;
+ protected boolean mDetachedSignature = false;
+ protected boolean mHiddenRecipients = false;
public String getCharset() {
return mCharset;
@@ -33,7 +53,7 @@ public class PgpSignEncryptInput {
this.mCharset = mCharset;
}
- public boolean ismFailOnMissingEncryptionKeyIds() {
+ public boolean isFailOnMissingEncryptionKeyIds() {
return mFailOnMissingEncryptionKeyIds;
}
@@ -54,11 +74,11 @@ public class PgpSignEncryptInput {
return this;
}
- public String getSignaturePassphrase() {
+ public Passphrase getSignaturePassphrase() {
return mSignaturePassphrase;
}
- public PgpSignEncryptInput setSignaturePassphrase(String signaturePassphrase) {
+ public PgpSignEncryptInput setSignaturePassphrase(Passphrase signaturePassphrase) {
mSignaturePassphrase = signaturePassphrase;
return this;
}
@@ -99,11 +119,11 @@ public class PgpSignEncryptInput {
return this;
}
- public String getSymmetricPassphrase() {
+ public Passphrase getSymmetricPassphrase() {
return mSymmetricPassphrase;
}
- public PgpSignEncryptInput setSymmetricPassphrase(String symmetricPassphrase) {
+ public PgpSignEncryptInput setSymmetricPassphrase(Passphrase symmetricPassphrase) {
mSymmetricPassphrase = symmetricPassphrase;
return this;
}
@@ -126,7 +146,7 @@ public class PgpSignEncryptInput {
return this;
}
- public boolean ismEnableAsciiArmorOutput() {
+ public boolean isEnableAsciiArmorOutput() {
return mEnableAsciiArmorOutput;
}
@@ -172,5 +192,14 @@ public class PgpSignEncryptInput {
public boolean isDetachedSignature() {
return mDetachedSignature;
}
+
+ public PgpSignEncryptInput setHiddenRecipients(boolean hiddenRecipients) {
+ this.mHiddenRecipients = hiddenRecipients;
+ return this;
+ }
+
+ public boolean isHiddenRecipients() {
+ return mHiddenRecipients;
+ }
}
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 81cc2c847..bd3c31d3a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2015 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org>
* Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.com>
*
@@ -60,7 +60,6 @@ import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
-import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicBoolean;
/** This class supports a single, low-level, sign/encrypt operation.
@@ -117,7 +116,8 @@ public class PgpSignEncryptOperation extends BaseOperation {
Log.d(Constants.TAG, "enableSignature:" + enableSignature
+ "\nenableEncryption:" + enableEncryption
+ "\nenableCompression:" + enableCompression
- + "\nenableAsciiArmorOutput:" + input.ismEnableAsciiArmorOutput());
+ + "\nenableAsciiArmorOutput:" + input.isEnableAsciiArmorOutput()
+ + "\nisHiddenRecipients:" + input.isHiddenRecipients());
// add additional key id to encryption ids (mostly to do self-encryption)
if (enableEncryption && input.getAdditionalEncryptId() != Constants.key.none) {
@@ -127,7 +127,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
ArmoredOutputStream armorOut = null;
OutputStream out;
- if (input.ismEnableAsciiArmorOutput()) {
+ if (input.isEnableAsciiArmorOutput()) {
armorOut = new ArmoredOutputStream(outputStream);
if (input.getVersionHeader() != null) {
armorOut.setHeader("Version", input.getVersionHeader());
@@ -243,7 +243,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
log.add(LogType.MSG_PSE_SYMMETRIC, indent);
JcePBEKeyEncryptionMethodGenerator symmetricEncryptionGenerator =
- new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().toCharArray());
+ new JcePBEKeyEncryptionMethodGenerator(input.getSymmetricPassphrase().getCharArray());
cPk.addMethod(symmetricEncryptionGenerator);
} else {
log.add(LogType.MSG_PSE_ASYMMETRIC, indent);
@@ -254,19 +254,19 @@ public class PgpSignEncryptOperation extends BaseOperation {
CanonicalizedPublicKeyRing keyRing = mProviderHelper.getCanonicalizedPublicKeyRing(
KeyRings.buildUnifiedKeyRingUri(id));
CanonicalizedPublicKey key = keyRing.getEncryptionSubKey();
- cPk.addMethod(key.getPubKeyEncryptionGenerator());
+ cPk.addMethod(key.getPubKeyEncryptionGenerator(input.isHiddenRecipients()));
log.add(LogType.MSG_PSE_KEY_OK, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(id));
} catch (PgpKeyNotFoundException e) {
log.add(LogType.MSG_PSE_KEY_WARN, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(id));
- if (input.ismFailOnMissingEncryptionKeyIds()) {
+ if (input.isFailOnMissingEncryptionKeyIds()) {
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
} catch (ProviderHelper.NotFoundException e) {
log.add(LogType.MSG_PSE_KEY_UNKNOWN, indent + 1,
KeyFormattingUtils.convertKeyIdToHex(id));
- if (input.ismFailOnMissingEncryptionKeyIds()) {
+ if (input.isFailOnMissingEncryptionKeyIds()) {
return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log);
}
}
@@ -280,7 +280,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
updateProgress(R.string.progress_preparing_signature, 4, 100);
try {
- boolean cleartext = input.isCleartextSignature() && input.ismEnableAsciiArmorOutput() && !enableEncryption;
+ boolean cleartext = input.isCleartextSignature() && input.isEnableAsciiArmorOutput() && !enableEncryption;
signatureGenerator = signingKey.getSignatureGenerator(
input.getSignatureHashAlgorithm(), cleartext, input.getNfcSignedHash(), input.getNfcCreationTimestamp());
} catch (PgpGeneralException e) {
@@ -358,7 +358,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
literalGen.close();
indent -= 1;
- } else if (enableSignature && input.isCleartextSignature() && input.ismEnableAsciiArmorOutput()) {
+ } else if (enableSignature && input.isCleartextSignature() && input.isEnableAsciiArmorOutput()) {
/* cleartext signature: sign-only of ascii text */
updateProgress(R.string.progress_signing, 8, 100);
@@ -404,7 +404,7 @@ public class PgpSignEncryptOperation extends BaseOperation {
// handle output stream separately for detached signatures
detachedByteOut = new ByteArrayOutputStream();
OutputStream detachedOut = detachedByteOut;
- if (input.ismEnableAsciiArmorOutput()) {
+ if (input.isEnableAsciiArmorOutput()) {
detachedArmorOut = new ArmoredOutputStream(detachedOut);
if (input.getVersionHeader() != null) {
detachedArmorOut.setHeader("Version", input.getVersionHeader());
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
index a4ed33397..975548c95 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java
@@ -1,9 +1,29 @@
+/*
+ * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2014 Vincent Breitmoser <v.breitmoser@mugenguild.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.pgp;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -39,12 +59,12 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
mEnableAsciiArmorOutput = src.readInt() == 1;
mCompressionId = src.readInt();
mEncryptionMasterKeyIds = src.createLongArray();
- mSymmetricPassphrase = src.readString();
+ mSymmetricPassphrase = src.readParcelable(Passphrase.class.getClassLoader());
mSymmetricEncryptionAlgorithm = src.readInt();
mSignatureMasterKeyId = src.readLong();
mSignatureSubKeyId = src.readInt() == 1 ? src.readLong() : null;
mSignatureHashAlgorithm = src.readInt();
- mSignaturePassphrase = src.readString();
+ mSignaturePassphrase = src.readParcelable(Passphrase.class.getClassLoader());
mAdditionalEncryptId = src.readLong();
mNfcSignedHash = src.createByteArray();
mNfcCreationTimestamp = src.readInt() == 1 ? new Date(src.readLong()) : null;
@@ -52,6 +72,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
mCharset = src.readString();
mCleartextSignature = src.readInt() == 1;
mDetachedSignature = src.readInt() == 1;
+ mHiddenRecipients = src.readInt() == 1;
mInputUris = src.createTypedArrayList(Uri.CREATOR);
mOutputUris = src.createTypedArrayList(Uri.CREATOR);
@@ -93,7 +114,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
dest.writeInt(mEnableAsciiArmorOutput ? 1 : 0);
dest.writeInt(mCompressionId);
dest.writeLongArray(mEncryptionMasterKeyIds);
- dest.writeString(mSymmetricPassphrase);
+ dest.writeParcelable(mSymmetricPassphrase, flags);
dest.writeInt(mSymmetricEncryptionAlgorithm);
dest.writeLong(mSignatureMasterKeyId);
if (mSignatureSubKeyId != null) {
@@ -103,7 +124,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
dest.writeInt(0);
}
dest.writeInt(mSignatureHashAlgorithm);
- dest.writeString(mSignaturePassphrase);
+ dest.writeParcelable(mSignaturePassphrase, flags);
dest.writeLong(mAdditionalEncryptId);
dest.writeByteArray(mNfcSignedHash);
if (mNfcCreationTimestamp != null) {
@@ -116,6 +137,7 @@ public class SignEncryptParcel extends PgpSignEncryptInput implements Parcelable
dest.writeString(mCharset);
dest.writeInt(mCleartextSignature ? 1 : 0);
dest.writeInt(mDetachedSignature ? 1 : 0);
+ dest.writeInt(mHiddenRecipients ? 1 : 0);
dest.writeTypedList(mInputUris);
dest.writeTypedList(mOutputUris);
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 a4bc95602..bd2866985 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
@@ -54,6 +54,7 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.IOException;
import java.io.InputStream;
@@ -179,7 +180,7 @@ public class OpenPgpService extends RemoteService {
return result;
}
- private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, String pin, byte[] hashToSign, int hashAlgo) {
+ private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
@@ -195,7 +196,7 @@ public class OpenPgpService extends RemoteService {
PendingIntent.FLAG_CANCEL_CURRENT);
}
- private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, String pin, byte[] encryptedSessionKey) {
+ private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(getBaseContext(), NfcActivity.class);
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
@@ -239,6 +240,11 @@ public class OpenPgpService extends RemoteService {
try {
boolean asciiArmor = cleartextSign || data.getBooleanExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
+ Passphrase passphrase = null;
+ if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) {
+ passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
+ }
+
byte[] nfcSignedHash = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_SIGNED_HASH);
if (nfcSignedHash != null) {
Log.d(Constants.TAG, "nfcSignedHash:" + Hex.toHexString(nfcSignedHash));
@@ -277,6 +283,7 @@ public class OpenPgpService extends RemoteService {
// sign-only
PgpSignEncryptInput pseInput = new PgpSignEncryptInput()
+ .setSignaturePassphrase(passphrase)
.setEnableAsciiArmorOutput(asciiArmor)
.setCleartextSignature(cleartextSign)
.setDetachedSignature(!cleartextSign)
@@ -365,6 +372,11 @@ public class OpenPgpService extends RemoteService {
compressionId = CompressionAlgorithmTags.UNCOMPRESSED;
}
+ Passphrase passphrase = null;
+ if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) {
+ passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
+ }
+
// first try to get key ids from non-ambiguous key id extra
long[] keyIds = data.getLongArrayExtra(OpenPgpApi.EXTRA_KEY_IDS);
if (keyIds == null) {
@@ -390,7 +402,8 @@ public class OpenPgpService extends RemoteService {
InputData inputData = new InputData(is, inputLength, originalFilename);
PgpSignEncryptInput pseInput = new PgpSignEncryptInput();
- pseInput.setEnableAsciiArmorOutput(asciiArmor)
+ pseInput.setSignaturePassphrase(passphrase)
+ .setEnableAsciiArmorOutput(asciiArmor)
.setVersionHeader(null)
.setCompressionId(compressionId)
.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED)
@@ -498,6 +511,11 @@ public class OpenPgpService extends RemoteService {
os = new ParcelFileDescriptor.AutoCloseOutputStream(output);
}
+ Passphrase passphrase = null;
+ if (data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE) != null) {
+ passphrase = new Passphrase(data.getCharArrayExtra(OpenPgpApi.EXTRA_PASSPHRASE));
+ }
+
String currentPkg = getCurrentCallingPackage();
Set<Long> allowedKeyIds;
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) {
@@ -508,7 +526,6 @@ public class OpenPgpService extends RemoteService {
KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg));
}
- String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE);
long inputLength = is.available();
InputData inputData = new InputData(is, inputLength);
@@ -554,15 +571,16 @@ public class OpenPgpService extends RemoteService {
}
} else if (pgpResult.success()) {
Intent result = new Intent();
- int resultType = OpenPgpApi.RESULT_TYPE_UNENCRYPTED_UNSIGNED;
OpenPgpSignatureResult signatureResult = pgpResult.getSignatureResult();
+ // TODO: currently RESULT_TYPE_UNENCRYPTED_UNSIGNED is never returned
+ // instead an error is returned when no pgp data has been found
+ int resultType = OpenPgpApi.RESULT_TYPE_UNENCRYPTED_UNSIGNED;
if (signatureResult != null) {
resultType |= OpenPgpApi.RESULT_TYPE_SIGNED;
if (!signatureResult.isSignatureOnly()) {
resultType |= OpenPgpApi.RESULT_TYPE_ENCRYPTED;
}
- result.putExtra(OpenPgpApi.RESULT_TYPE, resultType);
result.putExtra(OpenPgpApi.RESULT_SIGNATURE, signatureResult);
@@ -582,7 +600,10 @@ public class OpenPgpService extends RemoteService {
// If signature key is known, return PendingIntent to show key
result.putExtra(OpenPgpApi.RESULT_INTENT, getShowKeyPendingIntent(signatureResult.getKeyId()));
}
+ } else {
+ resultType |= OpenPgpApi.RESULT_TYPE_ENCRYPTED;
}
+ result.putExtra(OpenPgpApi.RESULT_TYPE, resultType);
if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) >= 4) {
OpenPgpMetadata metadata = pgpResult.getDecryptMetadata();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
index 4bb64bcaa..81181d61d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java
@@ -92,11 +92,11 @@ public class AccountSettingsFragment extends Fragment {
}
private void createKey() {
- String[] userId = KeyRing.splitUserId(mAccSettings.getAccountName());
+ KeyRing.UserId userId = KeyRing.splitUserId(mAccSettings.getAccountName());
Intent intent = new Intent(getActivity(), CreateKeyActivity.class);
- intent.putExtra(CreateKeyActivity.EXTRA_NAME, userId[0]);
- intent.putExtra(CreateKeyActivity.EXTRA_EMAIL, userId[1]);
+ intent.putExtra(CreateKeyActivity.EXTRA_NAME, userId.name);
+ intent.putExtra(CreateKeyActivity.EXTRA_EMAIL, userId.email);
startActivityForResult(intent, REQUEST_CODE_CREATE_KEY);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
index 2c5c78161..e8c3e4511 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java
@@ -186,7 +186,7 @@ public class RemoteServiceActivity extends BaseActivity {
// user needs to select a key if it has explicitly requested (None is only allowed for new accounts)
if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) {
- Notify.showNotify(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR);
+ Notify.create(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR).show();
} else {
if (mUpdateExistingAccount) {
Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
index 5ec47f4c9..98a44466d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java
@@ -42,9 +42,11 @@ public class SelectSignKeyIdActivity extends BaseActivity {
private Uri mAppUri;
private String mPreferredUserId;
+ private Intent mData;
private SelectSignKeyIdListFragment mListFragment;
private TextView mActionCreateKey;
+ private TextView mNone;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -67,27 +69,38 @@ public class SelectSignKeyIdActivity extends BaseActivity {
createKey(mPreferredUserId);
}
});
+ mNone = (TextView) findViewById(R.id.api_select_sign_key_none);
+ mNone.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 0 is "none"
+ mData.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, 0);
+
+ setResult(Activity.RESULT_OK, mData);
+ finish();
+ }
+ });
Intent intent = getIntent();
mAppUri = intent.getData();
mPreferredUserId = intent.getStringExtra(EXTRA_USER_ID);
- Intent data = intent.getParcelableExtra(EXTRA_DATA);
+ mData = intent.getParcelableExtra(EXTRA_DATA);
if (mAppUri == null) {
Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!");
finish();
return;
} else {
Log.d(Constants.TAG, "uri: " + mAppUri);
- startListFragments(savedInstanceState, mAppUri, data);
+ startListFragments(savedInstanceState, mAppUri, mData);
}
}
private void createKey(String userId) {
- String[] userIdSplit = KeyRing.splitUserId(userId);
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
Intent intent = new Intent(this, CreateKeyActivity.class);
- intent.putExtra(CreateKeyActivity.EXTRA_NAME, userIdSplit[0]);
- intent.putExtra(CreateKeyActivity.EXTRA_EMAIL, userIdSplit[1]);
+ intent.putExtra(CreateKeyActivity.EXTRA_NAME, userIdSplit.name);
+ intent.putExtra(CreateKeyActivity.EXTRA_EMAIL, userIdSplit.email);
startActivityForResult(intent, REQUEST_CODE_CREATE_KEY);
}
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 95bd0de35..01b1925a0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java
@@ -73,6 +73,7 @@ import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -289,7 +290,7 @@ public class KeychainIntentService extends IntentService implements Progressable
try {
/* Input */
- String passphrase = data.getString(DECRYPT_PASSPHRASE);
+ Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
InputData inputData = createDecryptInputData(data);
@@ -419,7 +420,7 @@ public class KeychainIntentService extends IntentService implements Progressable
try {
/* Input */
- String passphrase = data.getString(DECRYPT_PASSPHRASE);
+ Passphrase passphrase = data.getParcelable(DECRYPT_PASSPHRASE);
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
InputData inputData = createDecryptInputData(data);
@@ -477,7 +478,7 @@ public class KeychainIntentService extends IntentService implements Progressable
// Input
SaveKeyringParcel saveParcel = data.getParcelable(EDIT_KEYRING_PARCEL);
- String passphrase = data.getString(EDIT_KEYRING_PASSPHRASE);
+ Passphrase passphrase = data.getParcelable(EDIT_KEYRING_PASSPHRASE);
// Operation
EditKeyOperation op = new EditKeyOperation(this, providerHelper, this, mActionCanceled);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
index bd047518d..91a079a5d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java
@@ -129,9 +129,9 @@ public class KeychainIntentServiceHandler extends Handler {
// show error from service
if (data.containsKey(DATA_ERROR)) {
- Notify.showNotify(mActivity,
+ Notify.create(mActivity,
mActivity.getString(R.string.error_message, data.getString(DATA_ERROR)),
- Notify.Style.ERROR);
+ Notify.Style.ERROR).show();
}
break;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
index 57881f8ee..ee481ad31 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java
@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.Date;
@@ -121,7 +122,7 @@ public class PassphraseCacheService extends Service {
* new events to the alarm manager for new passphrases to let them timeout in the future.
*/
public static void addCachedPassphrase(Context context, long masterKeyId, long subKeyId,
- String passphrase,
+ Passphrase passphrase,
String primaryUserId) {
Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + masterKeyId);
@@ -143,7 +144,7 @@ public class PassphraseCacheService extends Service {
* @return passphrase or null (if no passphrase is cached for this keyId)
*/
- public static String getCachedPassphrase(Context context, long masterKeyId, long subKeyId) throws KeyNotFoundException {
+ public static Passphrase getCachedPassphrase(Context context, long masterKeyId, long subKeyId) throws KeyNotFoundException {
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() for masterKeyId "
+ masterKeyId + ", subKeyId " + subKeyId);
@@ -190,7 +191,9 @@ public class PassphraseCacheService extends Service {
switch (returnMessage.what) {
case MSG_PASSPHRASE_CACHE_GET_OKAY:
- return returnMessage.getData().getString(EXTRA_PASSPHRASE);
+ Bundle returnData = returnMessage.getData();
+ returnData.setClassLoader(context.getClassLoader());
+ return returnData.getParcelable(EXTRA_PASSPHRASE);
case MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND:
throw new KeyNotFoundException();
default:
@@ -202,11 +205,11 @@ public class PassphraseCacheService extends Service {
/**
* Internal implementation to get cached passphrase.
*/
- private String getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException {
+ private Passphrase getCachedPassphraseImpl(long masterKeyId, long subKeyId) throws ProviderHelper.NotFoundException {
// passphrase for symmetric encryption?
if (masterKeyId == Constants.key.symmetric) {
Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption");
- String cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric).getPassphrase();
+ Passphrase cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric).getPassphrase();
if (cachedPassphrase == null) {
return null;
}
@@ -232,13 +235,13 @@ public class PassphraseCacheService extends Service {
case DIVERT_TO_CARD:
if (Preferences.getPreferences(this).useDefaultYubikeyPin()) {
Log.d(Constants.TAG, "PassphraseCacheService: Using default Yubikey PIN: 123456");
- return "123456"; // default Yubikey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
+ return new Passphrase("123456"); // default Yubikey PIN, see http://www.yubico.com/2012/12/yubikey-neo-openpgp/
} else {
Log.d(Constants.TAG, "PassphraseCacheService: NOT using default Yubikey PIN");
break;
}
case PASSPHRASE_EMPTY:
- return "";
+ return new Passphrase("");
case UNAVAILABLE:
throw new ProviderHelper.NotFoundException("secret key for this subkey is not available");
case GNU_DUMMY:
@@ -331,7 +334,7 @@ public class PassphraseCacheService extends Service {
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
- String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE);
+ Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE);
String primaryUserID = intent.getStringExtra(EXTRA_USER_ID);
Log.d(Constants.TAG,
@@ -373,10 +376,10 @@ public class PassphraseCacheService extends Service {
Log.e(Constants.TAG, "PassphraseCacheService: Bad request, missing masterKeyId or subKeyId!");
msg.what = MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND;
} else {
- String passphrase = getCachedPassphraseImpl(masterKeyId, subKeyId);
+ Passphrase passphrase = getCachedPassphraseImpl(masterKeyId, subKeyId);
msg.what = MSG_PASSPHRASE_CACHE_GET_OKAY;
Bundle bundle = new Bundle();
- bundle.putString(EXTRA_PASSPHRASE, passphrase);
+ bundle.putParcelable(EXTRA_PASSPHRASE, passphrase);
msg.setData(bundle);
}
} catch (ProviderHelper.NotFoundException e) {
@@ -412,7 +415,10 @@ public class PassphraseCacheService extends Service {
* Called when one specific passphrase for keyId timed out
*/
private void timeout(Context context, long keyId) {
- // remove passphrase corresponding to keyId from memory
+ CachedPassphrase cPass = mPassphraseCache.get(keyId);
+ // clean internal char[] from memory!
+ cPass.getPassphrase().removeFromMemory();
+ // remove passphrase object
mPassphraseCache.remove(keyId);
Log.d(Constants.TAG, "PassphraseCacheService Timeout of keyId " + keyId + ", removed from memory!");
@@ -517,9 +523,9 @@ public class PassphraseCacheService extends Service {
public class CachedPassphrase {
private String primaryUserID;
- private String passphrase;
+ private Passphrase passphrase;
- public CachedPassphrase(String passphrase, String primaryUserID) {
+ public CachedPassphrase(Passphrase passphrase, String primaryUserID) {
setPassphrase(passphrase);
setPrimaryUserID(primaryUserID);
}
@@ -528,7 +534,7 @@ public class PassphraseCacheService extends Service {
return primaryUserID;
}
- public String getPassphrase() {
+ public Passphrase getPassphrase() {
return passphrase;
}
@@ -536,7 +542,7 @@ public class PassphraseCacheService extends Service {
this.primaryUserID = primaryUserID;
}
- public void setPassphrase(String passphrase) {
+ public void setPassphrase(Passphrase passphrase) {
this.passphrase = passphrase;
}
}
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 e2d0c03c9..9fd278c13 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java
@@ -22,6 +22,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import org.sufficientlysecure.keychain.pgp.WrappedUserAttribute;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.Serializable;
import java.util.ArrayList;
@@ -296,33 +297,30 @@ public class SaveKeyringParcel implements Parcelable {
public static class ChangeUnlockParcel implements Parcelable {
// The new passphrase to use
- public final String mNewPassphrase;
+ public final Passphrase mNewPassphrase;
// A new pin to use. Must only contain [0-9]+
- public final String mNewPin;
+ public final Passphrase mNewPin;
- public ChangeUnlockParcel(String newPassphrase) {
+ public ChangeUnlockParcel(Passphrase newPassphrase) {
this(newPassphrase, null);
}
- public ChangeUnlockParcel(String newPassphrase, String newPin) {
+ public ChangeUnlockParcel(Passphrase newPassphrase, Passphrase newPin) {
if (newPassphrase == null && newPin == null) {
throw new RuntimeException("Cannot set both passphrase and pin. THIS IS A BUG!");
}
- if (newPin != null && !newPin.matches("[0-9]+")) {
- throw new RuntimeException("Pin must be numeric digits only. THIS IS A BUG!");
- }
mNewPassphrase = newPassphrase;
mNewPin = newPin;
}
public ChangeUnlockParcel(Parcel source) {
- mNewPassphrase = source.readString();
- mNewPin = source.readString();
+ mNewPassphrase = source.readParcelable(Passphrase.class.getClassLoader());
+ mNewPin = source.readParcelable(Passphrase.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel destination, int flags) {
- destination.writeString(mNewPassphrase);
- destination.writeString(mNewPin);
+ destination.writeParcelable(mNewPassphrase, flags);
+ destination.writeParcelable(mNewPin, flags);
}
@Override
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 a2d4a3d7c..b3738851c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java
@@ -62,6 +62,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.lang.reflect.Method;
@@ -168,8 +169,8 @@ public class CertifyKeyFragment extends LoaderFragment
@Override
public void onClick(View v) {
if (mSignMasterKeyId == Constants.key.none) {
- Notify.showNotify(getActivity(), getString(R.string.select_key_to_certify),
- Notify.Style.ERROR);
+ Notify.create(getActivity(), getString(R.string.select_key_to_certify),
+ Notify.Style.ERROR).show();
} else {
initiateCertifying();
}
@@ -246,14 +247,14 @@ public class CertifyKeyFragment extends LoaderFragment
while (!data.isAfterLast()) {
long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
String userId = data.getString(INDEX_USER_ID);
- String[] pieces = KeyRing.splitUserId(userId);
+ KeyRing.UserId pieces = KeyRing.splitUserId(userId);
// Two cases:
boolean grouped = masterKeyId == lastMasterKeyId;
- boolean subGrouped = data.isFirst() || grouped && lastName.equals(pieces[0]);
+ boolean subGrouped = data.isFirst() || grouped && lastName.equals(pieces.name);
// Remember for next loop
- lastName = pieces[0];
+ lastName = pieces.name;
Log.d(Constants.TAG, Long.toString(masterKeyId, 16) + (grouped ? "grouped" : "not grouped"));
@@ -318,7 +319,7 @@ public class CertifyKeyFragment extends LoaderFragment
*/
private void initiateCertifying() {
// get the user's passphrase for this key (if required)
- String passphrase;
+ Passphrase passphrase;
try {
passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSignMasterKeyId, mSignMasterKeyId);
} catch (PassphraseCacheService.KeyNotFoundException e) {
@@ -341,7 +342,6 @@ public class CertifyKeyFragment extends LoaderFragment
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- String passphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
startCertifying();
}
return;
@@ -360,8 +360,8 @@ public class CertifyKeyFragment extends LoaderFragment
// Bail out if there is not at least one user id selected
ArrayList<CertifyAction> certifyActions = mUserIdsAdapter.getSelectedCertifyActions();
if (certifyActions.isEmpty()) {
- Notify.showNotify(getActivity(), "No identities selected!",
- Notify.Style.ERROR);
+ Notify.create(getActivity(), "No identities selected!",
+ Notify.Style.ERROR).show();
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
index 2da5511b8..ab76f693e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -20,31 +20,74 @@ package org.sufficientlysecure.keychain.ui;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
+import android.view.View;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
+import java.util.ArrayList;
public class CreateKeyActivity extends BaseActivity {
public static final String EXTRA_NAME = "name";
public static final String EXTRA_EMAIL = "email";
+ public static final String EXTRA_FIRST_TIME = "first_time";
+ public static final String EXTRA_ADDITIONAL_EMAILS = "additional_emails";
+ public static final String EXTRA_PASSPHRASE = "passphrase";
- public static enum FragAction {
- START,
- TO_RIGHT,
- TO_LEFT
- }
+ public static final String FRAGMENT_TAG = "currentFragment";
+
+ String mName;
+ String mEmail;
+ ArrayList<String> mAdditionalEmails;
+ Passphrase mPassphrase;
+ boolean mFirstTime;
+
+ Fragment mCurrentFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // pass extras into fragment
- CreateKeyNameFragment frag =
- CreateKeyNameFragment.newInstance(
- getIntent().getStringExtra(EXTRA_NAME),
- getIntent().getStringExtra(EXTRA_EMAIL)
- );
- loadFragment(null, frag, FragAction.START);
+ // Check whether we're recreating a previously destroyed instance
+ if (savedInstanceState != null) {
+ // Restore value of members from saved state
+ mName = savedInstanceState.getString(EXTRA_NAME);
+ mEmail = savedInstanceState.getString(EXTRA_EMAIL);
+ mAdditionalEmails = savedInstanceState.getStringArrayList(EXTRA_ADDITIONAL_EMAILS);
+ mPassphrase = savedInstanceState.getParcelable(EXTRA_PASSPHRASE);
+ mFirstTime = savedInstanceState.getBoolean(EXTRA_FIRST_TIME);
+
+ mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
+ } else {
+ // Initialize members with default values for a new instance
+ mName = getIntent().getStringExtra(EXTRA_NAME);
+ mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
+ mFirstTime = getIntent().getBooleanExtra(EXTRA_FIRST_TIME, false);
+
+ // Start with first fragment of wizard
+ CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance();
+ loadFragment(frag, FragAction.START);
+ }
+
+ if (mFirstTime) {
+ setTitle(R.string.app_name);
+ setActionBarIcon(R.drawable.ic_launcher);
+ mToolbar.setNavigationOnClickListener(null);
+ } else {
+ setTitle(R.string.title_manage_my_keys);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ outState.putString(EXTRA_NAME, mName);
+ outState.putString(EXTRA_EMAIL, mEmail);
+ outState.putStringArrayList(EXTRA_ADDITIONAL_EMAILS, mAdditionalEmails);
+ outState.putParcelable(EXTRA_PASSPHRASE, mPassphrase);
+ outState.putBoolean(EXTRA_FIRST_TIME, mFirstTime);
}
@Override
@@ -52,23 +95,23 @@ public class CreateKeyActivity extends BaseActivity {
setContentView(R.layout.create_key_activity);
}
- public void loadFragment(Bundle savedInstanceState, Fragment fragment, FragAction action) {
- // However, if we're being restored from a previous state,
- // then we don't need to do anything and should return or else
- // we could end up with overlapping fragments.
- if (savedInstanceState != null) {
- return;
- }
+ public static enum FragAction {
+ START,
+ TO_RIGHT,
+ TO_LEFT
+ }
+
+ public void loadFragment(Fragment fragment, FragAction action) {
+ mCurrentFragment = fragment;
// Add the fragment to the 'fragment_container' FrameLayout
- // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch (action) {
case START:
transaction.setCustomAnimations(0, 0);
- transaction.replace(R.id.create_key_fragment_container, fragment)
- .commitAllowingStateLoss();
+ transaction.replace(R.id.create_key_fragment_container, fragment, FRAGMENT_TAG)
+ .commit();
break;
case TO_LEFT:
getSupportFragmentManager().popBackStackImmediate();
@@ -77,8 +120,8 @@ public class CreateKeyActivity extends BaseActivity {
transaction.setCustomAnimations(R.anim.frag_slide_in_from_right, R.anim.frag_slide_out_to_left,
R.anim.frag_slide_in_from_left, R.anim.frag_slide_out_to_right);
transaction.addToBackStack(null);
- transaction.replace(R.id.create_key_fragment_container, fragment)
- .commitAllowingStateLoss();
+ transaction.replace(R.id.create_key_fragment_container, fragment, FRAGMENT_TAG)
+ .commit();
break;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
index 66424e012..2e8a1f370 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java
@@ -46,16 +46,12 @@ import java.util.List;
public class CreateKeyEmailFragment extends Fragment {
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
-
CreateKeyActivity mCreateKeyActivity;
EmailEditText mEmailEdit;
RecyclerView mEmailsRecyclerView;
View mBackButton;
View mNextButton;
- String mName;
ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels;
EmailAdapter mEmailAdapter;
@@ -63,13 +59,10 @@ public class CreateKeyEmailFragment extends Fragment {
/**
* Creates new instance of this fragment
*/
- public static CreateKeyEmailFragment newInstance(String name, String email) {
+ public static CreateKeyEmailFragment newInstance() {
CreateKeyEmailFragment frag = new CreateKeyEmailFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
-
frag.setArguments(args);
return frag;
@@ -85,7 +78,7 @@ public class CreateKeyEmailFragment extends Fragment {
*/
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
boolean output = true;
- if (editText.getText().toString().length() == 0) {
+ if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
@@ -106,31 +99,33 @@ public class CreateKeyEmailFragment extends Fragment {
mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails);
// initial values
- mName = getArguments().getString(ARG_NAME);
- String email = getArguments().getString(ARG_EMAIL);
- mEmailEdit.setText(email);
+ mEmailEdit.setText(mCreateKeyActivity.mEmail);
// focus empty edit fields
- if (email == null) {
+ if (mCreateKeyActivity.mEmail == null) {
mEmailEdit.requestFocus();
}
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
});
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- createKeyCheck();
+ nextClicked();
}
});
mEmailsRecyclerView.setHasFixedSize(true);
mEmailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mEmailsRecyclerView.setItemAnimator(new DefaultItemAnimator());
+ // initial values
mAdditionalEmailModels = new ArrayList<>();
+ if (mCreateKeyActivity.mAdditionalEmails != null) {
+ setAdditionalEmails(mCreateKeyActivity.mAdditionalEmails);
+ }
mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -171,25 +166,38 @@ public class CreateKeyEmailFragment extends Fragment {
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
- private void createKeyCheck() {
+ private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mEmailEdit)) {
+ // save state
+ mCreateKeyActivity.mEmail = mEmailEdit.getText().toString();
+ mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
- ArrayList<String> emails = new ArrayList<>();
- for (EmailAdapter.ViewModel holder : mAdditionalEmailModels) {
- emails.add(holder.toString());
- }
+ CreateKeyPassphraseFragment frag = CreateKeyPassphraseFragment.newInstance();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
+ }
+ }
- CreateKeyPassphraseFragment frag =
- CreateKeyPassphraseFragment.newInstance(
- mName,
- mEmailEdit.getText().toString(),
- emails
- );
+ private ArrayList<String> getAdditionalEmails() {
+ ArrayList<String> emails = new ArrayList<>();
+ for (EmailAdapter.ViewModel holder : mAdditionalEmailModels) {
+ emails.add(holder.toString());
+ }
+ return emails;
+ }
- mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
+ private void setAdditionalEmails(ArrayList<String> emails) {
+ for (String email : emails) {
+ mAdditionalEmailModels.add(new EmailAdapter.ViewModel(email));
}
}
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ // save state in activity
+ mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
+ }
+
public static class EmailAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<ViewModel> mDataset;
private View.OnClickListener mFooterOnClickListener;
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 ae42c891d..cbe3eecd4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -64,32 +65,15 @@ public class CreateKeyFinalFragment extends Fragment {
TextView mEditText;
View mEditButton;
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
- public static final String ARG_ADDITIONAL_EMAILS = "emails";
- public static final String ARG_PASSPHRASE = "passphrase";
-
- String mName;
- String mEmail;
- ArrayList<String> mAdditionalEmails;
- String mPassphrase;
-
SaveKeyringParcel mSaveKeyringParcel;
/**
* Creates new instance of this fragment
*/
- public static CreateKeyFinalFragment newInstance(String name, String email,
- ArrayList<String> additionalEmails,
- String passphrase) {
+ public static CreateKeyFinalFragment newInstance() {
CreateKeyFinalFragment frag = new CreateKeyFinalFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
- args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
- args.putString(ARG_PASSPHRASE, passphrase);
-
frag.setArguments(args);
return frag;
@@ -107,17 +91,11 @@ public class CreateKeyFinalFragment extends Fragment {
mEditText = (TextView) view.findViewById(R.id.create_key_edit_text);
mEditButton = view.findViewById(R.id.create_key_edit_button);
- // get args
- mName = getArguments().getString(ARG_NAME);
- mEmail = getArguments().getString(ARG_EMAIL);
- mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
- mPassphrase = getArguments().getString(ARG_PASSPHRASE);
-
// set values
- mNameEdit.setText(mName);
- if (mAdditionalEmails != null && mAdditionalEmails.size() > 0) {
- String emailText = mEmail + ", ";
- Iterator<?> it = mAdditionalEmails.iterator();
+ mNameEdit.setText(mCreateKeyActivity.mName);
+ if (mCreateKeyActivity.mAdditionalEmails != null && mCreateKeyActivity.mAdditionalEmails.size() > 0) {
+ String emailText = mCreateKeyActivity.mEmail + ", ";
+ Iterator<?> it = mCreateKeyActivity.mAdditionalEmails.iterator();
while (it.hasNext()) {
Object next = it.next();
emailText += next;
@@ -127,7 +105,7 @@ public class CreateKeyFinalFragment extends Fragment {
}
mEmailEdit.setText(emailText);
} else {
- mEmailEdit.setText(mEmail);
+ mEmailEdit.setText(mCreateKeyActivity.mEmail);
}
mCreateButton.setOnClickListener(new View.OnClickListener() {
@@ -140,7 +118,7 @@ public class CreateKeyFinalFragment extends Fragment {
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
});
@@ -157,6 +135,12 @@ public class CreateKeyFinalFragment extends Fragment {
}
@Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCreateKeyActivity = (CreateKeyActivity) getActivity();
+ }
+
+ @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_EDIT_KEY: {
@@ -186,17 +170,22 @@ public class CreateKeyFinalFragment extends Fragment {
Algorithm.RSA, 4096, null, KeyFlags.SIGN_DATA, 0L));
mSaveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
Algorithm.RSA, 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
- String userId = KeyRing.createUserId(mName, mEmail, null);
+ String userId = KeyRing.createUserId(
+ new KeyRing.UserId(mCreateKeyActivity.mName, mCreateKeyActivity.mEmail, null)
+ );
mSaveKeyringParcel.mAddUserIds.add(userId);
mSaveKeyringParcel.mChangePrimaryUserId = userId;
- if (mAdditionalEmails != null && mAdditionalEmails.size() > 0) {
- for (String email : mAdditionalEmails) {
- String thisUserId = KeyRing.createUserId(mName, email, null);
+ if (mCreateKeyActivity.mAdditionalEmails != null
+ && mCreateKeyActivity.mAdditionalEmails.size() > 0) {
+ for (String email : mCreateKeyActivity.mAdditionalEmails) {
+ String thisUserId = KeyRing.createUserId(
+ new KeyRing.UserId(mCreateKeyActivity.mName, email, null)
+ );
mSaveKeyringParcel.mAddUserIds.add(thisUserId);
}
}
- mSaveKeyringParcel.mNewUnlock = mPassphrase != null
- ? new ChangeUnlockParcel(mPassphrase, null)
+ mSaveKeyringParcel.mNewUnlock = mCreateKeyActivity.mPassphrase != null
+ ? new ChangeUnlockParcel(mCreateKeyActivity.mPassphrase, null)
: null;
}
}
@@ -288,8 +277,8 @@ public class CreateKeyFinalFragment extends Fragment {
// TODO: upload operation needs a result!
// TODO: then combine these results
//if (result.getResult() == OperationResultParcel.RESULT_OK) {
- //Notify.showNotify(getActivity(), R.string.key_send_success,
- //Notify.Style.INFO);
+ //Notify.create(getActivity(), R.string.key_send_success,
+ //Notify.Style.OK).show();
Intent data = new Intent();
data.putExtra(OperationResult.EXTRA_RESULT, saveKeyResult);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java
index 50a3bd655..7480367bb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java
@@ -24,34 +24,26 @@ import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
-import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
import org.sufficientlysecure.keychain.ui.widget.NameEditText;
public class CreateKeyNameFragment extends Fragment {
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
-
CreateKeyActivity mCreateKeyActivity;
NameEditText mNameEdit;
+ View mBackButton;
View mNextButton;
- String mEmail;
-
/**
* Creates new instance of this fragment
*/
- public static CreateKeyNameFragment newInstance(String name, String email) {
+ public static CreateKeyNameFragment newInstance() {
CreateKeyNameFragment frag = new CreateKeyNameFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
frag.setArguments(args);
@@ -68,7 +60,7 @@ public class CreateKeyNameFragment extends Fragment {
*/
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
boolean output = true;
- if (editText.getText().toString().length() == 0) {
+ if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
@@ -79,39 +71,31 @@ public class CreateKeyNameFragment extends Fragment {
return output;
}
- private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
- boolean output = true;
- if (!editText1.getText().toString().equals(editText2.getText().toString())) {
- editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
- editText2.requestFocus();
- output = false;
- } else {
- editText2.setError(null);
- }
-
- return output;
- }
-
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.create_key_name_fragment, container, false);
mNameEdit = (NameEditText) view.findViewById(R.id.create_key_name);
+ mBackButton = view.findViewById(R.id.create_key_back_button);
mNextButton = view.findViewById(R.id.create_key_next_button);
// initial values
- String name = getArguments().getString(ARG_NAME);
- mEmail = getArguments().getString(ARG_EMAIL);
- mNameEdit.setText(name);
+ mNameEdit.setText(mCreateKeyActivity.mName);
// focus empty edit fields
- if (name == null) {
+ if (mCreateKeyActivity.mName == null) {
mNameEdit.requestFocus();
}
+ mBackButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
+ }
+ });
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- createKeyCheck();
+ nextClicked();
}
});
@@ -124,16 +108,13 @@ public class CreateKeyNameFragment extends Fragment {
mCreateKeyActivity = (CreateKeyActivity) getActivity();
}
- private void createKeyCheck() {
+ private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mNameEdit)) {
+ // save state
+ mCreateKeyActivity.mName = mNameEdit.getText().toString();
- CreateKeyEmailFragment frag =
- CreateKeyEmailFragment.newInstance(
- mNameEdit.getText().toString(),
- mEmail
- );
-
- mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
+ CreateKeyEmailFragment frag = CreateKeyEmailFragment.newInstance();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
index 055ea608b..32173edf7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java
@@ -21,6 +21,7 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
+import android.text.Editable;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
@@ -34,20 +35,13 @@ import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.ArrayList;
+import java.util.Arrays;
public class CreateKeyPassphraseFragment extends Fragment {
- public static final String ARG_NAME = "name";
- public static final String ARG_EMAIL = "email";
- public static final String ARG_ADDITIONAL_EMAILS = "emails";
-
- // model
- String mName;
- String mEmail;
- ArrayList<String> mAdditionalEmails;
-
// view
CreateKeyActivity mCreateKeyActivity;
PassphraseEditText mPassphraseEdit;
@@ -59,15 +53,10 @@ public class CreateKeyPassphraseFragment extends Fragment {
/**
* Creates new instance of this fragment
*/
- public static CreateKeyPassphraseFragment newInstance(String name, String email,
- ArrayList<String> additionalEmails) {
+ public static CreateKeyPassphraseFragment newInstance() {
CreateKeyPassphraseFragment frag = new CreateKeyPassphraseFragment();
Bundle args = new Bundle();
- args.putString(ARG_NAME, name);
- args.putString(ARG_EMAIL, email);
- args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
-
frag.setArguments(args);
return frag;
@@ -83,7 +72,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
*/
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
boolean output = true;
- if (editText.getText().toString().length() == 0) {
+ if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
@@ -95,11 +84,13 @@ public class CreateKeyPassphraseFragment extends Fragment {
}
private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
- boolean output = true;
- if (!editText1.getText().toString().equals(editText2.getText().toString())) {
+ Passphrase p1 = new Passphrase(editText1);
+ Passphrase p2 = new Passphrase(editText2);
+ boolean output = (p1.equals(p2));
+
+ if (!output) {
editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
editText2.requestFocus();
- output = false;
} else {
editText2.setError(null);
}
@@ -118,9 +109,12 @@ public class CreateKeyPassphraseFragment extends Fragment {
mNextButton = view.findViewById(R.id.create_key_next_button);
// initial values
- mName = getArguments().getString(ARG_NAME);
- mEmail = getArguments().getString(ARG_EMAIL);
- mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
+ // TODO: using String here is unsafe...
+ if (mCreateKeyActivity.mPassphrase != null) {
+ mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray()));
+ mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray()));
+ }
+
mPassphraseEdit.requestFocus();
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -131,7 +125,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
mNextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- createKeyCheck();
+ nextClicked();
}
});
mShowPassphrase.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@@ -159,23 +153,19 @@ public class CreateKeyPassphraseFragment extends Fragment {
private void back() {
hideKeyboard();
- mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
}
- private void createKeyCheck() {
+ private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mPassphraseEdit)
&& areEditTextsEqual(getActivity(), mPassphraseEdit, mPassphraseEditAgain)) {
- CreateKeyFinalFragment frag =
- CreateKeyFinalFragment.newInstance(
- mName,
- mEmail,
- mAdditionalEmails,
- mPassphraseEdit.getText().toString()
- );
+ // save state
+ mCreateKeyActivity.mPassphrase = new Passphrase(mPassphraseEdit);
+ CreateKeyFinalFragment frag = CreateKeyFinalFragment.newInstance();
hideKeyboard();
- mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
new file mode 100644
index 000000000..180a52a1c
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v4.app.Fragment;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
+import org.sufficientlysecure.keychain.ui.dialog.AddEmailDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
+import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
+import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CreateKeyStartFragment extends Fragment {
+
+ CreateKeyActivity mCreateKeyActivity;
+
+ View mCreateKey;
+ View mImportKey;
+ View mYubiKey;
+ TextView mCancel;
+ public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static CreateKeyStartFragment newInstance() {
+ CreateKeyStartFragment frag = new CreateKeyStartFragment();
+
+ Bundle args = new Bundle();
+
+ frag.setArguments(args);
+
+ return frag;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.create_key_start_fragment, container, false);
+
+ mCreateKey = view.findViewById(R.id.create_key_create_key_button);
+ mImportKey = view.findViewById(R.id.create_key_import_button);
+// mYubiKey = view.findViewById(R.id.create_key_yubikey_button);
+ mCancel = (TextView) view.findViewById(R.id.create_key_cancel);
+
+ if (mCreateKeyActivity.mFirstTime) {
+ mCancel.setText(R.string.first_time_skip);
+ } else {
+ mCancel.setText(R.string.btn_do_not_save);
+ }
+
+ mCreateKey.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ CreateKeyNameFragment frag = CreateKeyNameFragment.newInstance();
+ mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
+ }
+ });
+
+ mImportKey.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(mCreateKeyActivity, ImportKeysActivity.class);
+ intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
+ startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
+ }
+ });
+
+ mCancel.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ finishSetup(null);
+ }
+ });
+
+ return view;
+ }
+
+
+ private void finishSetup(Intent srcData) {
+ if (mCreateKeyActivity.mFirstTime) {
+ Preferences prefs = Preferences.getPreferences(mCreateKeyActivity);
+ prefs.setFirstTime(false);
+ }
+ Intent intent = new Intent(mCreateKeyActivity, MainActivity.class);
+ // give intent through to display notify
+ if (srcData != null) {
+ intent.putExtras(srcData);
+ }
+ startActivity(intent);
+ mCreateKeyActivity.finish();
+ }
+
+ // workaround for https://code.google.com/p/android/issues/detail?id=61394
+// @Override
+// public boolean onKeyDown(int keyCode, KeyEvent event) {
+// return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event);
+// }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) {
+ if (resultCode == Activity.RESULT_OK) {
+ finishSetup(data);
+ }
+ } else {
+ Log.e(Constants.TAG, "No valid request code!");
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mCreateKeyActivity = (CreateKeyActivity) getActivity();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
index c808557a6..a92fb596c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
@@ -139,7 +139,7 @@ public class DecryptFilesFragment extends DecryptFragment {
private void decryptAction() {
if (mInputUri == null) {
- Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR).show();
return;
}
@@ -147,7 +147,9 @@ public class DecryptFilesFragment extends DecryptFragment {
}
private String removeEncryptedAppend(String name) {
- if (name.endsWith(".asc") || name.endsWith(".gpg") || name.endsWith(".pgp")) {
+ if (name.endsWith(Constants.FILE_EXTENSION_ASC)
+ || name.endsWith(Constants.FILE_EXTENSION_PGP_MAIN)
+ || name.endsWith(Constants.FILE_EXTENSION_PGP_ALTERNATE)) {
return name.substring(0, name.length() - 4);
}
return name;
@@ -189,7 +191,7 @@ public class DecryptFilesFragment extends DecryptFragment {
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
- data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
+ data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -263,7 +265,7 @@ public class DecryptFilesFragment extends DecryptFragment {
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
- data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
+ data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -339,7 +341,7 @@ public class DecryptFilesFragment extends DecryptFragment {
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
decryptOriginalFilename();
}
return;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 60103f344..63508e530 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
+import org.sufficientlysecure.keychain.util.Passphrase;
public abstract class DecryptFragment extends Fragment {
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
@@ -57,7 +58,7 @@ public abstract class DecryptFragment extends Fragment {
// State
- protected String mPassphrase;
+ protected Passphrase mPassphrase;
protected byte[] mNfcDecryptedSessionKey;
@Override
@@ -100,7 +101,7 @@ public abstract class DecryptFragment extends Fragment {
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
}
- protected void startNfcDecrypt(long subKeyId, String pin, byte[] encryptedSessionKey) {
+ protected void startNfcDecrypt(long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(getActivity(), NfcActivity.class);
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
@@ -128,14 +129,14 @@ public abstract class DecryptFragment extends Fragment {
mSignatureKeyId = signatureResult.getKeyId();
String userId = signatureResult.getPrimaryUserId();
- String[] userIdSplit = KeyRing.splitUserId(userId);
- if (userIdSplit[0] != null) {
- mSignatureName.setText(userIdSplit[0]);
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
+ if (userIdSplit.name != null) {
+ mSignatureName.setText(userIdSplit.name);
} else {
mSignatureName.setText(R.string.user_id_no_name);
}
- if (userIdSplit[1] != null) {
- mSignatureEmail.setText(userIdSplit[1]);
+ if (userIdSplit.email != null) {
+ mSignatureEmail.setText(userIdSplit.email);
} else {
mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(getActivity(), mSignatureKeyId));
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
index 1e9e7bcb1..bc2ec014a 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java
@@ -161,7 +161,7 @@ public class DecryptTextActivity extends BaseActivity {
if (sharedText != null) {
loadFragment(savedInstanceState, sharedText);
} else {
- Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR);
+ Notify.create(this, R.string.error_invalid_data, Notify.Style.ERROR).show();
}
} else {
Log.e(Constants.TAG, "ACTION_SEND received non-plaintext, this should not happen in this activity!");
@@ -175,7 +175,7 @@ public class DecryptTextActivity extends BaseActivity {
if (extraText != null) {
loadFragment(savedInstanceState, extraText);
} else {
- Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR);
+ Notify.create(this, R.string.error_invalid_data, Notify.Style.ERROR).show();
}
} else if (ACTION_DECRYPT_FROM_CLIPBOARD.equals(action)) {
Log.d(Constants.TAG, "ACTION_DECRYPT_FROM_CLIPBOARD");
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
index 1b34f6bf0..80a07214b 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -132,7 +132,7 @@ public class DecryptTextFragment extends DecryptFragment {
private void copyToClipboard(String text) {
ClipboardReflection.copyToClipboard(getActivity(), text);
- Notify.showNotify(getActivity(), R.string.text_copied_to_clipboard, Notify.Style.INFO);
+ Notify.create(getActivity(), R.string.text_copied_to_clipboard, Notify.Style.OK).show();
}
@Override
@@ -161,7 +161,7 @@ public class DecryptTextFragment extends DecryptFragment {
// data
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
- data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
+ data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@@ -247,7 +247,7 @@ public class DecryptTextFragment extends DecryptFragment {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
decryptStart();
} else {
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 de1eb64c2..86fb8dc80 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java
@@ -67,6 +67,7 @@ import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class EditKeyFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
@@ -100,7 +101,7 @@ public class EditKeyFragment extends LoaderFragment implements
private SaveKeyringParcel mSaveKeyringParcel;
private String mPrimaryUserId;
- private String mCurrentPassphrase;
+ private Passphrase mCurrentPassphrase;
/**
* Creates new instance of this fragment
@@ -267,7 +268,7 @@ public class EditKeyFragment extends LoaderFragment implements
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == Activity.RESULT_OK && data != null) {
- mCurrentPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mCurrentPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, EditKeyFragment.this);
@@ -386,7 +387,7 @@ public class EditKeyFragment extends LoaderFragment implements
// cache new returned passphrase!
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
- data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
+ (Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
null
);
}
@@ -545,7 +546,7 @@ public class EditKeyFragment extends LoaderFragment implements
Messenger messenger = new Messenger(returnHandler);
// pre-fill out primary name
- String predefinedName = KeyRing.splitUserId(mPrimaryUserId)[0];
+ String predefinedName = KeyRing.splitUserId(mPrimaryUserId).name;
AddUserIdDialogFragment addUserIdDialog = AddUserIdDialogFragment.newInstance(messenger,
predefinedName);
@@ -576,11 +577,11 @@ public class EditKeyFragment extends LoaderFragment implements
private void returnKeyringParcel() {
if (mSaveKeyringParcel.mAddUserIds.size() == 0) {
- Notify.showNotify(getActivity(), R.string.edit_key_error_add_identity, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.edit_key_error_add_identity, Notify.Style.ERROR).show();
return;
}
if (mSaveKeyringParcel.mAddSubKeys.size() == 0) {
- Notify.showNotify(getActivity(), R.string.edit_key_error_add_subkey, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.edit_key_error_add_subkey, Notify.Style.ERROR).show();
return;
}
@@ -593,7 +594,7 @@ public class EditKeyFragment extends LoaderFragment implements
getActivity().finish();
}
- private void saveInDatabase(String passphrase) {
+ private void saveInDatabase(Passphrase passphrase) {
Log.d(Constants.TAG, "mSaveKeyringParcel:\n" + mSaveKeyringParcel.toString());
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
@@ -640,7 +641,7 @@ public class EditKeyFragment extends LoaderFragment implements
// fill values for this action
Bundle data = new Bundle();
- data.putString(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
+ data.putParcelable(KeychainIntentService.EDIT_KEYRING_PASSPHRASE, passphrase);
data.putParcelable(KeychainIntentService.EDIT_KEYRING_PARCEL, mSaveKeyringParcel);
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 35dfcb87c..5438f667c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.util.Date;
@@ -41,7 +42,7 @@ public abstract class EncryptActivity extends BaseActivity {
public static final int REQUEST_CODE_NFC = 0x00008002;
// For NFC data
- protected String mSigningKeyPassphrase = null;
+ protected Passphrase mSigningKeyPassphrase = null;
protected Date mNfcTimestamp = null;
protected byte[] mNfcHash = null;
@@ -64,7 +65,7 @@ public abstract class EncryptActivity extends BaseActivity {
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
}
- protected void startNfcSign(long keyId, String pin, byte[] hashToSign, int hashAlgo) {
+ protected void startNfcSign(long keyId, Passphrase pin, byte[] hashToSign, int hashAlgo) {
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(this, NfcActivity.class);
intent.setAction(NfcActivity.ACTION_SIGN_HASH);
@@ -84,7 +85,7 @@ public abstract class EncryptActivity extends BaseActivity {
switch (requestCode) {
case REQUEST_CODE_PASSPHRASE: {
if (resultCode == RESULT_OK && data != null) {
- mSigningKeyPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
+ mSigningKeyPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
startEncrypt();
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
index baf445293..2a102c6c4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
@@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
+import org.sufficientlysecure.keychain.util.Passphrase;
+
import java.util.ArrayList;
public interface EncryptActivityInterface {
@@ -29,6 +31,8 @@ public interface EncryptActivityInterface {
public boolean isUseArmor();
public boolean isUseCompression();
+ public boolean isEncryptFilenames();
+ public boolean isHiddenRecipients();
public long getSignatureKey();
public long[] getEncryptionKeys();
@@ -37,7 +41,7 @@ public interface EncryptActivityInterface {
public void setEncryptionKeys(long[] encryptionKeys);
public void setEncryptionUsers(String[] encryptionUsers);
- public void setPassphrase(String passphrase);
+ public void setPassphrase(Passphrase passphrase);
// ArrayList on purpose as only those are parcelable
public ArrayList<Uri> getInputUris();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
index b862d5b11..fe9b05226 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
@@ -62,14 +63,18 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
private static final int MODE_SYMMETRIC = 1;
// model used by fragments
- private long mEncryptionKeyIds[] = null;
- private String mEncryptionUserIds[] = null;
- private long mSigningKeyId = Constants.key.none;
- private String mPassphrase = "";
private boolean mUseArmor = false;
private boolean mUseCompression = true;
private boolean mDeleteAfterEncrypt = false;
private boolean mShareAfterEncrypt = false;
+ private boolean mEncryptFilenames = true;
+ private boolean mHiddenRecipients = false;
+
+ private long mEncryptionKeyIds[] = null;
+ private String mEncryptionUserIds[] = null;
+ private long mSigningKeyId = Constants.key.none;
+ private Passphrase mPassphrase = new Passphrase();
+
private ArrayList<Uri> mInputUris;
private ArrayList<Uri> mOutputUris;
private String mMessage = "";
@@ -89,6 +94,16 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
}
@Override
+ public boolean isEncryptFilenames() {
+ return mEncryptFilenames;
+ }
+
+ @Override
+ public boolean isHiddenRecipients() {
+ return mHiddenRecipients;
+ }
+
+ @Override
public long getSignatureKey() {
return mSigningKeyId;
}
@@ -122,7 +137,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
}
@Override
- public void setPassphrase(String passphrase) {
+ public void setPassphrase(Passphrase passphrase) {
mPassphrase = passphrase;
}
@@ -222,14 +237,15 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
} else {
data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
}
+ data.setHiddenRecipients(mHiddenRecipients);
data.setEnableAsciiArmorOutput(mUseArmor);
data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
- String passphrase = mPassphrase;
- if (passphrase.length() == 0) {
+ Passphrase passphrase = mPassphrase;
+ if (passphrase.isEmpty()) {
passphrase = null;
}
data.setSymmetricPassphrase(passphrase);
@@ -268,14 +284,14 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris);
}
- sendIntent.setType("application/octet-stream");
+ sendIntent.setType(Constants.ENCRYPTED_FILES_MIME);
if (!isModeSymmetric() && mEncryptionUserIds != null) {
Set<String> users = new HashSet<>();
for (String user : mEncryptionUserIds) {
- String[] userId = KeyRing.splitUserId(user);
- if (userId[1] != null) {
- users.add(userId[1]);
+ KeyRing.UserId userId = KeyRing.splitUserId(user);
+ if (userId.email != null) {
+ users.add(userId.email);
}
}
sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()]));
@@ -287,7 +303,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
// file checks
if (mInputUris.isEmpty()) {
- Notify.showNotify(this, R.string.no_file_selected, Notify.Style.ERROR);
+ Notify.create(this, R.string.no_file_selected, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
return false;
} else if (mInputUris.size() > 1 && !mShareAfterEncrypt) {
// This should be impossible...
@@ -301,11 +318,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
// symmetric encryption checks
if (mPassphrase == null) {
- Notify.showNotify(this, R.string.passphrases_do_not_match, Notify.Style.ERROR);
+ Notify.create(this, R.string.passphrases_do_not_match, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
return false;
}
if (mPassphrase.isEmpty()) {
- Notify.showNotify(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR);
+ Notify.create(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
return false;
}
@@ -317,7 +336,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
// Files must be encrypted, only text can be signed-only right now
if (!gotEncryptionKeys) {
- Notify.showNotify(this, R.string.select_encryption_key, Notify.Style.ERROR);
+ Notify.create(this, R.string.select_encryption_key, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_file_fragment));
return false;
}
}
@@ -371,6 +391,16 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
notifyUpdate();
break;
}
+ case R.id.check_encrypt_filenames: {
+ mEncryptFilenames = item.isChecked();
+ notifyUpdate();
+ break;
+ }
+// case R.id.check_hidden_recipients: {
+// mHiddenRecipients = item.isChecked();
+// notifyUpdate();
+// break;
+// }
default: {
return super.onOptionsItemSelected(item);
}
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 48737d223..4ba76d8ea 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java
@@ -115,9 +115,9 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
}
if (mEncryptInterface.getInputUris().contains(inputUri)) {
- Notify.showNotify(getActivity(),
+ Notify.create(getActivity(),
getActivity().getString(R.string.error_file_added_already, FileHelper.getFilename(getActivity(), inputUri)),
- Notify.Style.ERROR);
+ Notify.Style.ERROR).show(this);
return;
}
@@ -137,36 +137,39 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt
throw new IllegalStateException();
}
Uri inputUri = mEncryptInterface.getInputUris().get(0);
+ String targetName =
+ (mEncryptInterface.isEncryptFilenames() ? "1" : FileHelper.getFilename(getActivity(), inputUri))
+ + (mEncryptInterface.isUseArmor() ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
File file = new File(inputUri.getPath());
File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR;
- String targetName = FileHelper.getFilename(getActivity(), inputUri) +
- (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg");
File targetFile = new File(parentDir, targetName);
FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file),
getString(R.string.specify_file_to_encrypt_to), targetFile, REQUEST_CODE_OUTPUT);
} else {
- FileHelper.saveDocument(this, "*/*", FileHelper.getFilename(getActivity(), inputUri) +
- (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"), REQUEST_CODE_OUTPUT);
+ FileHelper.saveDocument(this, "*/*", targetName, REQUEST_CODE_OUTPUT);
}
}
private void encryptClicked(boolean share) {
if (mEncryptInterface.getInputUris().isEmpty()) {
- Notify.showNotify(getActivity(), R.string.error_no_file_selected, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.error_no_file_selected, Notify.Style.ERROR).show(this);
return;
}
if (share) {
mEncryptInterface.getOutputUris().clear();
+ int filenameCounter = 1;
for (Uri uri : mEncryptInterface.getInputUris()) {
- String targetName = FileHelper.getFilename(getActivity(), uri) +
- (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg");
+ String targetName =
+ (mEncryptInterface.isEncryptFilenames() ? String.valueOf(filenameCounter) : FileHelper.getFilename(getActivity(), uri))
+ + (mEncryptInterface.isUseArmor() ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN);
mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName));
+ filenameCounter++;
}
mEncryptInterface.startEncrypt(true);
} else {
if (mEncryptInterface.getInputUris().size() > 1) {
- Notify.showNotify(getActivity(), R.string.error_multi_not_supported, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.error_multi_not_supported, Notify.Style.ERROR).show(this);
return;
}
showOutputFileDialog();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
index 86731b162..36b3c08f9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java
@@ -28,6 +28,7 @@ import android.view.ViewGroup;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
@@ -67,8 +68,13 @@ public class EncryptSymmetricFragment extends Fragment implements EncryptActivit
@Override
public void afterTextChanged(Editable s) {
// update passphrase in EncryptActivity
- if (mPassphrase.getText().toString().equals(mPassphraseAgain.getText().toString())) {
- mEncryptInterface.setPassphrase(s.toString());
+ Passphrase p1 = new Passphrase(mPassphrase.getText());
+ Passphrase p2 = new Passphrase(mPassphraseAgain.getText());
+ boolean passesEquals = (p1.equals(p2));
+ p1.removeFromMemory();
+ p2.removeFromMemory();
+ if (passesEquals) {
+ mEncryptInterface.setPassphrase(new Passphrase(mPassphrase.getText()));
} else {
mEncryptInterface.setPassphrase(null);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
index ee15cf7b5..c800153ae 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -36,7 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ShareHelper;
import java.util.ArrayList;
@@ -63,16 +63,19 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
private static final int MODE_SYMMETRIC = 1;
// model used by fragments
+ private boolean mShareAfterEncrypt = false;
+ private boolean mUseCompression = true;
+ private boolean mHiddenRecipients = false;
+
private long mEncryptionKeyIds[] = null;
private String mEncryptionUserIds[] = null;
// TODO Constants.key.none? What's wrong with a null value?
private long mSigningKeyId = Constants.key.none;
- private String mPassphrase = "";
- private boolean mShareAfterEncrypt = false;
+ private Passphrase mPassphrase = new Passphrase();
+
private ArrayList<Uri> mInputUris;
private ArrayList<Uri> mOutputUris;
private String mMessage = "";
- private boolean mUseCompression = true;
public boolean isModeSymmetric() {
return MODE_SYMMETRIC == mCurrentMode;
@@ -84,11 +87,21 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
@Override
+ public boolean isEncryptFilenames() {
+ return false;
+ }
+
+ @Override
public boolean isUseCompression() {
return mUseCompression;
}
@Override
+ public boolean isHiddenRecipients() {
+ return mHiddenRecipients;
+ }
+
+ @Override
public long getSignatureKey() {
return mSigningKeyId;
}
@@ -122,7 +135,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
@Override
- public void setPassphrase(String passphrase) {
+ public void setPassphrase(Passphrase passphrase) {
+ mPassphrase.removeFromMemory();
mPassphrase = passphrase;
}
@@ -184,8 +198,9 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
// Copy to clipboard
copyToClipboard(result.getResultBytes());
result.createNotify(EncryptTextActivity.this).show();
- // Notify.showNotify(EncryptTextActivity.this,
- // R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);
+ // Notify.create(EncryptTextActivity.this,
+ // R.string.encrypt_sign_clipboard_successful, Notify.Style.OK)
+ // .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
}
}
@@ -202,6 +217,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
} else {
data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
}
+ data.setHiddenRecipients(mHiddenRecipients);
data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
@@ -210,8 +226,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
- String passphrase = mPassphrase;
- if (passphrase.length() == 0) {
+ Passphrase passphrase = mPassphrase;
+ if (passphrase.isEmpty()) {
passphrase = null;
}
data.setSymmetricPassphrase(passphrase);
@@ -247,15 +263,15 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
private Intent createSendIntent(byte[] resultBytes) {
Intent sendIntent;
sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.setType("text/plain");
+ sendIntent.setType(Constants.ENCRYPTED_TEXT_MIME);
sendIntent.putExtra(Intent.EXTRA_TEXT, new String(resultBytes));
if (!isModeSymmetric() && mEncryptionUserIds != null) {
Set<String> users = new HashSet<>();
for (String user : mEncryptionUserIds) {
- String[] userId = KeyRing.splitUserId(user);
- if (userId[1] != null) {
- users.add(userId[1]);
+ KeyRing.UserId userId = KeyRing.splitUserId(user);
+ if (userId.email != null) {
+ users.add(userId.email);
}
}
// pass trough email addresses as extra for email applications
@@ -266,7 +282,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
protected boolean inputIsValid() {
if (mMessage == null) {
- Notify.showNotify(this, R.string.error_message, Notify.Style.ERROR);
+ Notify.create(this, R.string.error_message, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
return false;
}
@@ -274,11 +291,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
// symmetric encryption checks
if (mPassphrase == null) {
- Notify.showNotify(this, R.string.passphrases_do_not_match, Notify.Style.ERROR);
+ Notify.create(this, R.string.passphrases_do_not_match, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
return false;
}
if (mPassphrase.isEmpty()) {
- Notify.showNotify(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR);
+ Notify.create(this, R.string.passphrase_must_not_be_empty, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
return false;
}
@@ -289,7 +308,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
&& mEncryptionKeyIds.length > 0);
if (!gotEncryptionKeys && mSigningKeyId == 0) {
- Notify.showNotify(this, R.string.select_encryption_or_signature_key, Notify.Style.ERROR);
+ Notify.create(this, R.string.select_encryption_or_signature_key, Notify.Style.ERROR)
+ .show(getSupportFragmentManager().findFragmentById(R.id.encrypt_text_fragment));
return false;
}
}
@@ -353,6 +373,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
notifyUpdate();
break;
}
+// case R.id.check_hidden_recipients: {
+// mHiddenRecipients = item.isChecked();
+// notifyUpdate();
+// break;
+// }
default: {
return super.onOptionsItemSelected(item);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
deleted file mode 100644
index 393e15cfa..000000000
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.Window;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.util.Preferences;
-
-public class FirstTimeActivity extends BaseActivity {
-
- View mCreateKey;
- View mImportKey;
- View mSkipSetup;
-
- public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
-
- super.onCreate(savedInstanceState);
-
- mCreateKey = findViewById(R.id.first_time_create_key);
- mImportKey = findViewById(R.id.first_time_import_key);
- mSkipSetup = findViewById(R.id.first_time_cancel);
-
- mSkipSetup.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- finishSetup(null);
- }
- });
-
- mImportKey.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(FirstTimeActivity.this, ImportKeysActivity.class);
- intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
- startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
- }
- });
-
- mCreateKey.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(FirstTimeActivity.this, CreateKeyActivity.class);
- startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
- }
- });
- }
-
- @Override
- protected void initLayout() {
- setContentView(R.layout.first_time_activity);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) {
- if (resultCode == RESULT_OK) {
- finishSetup(data);
- }
- } else {
- Log.e(Constants.TAG, "No valid request code!");
- }
- }
-
- private void finishSetup(Intent srcData) {
- Preferences prefs = Preferences.getPreferences(this);
- prefs.setFirstTime(false);
- Intent intent = new Intent(this, MainActivity.class);
- // give intent through to display notify
- if (srcData != null) {
- intent.putExtras(srcData);
- }
- startActivity(intent);
- finish();
- }
-
- // workaround for https://code.google.com/p/android/issues/detail?id=61394
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event);
- }
-
-}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index d51e2c7fc..9143609ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -26,6 +26,7 @@ import android.os.Messenger;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -277,7 +278,8 @@ public class ImportKeysActivity extends BaseActivity {
private boolean isFingerprintValid(String fingerprint) {
if (fingerprint == null || fingerprint.length() < 40) {
- Notify.showNotify(this, R.string.import_qr_code_too_short_fingerprint, Notify.Style.ERROR);
+ Notify.create(this, R.string.import_qr_code_too_short_fingerprint, Notify.Style.ERROR)
+ .show((ViewGroup) findViewById(R.id.import_snackbar));
return false;
} else {
return true;
@@ -329,7 +331,8 @@ public class ImportKeysActivity extends BaseActivity {
return;
}
- result.createNotify(ImportKeysActivity.this).show();
+ result.createNotify(ImportKeysActivity.this)
+ .show((ViewGroup) findViewById(R.id.import_snackbar));
}
}
};
@@ -372,7 +375,8 @@ public class ImportKeysActivity extends BaseActivity {
startService(intent);
} catch (IOException e) {
Log.e(Constants.TAG, "Problem writing cache file", e);
- Notify.showNotify(this, "Problem writing cache file!", Notify.Style.ERROR);
+ Notify.create(this, "Problem writing cache file!", Notify.Style.ERROR)
+ .show((ViewGroup) findViewById(R.id.import_snackbar));
}
} else if (ls instanceof ImportKeysListFragment.CloudLoaderState) {
ImportKeysListFragment.CloudLoaderState sls = (ImportKeysListFragment.CloudLoaderState) ls;
@@ -412,7 +416,8 @@ public class ImportKeysActivity extends BaseActivity {
// start service with intent
startService(intent);
} else {
- Notify.showNotify(this, R.string.error_nothing_import, Notify.Style.ERROR);
+ Notify.create(this, R.string.error_nothing_import, Notify.Style.ERROR)
+ .show((ViewGroup) findViewById(R.id.import_snackbar));
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
index cc8b47971..1c1e5fe99 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java
@@ -154,7 +154,7 @@ public class ImportKeysProxyActivity extends FragmentActivity {
String fingerprint = null;
// example: openpgp4fpr:73EE2314F65FA92EC2390D3A718C070100012282
- if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) {
+ if (uri != null && uri.getScheme() != null && uri.getScheme().toLowerCase(Locale.ENGLISH).equals(Constants.FINGERPRINT_SCHEME)) {
fingerprint = uri.getEncodedSchemeSpecificPart().toLowerCase(Locale.ENGLISH);
}
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 8c34efba2..5f1189deb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -169,6 +169,22 @@ public class KeyListFragment extends LoaderFragment
mStickyList.setDrawingListUnderStickyHeader(false);
mStickyList.setFastScrollEnabled(true);
+ // Adds an empty footer view so that the Floating Action Button won't block content
+ // in last few rows.
+ View footer = new View(getActivity());
+
+ int spacing = (int) android.util.TypedValue.applyDimension(
+ android.util.TypedValue.COMPLEX_UNIT_DIP, 72, getResources().getDisplayMetrics()
+ );
+
+ android.widget.AbsListView.LayoutParams params = new android.widget.AbsListView.LayoutParams(
+ android.widget.AbsListView.LayoutParams.MATCH_PARENT,
+ spacing
+ );
+
+ footer.setLayoutParams(params);
+ mStickyList.addFooterView(footer, null, false);
+
/*
* Multi-selection
*/
@@ -369,13 +385,13 @@ public class KeyListFragment extends LoaderFragment
/**
* Show dialog to delete key
*
- * @param hasSecret must contain whether the list of masterKeyIds contains a secret key or not
+ * @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.showNotify(getActivity(), R.string.secret_cannot_multiple,
- Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.secret_cannot_multiple,
+ Notify.Style.ERROR).show();
return;
}
@@ -468,28 +484,29 @@ public class KeyListFragment extends LoaderFragment
case R.id.menu_key_list_debug_read:
try {
KeychainDatabase.debugBackup(getActivity(), true);
- Notify.showNotify(getActivity(), "Restored debug_backup.db", Notify.Style.INFO);
+ Notify.create(getActivity(), "Restored debug_backup.db", Notify.Style.OK).show();
getActivity().getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null);
} catch (IOException e) {
Log.e(Constants.TAG, "IO Error", e);
- Notify.showNotify(getActivity(), "IO Error " + e.getMessage(), Notify.Style.ERROR);
+ Notify.create(getActivity(), "IO Error " + e.getMessage(), Notify.Style.ERROR).show();
}
return true;
case R.id.menu_key_list_debug_write:
try {
KeychainDatabase.debugBackup(getActivity(), false);
- Notify.showNotify(getActivity(), "Backup to debug_backup.db completed", Notify.Style.INFO);
+ Notify.create(getActivity(), "Backup to debug_backup.db completed", Notify.Style.OK).show();
} catch (IOException e) {
Log.e(Constants.TAG, "IO Error", e);
- Notify.showNotify(getActivity(), "IO Error: " + e.getMessage(), Notify.Style.ERROR);
+ Notify.create(getActivity(), "IO Error: " + e.getMessage(), Notify.Style.ERROR).show();
}
return true;
case R.id.menu_key_list_debug_first_time:
Preferences prefs = Preferences.getPreferences(getActivity());
prefs.setFirstTime(true);
- Intent intent = new Intent(getActivity(), FirstTimeActivity.class);
+ Intent intent = new Intent(getActivity(), CreateKeyActivity.class);
+ intent.putExtra(CreateKeyActivity.EXTRA_FIRST_TIME, true);
startActivity(intent);
getActivity().finish();
return true;
@@ -688,14 +705,14 @@ public class KeyListFragment extends LoaderFragment
{ // set name and stuff, common to both key types
String userId = cursor.getString(INDEX_USER_ID);
- String[] userIdSplit = KeyRing.splitUserId(userId);
- if (userIdSplit[0] != null) {
- h.mMainUserId.setText(highlighter.highlight(userIdSplit[0]));
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
+ if (userIdSplit.name != null) {
+ h.mMainUserId.setText(highlighter.highlight(userIdSplit.name));
} else {
h.mMainUserId.setText(R.string.user_id_no_name);
}
- if (userIdSplit[1] != null) {
- h.mMainUserIdRest.setText(highlighter.highlight(userIdSplit[1]));
+ if (userIdSplit.email != null) {
+ h.mMainUserIdRest.setText(highlighter.highlight(userIdSplit.email));
h.mMainUserIdRest.setVisibility(View.VISIBLE);
} else {
h.mMainUserIdRest.setVisibility(View.GONE);
@@ -908,5 +925,4 @@ public class KeyListFragment extends LoaderFragment
}
-
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
index b6b2fcb8a..5fa3edba4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java
@@ -54,7 +54,9 @@ public class MainActivity extends MaterialNavigationDrawer implements FabContain
// if this is the first time show first time activity
Preferences prefs = Preferences.getPreferences(this);
if (prefs.isFirstTime()) {
- startActivity(new Intent(this, FirstTimeActivity.class));
+ Intent intent = new Intent(this, CreateKeyActivity.class);
+ intent.putExtra(CreateKeyActivity.EXTRA_FIRST_TIME, true);
+ startActivity(intent);
finish();
return;
}
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 b06cf0abd..b77637696 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -55,6 +55,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
/**
@@ -212,9 +213,9 @@ public class PassphraseDialogActivity extends FragmentActivity {
// the catch clause doesn't return.
try {
String mainUserId = mSecretRing.getPrimaryUserIdWithFallback();
- String[] mainUserIdSplit = KeyRing.splitUserId(mainUserId);
- if (mainUserIdSplit[0] != null) {
- userId = mainUserIdSplit[0];
+ KeyRing.UserId mainUserIdSplit = KeyRing.splitUserId(mainUserId);
+ if (mainUserIdSplit.name != null) {
+ userId = mainUserIdSplit.name;
} else {
userId = getString(R.string.user_id_no_name);
}
@@ -240,7 +241,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
break;
// special case: empty passphrase just returns the empty passphrase
case PASSPHRASE_EMPTY:
- finishCaching("");
+ finishCaching(new Passphrase(""));
default:
message = "This should not happen!";
break;
@@ -322,7 +323,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
positive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- final String passphrase = mPassphraseEditText.getText().toString();
+ final Passphrase passphrase = new Passphrase(mPassphraseEditText);
// Early breakout if we are dealing with a symmetric key
if (mSecretRing == null) {
@@ -399,7 +400,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
});
}
- private void finishCaching(String passphrase) {
+ private void finishCaching(Passphrase passphrase) {
// any indication this isn't needed anymore, don't do it.
if (mIsCancelled || getActivity() == null) {
return;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
index d3c1d971a..43af07bbe 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeViewActivity.java
@@ -80,7 +80,7 @@ public class QrCodeViewActivity extends BaseActivity {
KeychainContract.KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
if (blob == null) {
Log.e(Constants.TAG, "key not found!");
- Notify.showNotify(this, R.string.error_key_not_found, Style.ERROR);
+ Notify.create(this, R.string.error_key_not_found, Style.ERROR).show();
ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
}
@@ -102,7 +102,7 @@ public class QrCodeViewActivity extends BaseActivity {
});
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
- Notify.showNotify(this, R.string.error_key_not_found, Style.ERROR);
+ Notify.create(this, R.string.error_key_not_found, Style.ERROR).show();
ActivityCompat.finishAfterTransition(QrCodeViewActivity.this);
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
index d0cea5f05..863aef65f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SafeSlingerActivity.java
@@ -205,7 +205,7 @@ public class SafeSlingerActivity extends BaseActivity {
activity.startService(intent);
} catch (IOException e) {
Log.e(Constants.TAG, "Problem writing cache file", e);
- Notify.showNotify(activity, "Problem writing cache file!", Notify.Style.ERROR);
+ Notify.create(activity, "Problem writing cache file!", Notify.Style.ERROR).show();
}
} else {
// give everything else down to KeyListActivity!
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 70c590728..435a455dc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -21,18 +21,12 @@ package org.sufficientlysecure.keychain.ui;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcEvent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -40,7 +34,6 @@ import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.provider.ContactsContract;
-import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.LoaderManager;
@@ -59,9 +52,7 @@ 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;
@@ -76,6 +67,8 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
+import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+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;
@@ -84,6 +77,7 @@ import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.NfcHelper;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -93,8 +87,8 @@ public class ViewKeyActivity extends BaseActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
static final int REQUEST_QR_FINGERPRINT = 1;
- static final int REQUEST_DELETE= 2;
- static final int REQUEST_EXPORT= 3;
+ static final int REQUEST_DELETE = 2;
+ static final int REQUEST_EXPORT = 3;
ExportHelper mExportHelper;
ProviderHelper mProviderHelper;
@@ -115,11 +109,7 @@ public class ViewKeyActivity extends BaseActivity implements
private CardView mQrCodeLayout;
// NFC
- private NfcAdapter mNfcAdapter;
- private NfcAdapter.CreateNdefMessageCallback mNdefCallback;
- private NfcAdapter.OnNdefPushCompleteCallback mNdefCompleteCallback;
- private byte[] mNfcKeyringBytes;
- private static final int NFC_SENT = 1;
+ private NfcHelper mNfcHelper;
private static final int LOADER_ID_UNIFIED = 0;
@@ -256,7 +246,7 @@ public class ViewKeyActivity extends BaseActivity implements
mActionNfc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- invokeNfcBeam();
+ mNfcHelper.invokeNfcBeam();
}
});
@@ -264,7 +254,8 @@ public class ViewKeyActivity extends BaseActivity implements
// or start new ones.
getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
- initNfc(mDataUri);
+ mNfcHelper = new NfcHelper(this, mProviderHelper);
+ mNfcHelper.initNfc(mDataUri);
}
@@ -291,31 +282,31 @@ public class ViewKeyActivity extends BaseActivity implements
return true;
}
case R.id.menu_key_view_export_file: {
- Intent mIntent = new Intent(this,PassphraseDialogActivity.class);
- long keyId=0;
try {
- keyId = new ProviderHelper(this)
- .getCachedPublicKeyRing(mDataUri)
- .extractOrGetMasterKeyId();
- } catch (PgpKeyNotFoundException e) {
- e.printStackTrace();
+ if (PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId, mMasterKeyId) != null) {
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
+ return true;
+ }
+
+ startPassphraseActivity(REQUEST_EXPORT);
+ } catch (PassphraseCacheService.KeyNotFoundException e) {
+ // This happens when the master key is stripped
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
}
- mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
- startActivityForResult(mIntent,REQUEST_EXPORT);
return true;
}
case R.id.menu_key_view_delete: {
- Intent mIntent = new Intent(this,PassphraseDialogActivity.class);
- long keyId=0;
try {
- keyId = new ProviderHelper(this)
- .getCachedPublicKeyRing(mDataUri)
- .extractOrGetMasterKeyId();
- } catch (PgpKeyNotFoundException e) {
- e.printStackTrace();
+ if (PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId, mMasterKeyId) != null) {
+ deleteKey();
+ return true;
+ }
+
+ startPassphraseActivity(REQUEST_DELETE);
+ } catch (PassphraseCacheService.KeyNotFoundException e) {
+ // This happens when the master key is stripped
+ deleteKey();
}
- mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
- startActivityForResult(mIntent,REQUEST_DELETE);
return true;
}
case R.id.menu_key_view_advanced: {
@@ -328,7 +319,7 @@ public class ViewKeyActivity extends BaseActivity implements
try {
updateFromKeyserver(mDataUri, mProviderHelper);
} catch (ProviderHelper.NotFoundException e) {
- Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
+ Notify.create(this, R.string.error_key_not_found, Notify.Style.ERROR).show();
}
return true;
}
@@ -364,41 +355,6 @@ public class ViewKeyActivity extends BaseActivity implements
return true;
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void invokeNfcBeam() {
- // Check if device supports NFC
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
- Notify.createNotify(this, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show();
- return;
- }
- // Check for available NFC Adapter
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
- Notify.createNotify(this, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
- @Override
- public void onAction() {
- Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
- startActivity(intentSettings);
- }
- }, R.string.menu_nfc_preferences).show();
-
- return;
- }
-
- if (!mNfcAdapter.isNdefPushEnabled()) {
- Notify.createNotify(this, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
- @Override
- public void onAction() {
- Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
- startActivity(intentSettings);
- }
- }, R.string.menu_beam_preferences).show();
-
- return;
- }
-
- mNfcAdapter.invokeBeam(this);
- }
private void scanQrCode() {
Intent scanQrCode = new Intent(this, ImportKeysProxyActivity.class);
@@ -415,7 +371,7 @@ public class ViewKeyActivity extends BaseActivity implements
private void certifyImmediate() {
Intent intent = new Intent(this, CertifyKeyActivity.class);
- intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{mMasterKeyId});
+ intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] {mMasterKeyId});
startCertifyIntent(intent);
}
@@ -464,22 +420,32 @@ public class ViewKeyActivity extends BaseActivity implements
ActivityCompat.startActivity(this, qrCodeIntent, opts);
}
- private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper)
- throws ProviderHelper.NotFoundException {
- Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
-
- HashMap<String, Object> data = providerHelper.getGenericData(
- baseUri,
- new String[]{KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
- new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
+ private void startPassphraseActivity(int requestCode) {
+ Intent intent = new Intent(this, PassphraseDialogActivity.class);
+ intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mMasterKeyId);
+ startActivityForResult(intent, requestCode);
+ }
- exportHelper.showExportKeysDialog(
- new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
- Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
- );
+ private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper) {
+ try {
+ Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
+
+ HashMap<String, Object> data = providerHelper.getGenericData(
+ baseUri,
+ new String[] {KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
+ new int[] {ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
+
+ exportHelper.showExportKeysDialog(
+ new long[] {(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
+ Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
+ );
+ } catch (ProviderHelper.NotFoundException e) {
+ Notify.create(this, R.string.error_key_not_found, Notify.Style.ERROR).show();
+ Log.e(Constants.TAG, "Key not found", e);
+ }
}
- private void deleteKey(Uri dataUri, ExportHelper exportHelper) {
+ private void deleteKey() {
// Message is received after key is deleted
Handler returnHandler = new Handler() {
@Override
@@ -491,7 +457,11 @@ public class ViewKeyActivity extends BaseActivity implements
}
};
- exportHelper.deleteKey(dataUri, returnHandler);
+ // 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");
}
@Override
@@ -507,32 +477,27 @@ public class ViewKeyActivity extends BaseActivity implements
String fp = data.getStringExtra(ImportKeysProxyActivity.EXTRA_FINGERPRINT);
if (fp == null) {
- Notify.createNotify(this, "Error scanning fingerprint!",
+ Notify.create(this, "Error scanning fingerprint!",
Notify.LENGTH_LONG, Notify.Style.ERROR).show();
return;
}
if (mFingerprint.equalsIgnoreCase(fp)) {
certifyImmediate();
} else {
- Notify.createNotify(this, "Fingerprints did not match!",
+ Notify.create(this, "Fingerprints did not match!",
Notify.LENGTH_LONG, Notify.Style.ERROR).show();
}
return;
}
- if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){
- deleteKey(mDataUri, mExportHelper);
- }
- if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK){
- try {
- exportToFile(mDataUri, mExportHelper, mProviderHelper);
- } catch (ProviderHelper.NotFoundException e) {
- Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
- Log.e(Constants.TAG, "Key not found", e);
- }
+ if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK) {
+ deleteKey();
}
+ if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK) {
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
+ }
if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
@@ -545,14 +510,14 @@ public class ViewKeyActivity extends BaseActivity implements
private void encrypt(Uri dataUri, boolean text) {
// If there is no encryption key, don't bother.
if (!mHasEncrypt) {
- Notify.showNotify(this, R.string.error_no_encrypt_subkey, Notify.Style.ERROR);
+ Notify.create(this, R.string.error_no_encrypt_subkey, Notify.Style.ERROR).show();
return;
}
try {
long keyId = new ProviderHelper(this)
.getCachedPublicKeyRing(dataUri)
.extractOrGetMasterKeyId();
- long[] encryptionKeyIds = new long[]{keyId};
+ long[] encryptionKeyIds = new long[] {keyId};
Intent intent;
if (text) {
intent = new Intent(this, EncryptTextActivity.class);
@@ -690,98 +655,9 @@ public class ViewKeyActivity extends BaseActivity implements
loadTask.execute();
}
- /**
- * NFC: Initialize NFC sharing if OS and device supports it
- */
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
- private void initNfc(final Uri dataUri) {
- // check if NFC Beam is supported (>= Android 4.1)
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
-
- // Implementation for the CreateNdefMessageCallback interface
- mNdefCallback = new NfcAdapter.CreateNdefMessageCallback() {
- @Override
- public NdefMessage createNdefMessage(NfcEvent event) {
- /*
- * When a device receives a push with an AAR in it, the application specified in the AAR is
- * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
- * guarantee that this activity starts when receiving a beamed message. For now, this code
- * uses the tag dispatch system.
- */
- return new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
- mNfcKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
- }
- };
-
- // Implementation for the OnNdefPushCompleteCallback interface
- mNdefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() {
- @Override
- public void onNdefPushComplete(NfcEvent event) {
- // A handler is needed to send messages to the activity when this
- // callback occurs, because it happens from a binder thread
- mNfcHandler.obtainMessage(NFC_SENT).sendToTarget();
- }
- };
-
- // Check for available NFC Adapter
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if (mNfcAdapter != null) {
- /*
- * Retrieve mNfcKeyringBytes here asynchronously (to not block the UI)
- * and init nfc adapter afterwards.
- * mNfcKeyringBytes can not be retrieved in createNdefMessage, because this process
- * has no permissions to query the Uri.
- */
- AsyncTask<Void, Void, Void> initTask =
- new AsyncTask<Void, Void, Void>() {
- protected Void doInBackground(Void... unused) {
- try {
- Uri blobUri =
- KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
- mNfcKeyringBytes = (byte[]) mProviderHelper.getGenericData(
- blobUri,
- KeychainContract.KeyRingData.KEY_RING_DATA,
- ProviderHelper.FIELD_TYPE_BLOB);
- } catch (ProviderHelper.NotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
-
- // no AsyncTask return (Void)
- return null;
- }
-
- protected void onPostExecute(Void unused) {
- // Register callback to set NDEF message
- mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
- ViewKeyActivity.this);
- // Register callback to listen for message-sent success
- mNfcAdapter.setOnNdefPushCompleteCallback(mNdefCompleteCallback,
- ViewKeyActivity.this);
- }
- };
-
- initTask.execute();
- }
- }
- }
-
- /**
- * NFC: This handler receives a message from onNdefPushComplete
- */
- private final Handler mNfcHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case NFC_SENT:
- Notify.showNotify(
- ViewKeyActivity.this, R.string.nfc_successful, Notify.Style.INFO);
- break;
- }
- }
- };
// These are the rows that we will retrieve.
- static final String[] PROJECTION = new String[]{
+ static final String[] PROJECTION = new String[] {
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
@@ -849,9 +725,9 @@ public class ViewKeyActivity extends BaseActivity implements
startFragment(mIsSecret, fpData);
// get name, email, and comment from USER_ID
- String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
- if (mainUserId[0] != null) {
- mName.setText(mainUserId[0]);
+ KeyRing.UserId mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
+ if (mainUserId.name != null) {
+ mName.setText(mainUserId.name);
} else {
mName.setText(R.string.user_id_no_name);
}
@@ -892,6 +768,7 @@ public class ViewKeyActivity extends BaseActivity implements
} else if (mIsExpired) {
if (mIsSecret) {
mStatusText.setText(R.string.view_key_expired_secret);
+ mName.setText(mainUserId.name);
} else {
mStatusText.setText(R.string.view_key_expired);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
index 0654f0c9a..f17d6e0fd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -197,9 +197,9 @@ public class ViewKeyAdvActivity extends BaseActivity implements
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
// get name, email, and comment from USER_ID
- String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
- if (mainUserId[0] != null) {
- setTitle(mainUserId[0]);
+ KeyRing.UserId mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
+ if (mainUserId.name != null) {
+ setTitle(mainUserId.name);
} else {
setTitle(R.string.user_id_no_name);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java
index 90d7a400f..f5c8a87b1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvCertsFragment.java
@@ -237,9 +237,9 @@ public class ViewKeyAdvCertsFragment extends LoaderFragment implements
TextView wSignStatus = (TextView) view.findViewById(R.id.signStatus);
String signerKeyId = KeyFormattingUtils.beautifyKeyIdWithPrefix(getActivity(), cursor.getLong(mIndexSignerKeyId));
- String[] userId = KeyRing.splitUserId(cursor.getString(mIndexSignerUserId));
- if (userId[0] != null) {
- wSignerName.setText(userId[0]);
+ KeyRing.UserId userId = KeyRing.splitUserId(cursor.getString(mIndexSignerUserId));
+ if (userId.name != null) {
+ wSignerName.setText(userId.name);
} else {
wSignerName.setText(R.string.user_id_no_name);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
index 95a6faea9..6bd3a9303 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.NfcHelper;
import java.io.IOException;
@@ -68,10 +69,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
private View mFingerprintClipboardButton;
private View mKeyShareButton;
private View mKeyClipboardButton;
+ private View mKeyNfcButton;
private ImageButton mKeySafeSlingerButton;
private View mKeyUploadButton;
ProviderHelper mProviderHelper;
+ NfcHelper mNfcHelper;
private static final int LOADER_ID_UNIFIED = 0;
@@ -83,6 +86,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer());
mProviderHelper = new ProviderHelper(ViewKeyAdvShareFragment.this.getActivity());
+ mNfcHelper = new NfcHelper(getActivity(), mProviderHelper);
mFingerprint = (TextView) view.findViewById(R.id.view_key_fingerprint);
mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code);
@@ -90,6 +94,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
mFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
mFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
mKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
+ mKeyNfcButton = view.findViewById(R.id.view_key_action_key_nfc);
mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
mKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger);
mKeyUploadButton = view.findViewById(R.id.view_key_action_upload);
@@ -128,6 +133,14 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
share(mDataUri, mProviderHelper, false, true);
}
});
+
+ mKeyNfcButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mNfcHelper.invokeNfcBeam();
+ }
+ });
+
mKeySafeSlingerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -186,13 +199,13 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
} else {
message = getResources().getString(R.string.key_copied_to_clipboard);
}
- Notify.showNotify(getActivity(), message, Notify.Style.OK);
+ Notify.create(getActivity(), message, Notify.Style.OK).show();
} else {
// Android will fail with android.os.TransactionTooLargeException if key is too big
// see http://www.lonestarprod.com/?p=34
if (content.length() >= 86389) {
- Notify.showNotify(getActivity(), R.string.key_too_big_for_sharing,
- Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.key_too_big_for_sharing,
+ Notify.Style.ERROR).show();
return;
}
@@ -210,10 +223,10 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
}
} catch (PgpGeneralException | IOException e) {
Log.e(Constants.TAG, "error processing key!", e);
- Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.error_key_processing, Notify.Style.ERROR).show();
} catch (ProviderHelper.NotFoundException e) {
Log.e(Constants.TAG, "key not found!", e);
- Notify.showNotify(getActivity(), R.string.error_key_not_found, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.error_key_not_found, Notify.Style.ERROR).show();
}
}
@@ -255,9 +268,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
// Prepare the loaders. Either re-connect with an existing ones,
// or start new ones.
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
+
+ // Prepare the NfcHelper
+ mNfcHelper.initNfc(mDataUri);
}
- static final String[] UNIFIED_PROJECTION = new String[]{
+ static final String[] UNIFIED_PROJECTION = new String[] {
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
KeyRings.USER_ID, KeyRings.FINGERPRINT,
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.IS_EXPIRED,
@@ -362,4 +378,5 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
startActivityForResult(uploadIntent, 0);
}
-}
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
index 429feb075..db88de676 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
@@ -140,25 +140,25 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
// main user id
String userId = entry.getUserIds().get(0);
- String[] userIdSplit = KeyRing.splitUserId(userId);
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
// name
- if (userIdSplit[0] != null) {
+ if (userIdSplit.name != null) {
// show red user id if it is a secret key
if (entry.isSecretKey()) {
holder.mainUserId.setText(mActivity.getString(R.string.secret_key)
- + " " + userIdSplit[0]);
+ + " " + userIdSplit.name);
} else {
- holder.mainUserId.setText(highlighter.highlight(userIdSplit[0]));
+ holder.mainUserId.setText(highlighter.highlight(userIdSplit.name));
}
} else {
holder.mainUserId.setText(R.string.user_id_no_name);
}
// email
- if (userIdSplit[1] != null) {
+ if (userIdSplit.email != null) {
holder.mainUserIdRest.setVisibility(View.VISIBLE);
- holder.mainUserIdRest.setText(highlighter.highlight(userIdSplit[1]));
+ holder.mainUserIdRest.setText(highlighter.highlight(userIdSplit.email));
} else {
holder.mainUserIdRest.setVisibility(View.GONE);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
index 70b57aa93..5218273a0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
@@ -33,7 +33,6 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.util.ArrayList;
@@ -83,9 +82,9 @@ public class MultiUserIdsAdapter extends CursorAdapter {
{ // first one
String userId = uids.get(0);
- String[] splitUserId = KeyRing.splitUserId(userId);
- if (splitUserId[0] != null) {
- vName.setText(splitUserId[0]);
+ KeyRing.UserId splitUserId = KeyRing.splitUserId(userId);
+ if (splitUserId.name != null) {
+ vName.setText(splitUserId.name);
} else {
vName.setText(R.string.user_id_no_name);
}
@@ -93,9 +92,9 @@ public class MultiUserIdsAdapter extends CursorAdapter {
if (isHeader == 1) {
vHeaderId.setVisibility(View.VISIBLE);
String message;
- if (splitUserId[0] != null) {
+ if (splitUserId.name != null) {
message = mContext.getString(R.string.section_uids_to_certify) +
- splitUserId[0];
+ splitUserId.name;
} else {
message = mContext.getString(R.string.section_uids_to_certify) +
context.getString(R.string.user_id_no_name);
@@ -108,13 +107,13 @@ public class MultiUserIdsAdapter extends CursorAdapter {
StringBuilder lines = new StringBuilder();
for (String uid : uids) {
- String[] splitUserId = KeyRing.splitUserId(uid);
- if (splitUserId[1] == null) {
+ KeyRing.UserId splitUserId = KeyRing.splitUserId(uid);
+ if (splitUserId.email == null) {
continue;
}
- lines.append(splitUserId[1]);
- if (splitUserId[2] != null) {
- lines.append(" (").append(splitUserId[2]).append(")");
+ lines.append(splitUserId.email);
+ if (splitUserId.comment != null) {
+ lines.append(" (").append(splitUserId.comment).append(")");
}
lines.append('\n');
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
index 892e30a54..3308a4500 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -122,16 +122,16 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
ViewHolderItem h = (ViewHolderItem) view.getTag();
String userId = cursor.getString(mIndexUserId);
- String[] userIdSplit = KeyRing.splitUserId(userId);
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
- if (userIdSplit[0] != null) {
- h.mainUserId.setText(highlighter.highlight(userIdSplit[0]));
+ if (userIdSplit.name != null) {
+ h.mainUserId.setText(highlighter.highlight(userIdSplit.name));
} else {
h.mainUserId.setText(R.string.user_id_no_name);
}
- if (userIdSplit[1] != null) {
+ if (userIdSplit.email != null) {
h.mainUserIdRest.setVisibility(View.VISIBLE);
- h.mainUserIdRest.setText(highlighter.highlight(userIdSplit[1]));
+ h.mainUserIdRest.setText(highlighter.highlight(userIdSplit.email));
} else {
h.mainUserIdRest.setVisibility(View.GONE);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
index 1cf3f4d38..c68c078ad 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java
@@ -72,20 +72,20 @@ public class UserIdsAdapter extends UserAttributesAdapter {
vDeleteButton.setVisibility(View.GONE); // not used
String userId = cursor.getString(INDEX_USER_ID);
- String[] splitUserId = KeyRing.splitUserId(userId);
- if (splitUserId[0] != null) {
- vName.setText(splitUserId[0]);
+ KeyRing.UserId splitUserId = KeyRing.splitUserId(userId);
+ if (splitUserId.name != null) {
+ vName.setText(splitUserId.name);
} else {
vName.setText(R.string.user_id_no_name);
}
- if (splitUserId[1] != null) {
- vAddress.setText(splitUserId[1]);
+ if (splitUserId.email != null) {
+ vAddress.setText(splitUserId.email);
vAddress.setVisibility(View.VISIBLE);
} else {
vAddress.setVisibility(View.GONE);
}
- if (splitUserId[2] != null) {
- vComment.setText(splitUserId[2]);
+ if (splitUserId.comment != null) {
+ vComment.setText(splitUserId.comment);
vComment.setVisibility(View.VISIBLE);
} else {
vComment.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
index 970855c77..c7197b46d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java
@@ -92,20 +92,20 @@ public class UserIdsAddedAdapter extends ArrayAdapter<String> {
// save reference to model item
holder.mModel = getItem(position);
- String[] splitUserId = KeyRing.splitUserId(holder.mModel);
- if (splitUserId[0] != null) {
- holder.vName.setText(splitUserId[0]);
+ KeyRing.UserId splitUserId = KeyRing.splitUserId(holder.mModel);
+ if (splitUserId.name != null) {
+ holder.vName.setText(splitUserId.name);
} else {
holder.vName.setText(R.string.user_id_no_name);
}
- if (splitUserId[1] != null) {
- holder.vAddress.setText(splitUserId[1]);
+ if (splitUserId.email != null) {
+ holder.vAddress.setText(splitUserId.email);
holder.vAddress.setVisibility(View.VISIBLE);
} else {
holder.vAddress.setVisibility(View.GONE);
}
- if (splitUserId[2] != null) {
- holder.vComment.setText(splitUserId[2]);
+ if (splitUserId.comment != null) {
+ holder.vComment.setText(splitUserId.comment);
holder.vComment.setVisibility(View.VISIBLE);
} else {
holder.vComment.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
index 5dd675fd3..fe4ba0262 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
@@ -100,8 +100,8 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
// return new user id back to activity
Bundle data = new Bundle();
- String userId = KeyRing.createUserId(mName.getText().toString(),
- mEmail.getText().toString(), mComment.getText().toString());
+ String userId = KeyRing.createUserId(new KeyRing.UserId(mName.getText().toString(),
+ mEmail.getText().toString(), mComment.getText().toString()));
data.putString(MESSAGE_DATA_USER_ID, userId);
sendMessageToHandler(MESSAGE_OKAY, data);
}
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
index 20f20c32e..f512ecca2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -100,9 +100,9 @@ public class DeleteKeyDialogFragment extends DialogFragment {
}
);
String name;
- String[] mainUserId = KeyRing.splitUserId((String) data.get(KeyRings.USER_ID));
- if (mainUserId[0] != null) {
- name = mainUserId[0];
+ 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);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
index 7ac85781f..63b6d26ac 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
@@ -190,7 +190,7 @@ public class FileDialogFragment extends DialogFragment {
mFile = file;
mFilename.setText(mFile.getName());
} else {
- Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.no_file_selected, Notify.Style.ERROR).show();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
index b34dc2edc..947c316e0 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "messenger";
@@ -67,12 +68,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
* @param messenger to communicate back after setting the passphrase
* @return
*/
- public static SetPassphraseDialogFragment newInstance(Messenger messenger, String oldPassphrase, int title) {
+ public static SetPassphraseDialogFragment newInstance(Messenger messenger, Passphrase oldPassphrase, int title) {
SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment();
Bundle args = new Bundle();
args.putInt(ARG_TITLE, title);
args.putParcelable(ARG_MESSENGER, messenger);
- args.putString(ARG_OLD_PASSPHRASE, oldPassphrase);
+ args.putParcelable(ARG_OLD_PASSPHRASE, oldPassphrase);
frag.setArguments(args);
@@ -88,7 +89,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
int title = getArguments().getInt(ARG_TITLE);
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
- String oldPassphrase = getArguments().getString(ARG_OLD_PASSPHRASE);
+ Passphrase oldPassphrase = getArguments().getParcelable(ARG_OLD_PASSPHRASE);
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
@@ -103,7 +104,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
- if (TextUtils.isEmpty(oldPassphrase)) {
+ if (oldPassphrase.isEmpty()) {
mNoPassphraseCheckBox.setChecked(true);
mPassphraseEditText.setEnabled(false);
mPassphraseAgainEditText.setEnabled(false);
@@ -123,12 +124,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
public void onClick(DialogInterface dialog, int id) {
dismiss();
- String passphrase1;
+ Passphrase passphrase1 = new Passphrase();
if (mNoPassphraseCheckBox.isChecked()) {
- passphrase1 = "";
+ passphrase1.setEmpty();
} else {
- passphrase1 = mPassphraseEditText.getText().toString();
- String passphrase2 = mPassphraseAgainEditText.getText().toString();
+ passphrase1 = new Passphrase(mPassphraseEditText);
+ Passphrase passphrase2 = new Passphrase(mPassphraseAgainEditText);
if (!passphrase1.equals(passphrase2)) {
Toast.makeText(
activity,
@@ -139,7 +140,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
return;
}
- if (passphrase1.equals("")) {
+ if (passphrase1.isEmpty()) {
Toast.makeText(
activity,
getString(R.string.error_message,
@@ -152,7 +153,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
// return resulting data back to activity
Bundle data = new Bundle();
- data.putString(MESSAGE_NEW_PASSPHRASE, passphrase1);
+ data.putParcelable(MESSAGE_NEW_PASSPHRASE, passphrase1);
sendMessageToHandler(MESSAGE_OKAY, data);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java
index 2e6181f07..c0e2fd29c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateDnsStep2Fragment.java
@@ -118,7 +118,7 @@ public class LinkedIdCreateDnsStep2Fragment extends LinkedIdCreateFinalFragment
private void proofToClipboard() {
ClipboardReflection.copyToClipboard(getActivity(), mResourceString);
- Notify.showNotify(getActivity(), R.string.linked_text_clipboard, Notify.Style.OK);
+ Notify.create(getActivity(), R.string.linked_text_clipboard, Notify.Style.OK).show();
}
private void saveFile(Uri uri) {
@@ -127,10 +127,10 @@ public class LinkedIdCreateDnsStep2Fragment extends LinkedIdCreateFinalFragment
new PrintWriter(getActivity().getContentResolver().openOutputStream(uri));
out.print(mResourceString);
if (out.checkError()) {
- Notify.showNotify(getActivity(), "Error writing file!", Style.ERROR);
+ Notify.create(getActivity(), "Error writing file!", Style.ERROR).show();
}
} catch (FileNotFoundException e) {
- Notify.showNotify(getActivity(), "File could not be opened for writing!", Style.ERROR);
+ Notify.create(getActivity(), "File could not be opened for writing!", Style.ERROR).show();
e.printStackTrace();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
index 28fbe6f19..99e770857 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateFinalFragment.java
@@ -168,7 +168,7 @@ public abstract class LinkedIdCreateFinalFragment extends Fragment {
private void startCertify() {
if (mVerifiedResource == null) {
- Notify.showNotify(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR);
+ Notify.create(getActivity(), R.string.linked_need_verify, Notify.Style.ERROR).show();
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubStep1Fragment.java
index 86a514fa9..77eccf3be 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubStep1Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateGithubStep1Fragment.java
@@ -80,14 +80,14 @@ public class LinkedIdCreateGithubStep1Fragment extends Fragment {
super.onPostExecute(result);
if (result == null) {
- Notify.showNotify(getActivity(),
- "Connection error while checking username!", Notify.Style.ERROR);
+ Notify.create(getActivity(),
+ "Connection error while checking username!", Notify.Style.ERROR).show();
return;
}
if (!result) {
- Notify.showNotify(getActivity(),
- "This handle does not exist on Github!", Notify.Style.ERROR);
+ Notify.create(getActivity(),
+ "This handle does not exist on Github!", Notify.Style.ERROR).show();
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
index 55ac6e075..5559c0daf 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateHttpsStep2Fragment.java
@@ -125,7 +125,7 @@ public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragmen
private void proofSave () {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
- Notify.showNotify(getActivity(), "External storage not available!", Style.ERROR);
+ Notify.create(getActivity(), "External storage not available!", Style.ERROR);
return;
}
@@ -146,11 +146,10 @@ public class LinkedIdCreateHttpsStep2Fragment extends LinkedIdCreateFinalFragmen
new PrintWriter(getActivity().getContentResolver().openOutputStream(uri));
out.print(mResourceString);
if (out.checkError()) {
- Notify.showNotify(getActivity(), "Error writing file!", Style.ERROR);
+ Notify.create(getActivity(), "Error writing file!", Style.ERROR).show();
}
} catch (FileNotFoundException e) {
- Notify.showNotify(getActivity(), "File could not be opened for writing!", Style.ERROR);
- e.printStackTrace();
+ Notify.create(getActivity(), "File could not be opened for writing!", Style.ERROR).show();
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
index c22351f87..c36f98058 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdCreateTwitterStep1Fragment.java
@@ -78,13 +78,13 @@ public class LinkedIdCreateTwitterStep1Fragment extends Fragment {
super.onPostExecute(result);
if (result == null) {
- Notify.showNotify(getActivity(),
+ Notify.create(getActivity(),
"Connection error while checking username!", Notify.Style.ERROR);
return;
}
if (!result) {
- Notify.showNotify(getActivity(),
+ Notify.create(getActivity(),
"This handle does not exist on Twitter!", Notify.Style.ERROR);
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
index 502abe8e6..41d0178a3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java
@@ -55,6 +55,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.ui.widget.CertListWidget;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.Passphrase;
public class LinkedIdViewFragment extends Fragment implements
@@ -153,7 +154,7 @@ public class LinkedIdViewFragment extends Fragment implements
} catch (IOException e) {
Log.e(Constants.TAG, "error parsing identity", e);
- Notify.createNotify(getActivity(), "Error parsing identity!",
+ Notify.create(getActivity(), "Error parsing identity!",
Notify.LENGTH_LONG, Style.ERROR).show();
finishFragment();
}
@@ -492,7 +493,7 @@ public class LinkedIdViewFragment extends Fragment implements
}
// get the user's passphrase for this key (if required)
- String passphrase;
+ Passphrase passphrase;
long certifyKeyId = mViewHolder.vKeySpinner.getSelectedItemId();
try {
passphrase = PassphraseCacheService.getCachedPassphrase(
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
index 3bc29edb6..7e07ed818 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java
@@ -18,7 +18,9 @@
package org.sufficientlysecure.keychain.ui.util;
import android.app.Activity;
-import android.content.res.Resources;
+import android.support.v4.app.Fragment;
+import android.view.View;
+import android.view.ViewGroup;
import com.nispok.snackbar.Snackbar;
import com.nispok.snackbar.Snackbar.SnackbarDuration;
@@ -35,157 +37,147 @@ import org.sufficientlysecure.keychain.util.FabContainer;
*/
public class Notify {
- public static enum Style {OK, WARN, INFO, ERROR}
+ public static enum Style {
+ OK, WARN, ERROR;
+
+ public void applyToBar(Snackbar bar) {
+
+ switch (this) {
+ case OK:
+ // bar.actionColorResource(R.color.android_green_light);
+ bar.lineColorResource(R.color.android_green_light);
+ break;
+ case WARN:
+ // bar.textColorResource(R.color.android_orange_light);
+ bar.lineColorResource(R.color.android_orange_light);
+ break;
+ case ERROR:
+ // bar.textColorResource(R.color.android_red_light);
+ bar.lineColorResource(R.color.android_red_light);
+ break;
+ }
+
+ }
+ }
public static final int LENGTH_INDEFINITE = 0;
public static final int LENGTH_LONG = 3500;
- /**
- * Shows a simple in-layout notification with the CharSequence given as parameter
- * @param text Text to show
- * @param style Notification styling
- */
- public static void showNotify(final Activity activity, CharSequence text, Style style) {
-
- Snackbar bar = getSnackbar(activity)
+ public static Showable create(final Activity activity, String text, int duration, Style style,
+ final ActionListener actionListener, int actionResId) {
+ final Snackbar snackbar = Snackbar.with(activity)
+ .type(SnackbarType.MULTI_LINE)
.text(text);
- switch (style) {
- case OK:
- break;
- case WARN:
- bar.textColor(activity.getResources().getColor(R.color.android_orange_light));
- break;
- case ERROR:
- bar.textColor(activity.getResources().getColor(R.color.android_red_light));
- break;
- }
-
- SnackbarManager.show(bar);
-
- }
-
- public static Showable createNotify (Activity activity, int resId, int duration, Style style) {
- final Snackbar bar = getSnackbar(activity)
- .text(resId);
-
if (duration == LENGTH_INDEFINITE) {
- bar.duration(SnackbarDuration.LENGTH_INDEFINITE);
+ snackbar.duration(SnackbarDuration.LENGTH_INDEFINITE);
} else {
- bar.duration(duration);
+ snackbar.duration(duration);
}
- switch (style) {
- case OK:
- bar.actionColor(activity.getResources().getColor(R.color.android_green_light));
- break;
- case WARN:
- bar.textColor(activity.getResources().getColor(R.color.android_orange_light));
- break;
- case ERROR:
- bar.textColor(activity.getResources().getColor(R.color.android_red_light));
- break;
- }
-
- return new Showable () {
- @Override
- public void show() {
- SnackbarManager.show(bar);
- }
- };
- }
-
- public static Showable createNotify(Activity activity, int resId, int duration, Style style,
- final ActionListener listener, int resIdAction) {
- return createNotify(activity, activity.getString(resId), duration, style, listener, resIdAction);
- }
-
- public static Showable createNotify(Activity activity, String msg, int duration, Style style) {
- return createNotify(activity, msg, duration, style, null, 0);
- }
+ style.applyToBar(snackbar);
- public static Showable createNotify(Activity activity, String msg, int duration, Style style,
- final ActionListener listener, int resIdAction) {
+ if (actionListener != null) {
+ snackbar.actionLabel(actionResId)
+ .actionListener(new ActionClickListener() {
+ @Override
+ public void onActionClicked(Snackbar snackbar) {
+ actionListener.onAction();
+ }
+ });
+ }
- final Snackbar bar = getSnackbar(activity)
- .text(msg);
+ if (activity instanceof FabContainer) {
+ snackbar.eventListener(new EventListenerAdapter() {
+ @Override
+ public void onShow(Snackbar snackbar) {
+ ((FabContainer) activity).fabMoveUp(snackbar.getHeight());
+ }
- if (listener != null) {
- bar.actionLabel(resIdAction);
- bar.actionListener(new ActionClickListener() {
@Override
- public void onActionClicked(Snackbar snackbar) {
- listener.onAction();
+ public void onDismiss(Snackbar snackbar) {
+ ((FabContainer) activity).fabRestorePosition();
}
});
}
- if (duration == LENGTH_INDEFINITE) {
- bar.duration(SnackbarDuration.LENGTH_INDEFINITE);
- } else {
- bar.duration(duration);
- }
+ return new Showable() {
+ @Override
+ public void show() {
+ SnackbarManager.show(snackbar, activity);
+ }
- switch (style) {
- case OK:
- bar.actionColor(activity.getResources().getColor(R.color.android_green_light));
- break;
- case WARN:
- bar.textColor(activity.getResources().getColor(R.color.android_orange_light));
- break;
- case ERROR:
- bar.textColor(activity.getResources().getColor(R.color.android_red_light));
- break;
- }
+ @Override
+ public void show(Fragment fragment) {
+ if (fragment != null) {
+ View view = fragment.getView();
+
+ if (view != null && view instanceof ViewGroup) {
+ SnackbarManager.show(snackbar, (ViewGroup) view);
+ return;
+ }
+ }
+
+ show();
+ }
- return new Showable () {
@Override
- public void show() {
- SnackbarManager.show(bar);
+ public void show(ViewGroup viewGroup) {
+ if (viewGroup != null) {
+ SnackbarManager.show(snackbar, viewGroup);
+ return;
+ }
+
+ show();
}
};
+ }
+ public static Showable create(Activity activity, String text, int duration, Style style) {
+ return create(activity, text, duration, style, null, -1);
}
- /**
- * Shows a simple in-layout notification with the resource text from given id
- * @param resId ResourceId of notification text
- * @param style Notification styling
- * @throws Resources.NotFoundException
- */
- public static void showNotify(Activity activity, int resId, Style style) throws Resources.NotFoundException {
- showNotify(activity, activity.getResources().getText(resId), style);
+ public static Showable create(Activity activity, String text, Style style) {
+ return create(activity, text, LENGTH_LONG, style);
}
- private static Snackbar getSnackbar(final Activity activity) {
- Snackbar bar = Snackbar.with(activity)
- .type(SnackbarType.MULTI_LINE)
- .duration(SnackbarDuration.LENGTH_LONG);
+ public static Showable create(Activity activity, int textResId, int duration, Style style,
+ ActionListener actionListener, int actionResId) {
+ return create(activity, activity.getString(textResId), duration, style, actionListener, actionResId);
+ }
- if (activity instanceof FabContainer) {
- bar.eventListener(new EventListenerAdapter() {
- @Override
- public void onShow(Snackbar snackbar) {
- ((FabContainer) activity).fabMoveUp(snackbar.getHeight());
- }
+ public static Showable create(Activity activity, int textResId, int duration, Style style) {
+ return create(activity, activity.getString(textResId), duration, style);
+ }
- @Override
- public void onDismiss(Snackbar snackbar) {
- ((FabContainer) activity).fabRestorePosition();
- }
- });
- }
- return bar;
+ public static Showable create(Activity activity, int textResId, Style style) {
+ return create(activity, activity.getString(textResId), style);
}
public interface Showable {
+
+ /**
+ * Shows the notification on the bottom of the Activity.
+ */
public void show();
+ /**
+ * Shows the notification on the bottom of the Fragment.
+ */
+ public void show(Fragment fragment);
+
+ /**
+ * Shows the notification on the given ViewGroup.
+ * The viewGroup should be either a RelativeLayout or FrameLayout.
+ */
+ public void show(ViewGroup viewGroup);
+
}
public interface ActionListener {
+
public void onAction();
}
-} \ No newline at end of file
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
index 1bdec7b84..e21c5d510 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
@@ -58,9 +58,10 @@ public class EmailEditText extends AutoCompleteTextView {
}
private void init() {
- this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
- this.addTextChangedListener(textWatcher);
- removeFlag();
+ setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ reenableKeyboardSuggestions();
+
+ addTextChangedListener(textWatcher);
initAdapter();
}
@@ -104,7 +105,7 @@ public class EmailEditText extends AutoCompleteTextView {
* Hack to re-enable keyboard auto correction in AutoCompleteTextView.
* From http://stackoverflow.com/a/22512858
*/
- private void removeFlag() {
+ private void reenableKeyboardSuggestions() {
int inputType = getInputType();
inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
setRawInputType(inputType);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
index 94a321f29..ceace1d26 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
@@ -184,7 +184,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView {
public class EncryptionKey {
private String mUserIdFull;
- private String[] mUserId;
+ private KeyRing.UserId mUserId;
private long mKeyId;
private boolean mHasDuplicate;
private Date mCreation;
@@ -222,23 +222,23 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView {
}
public String getPrimary() {
- if (mUserId[0] != null) {
- return mUserId[0];
+ if (mUserId.name != null) {
+ return mUserId.name;
} else {
- return mUserId[1];
+ return mUserId.email;
}
}
public String getSecondary() {
- if (mUserId[1] != null) {
- return mUserId[1];
+ if (mUserId.email != null) {
+ return mUserId.email;
} else {
return getCreationDate();
}
}
public String getTertiary() {
- if (mUserId[0] != null) {
+ if (mUserId.name != null) {
return getCreationDate();
} else {
return null;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
index aeb013c71..70f4e7792 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
@@ -39,7 +39,6 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.util.Log;
import java.util.Calendar;
@@ -158,9 +157,9 @@ public abstract class KeySpinner extends TintSpinner implements LoaderManager.Lo
TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email);
TextView vDuplicate = (TextView) view.findViewById(R.id.keyspinner_duplicate);
- String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId));
- vKeyName.setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")"));
- vKeyEmail.setText(userId[1]);
+ KeyRing.UserId userId = KeyRing.splitUserId(cursor.getString(mIndexUserId));
+ vKeyName.setText(userId.name);
+ vKeyEmail.setText(userId.email);
boolean duplicate = cursor.getLong(mIndexDuplicate) > 0;
if (duplicate) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
index f086c5696..153bf2ff2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java
@@ -50,7 +50,7 @@ public class NameEditText extends AutoCompleteTextView {
}
private void init() {
- removeFlag();
+ reenableKeyboardSuggestions();
initAdapter();
}
@@ -62,10 +62,10 @@ public class NameEditText extends AutoCompleteTextView {
}
/**
- * Hack to re-enable keyboard auto correction in AutoCompleteTextView.
+ * Hack to re-enable keyboard suggestions in AutoCompleteTextView.
* From http://stackoverflow.com/a/22512858
*/
- private void removeFlag() {
+ private void reenableKeyboardSuggestions() {
int inputType = getInputType();
inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
setRawInputType(inputType);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
index 6efc0a5ea..c782d2507 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -19,7 +19,6 @@ package org.sufficientlysecure.keychain.util;
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.annotation.TargetApi;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -28,7 +27,6 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.os.Build;
import android.provider.ContactsContract;
import android.util.Patterns;
@@ -37,7 +35,6 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
-import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import java.io.InputStream;
import java.util.ArrayList;
@@ -303,10 +300,9 @@ public class ContactHelper {
return new ArrayList<>(names);
}
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static Uri dataUriFromContactUri(Context context, Uri contactUri) {
Cursor contactMasterKey = context.getContentResolver().query(contactUri,
- new String[]{ContactsContract.Data.DATA2}, null, null, null, null);
+ new String[]{ContactsContract.Data.DATA2}, null, null, null);
if (contactMasterKey != null) {
if (contactMasterKey.moveToNext()) {
return KeychainContract.KeyRings.buildGenericKeyRingUri(contactMasterKey.getLong(0));
@@ -447,7 +443,7 @@ public class ContactHelper {
if (cursor != null) {
while (cursor.moveToNext()) {
long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
- String[] userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID));
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID));
boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0;
@@ -470,19 +466,19 @@ public class ContactHelper {
if (rawContactId != -1) {
deleteRawContactById(resolver, rawContactId);
}
- } else if (userIdSplit[0] != null) {
+ } else if (userIdSplit.name != null) {
// Create a new rawcontact with corresponding key if it does not exist yet
if (rawContactId == -1) {
Log.d(Constants.TAG, "Insert new raw contact with masterKeyId " + masterKeyId);
insertContact(ops, context, masterKeyId);
- writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit[0]);
+ writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit.name);
}
// We always update the display name (which is derived from primary user id)
// and email addresses from user id
- writeContactDisplayName(ops, rawContactId, userIdSplit[0]);
+ writeContactDisplayName(ops, rawContactId, userIdSplit.name);
writeContactEmail(ops, resolver, rawContactId, masterKeyId);
try {
resolver.applyBatch(ContactsContract.AUTHORITY, ops);
@@ -521,9 +517,9 @@ public class ContactHelper {
long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
- String[] userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID));
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(cursor.getString(INDEX_USER_ID));
- if (!isExpired && !isRevoked && userIdSplit[0] != null) {
+ if (!isExpired && !isRevoked && userIdSplit.name != null) {
// if expired or revoked will not be removed from keysToDelete or inserted
// into main profile ("me" contact)
boolean existsInMainProfile = keysToDelete.remove(masterKeyId);
@@ -534,7 +530,7 @@ public class ContactHelper {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
insertMainProfileRawContact(ops, masterKeyId);
- writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit[0]);
+ writeContactKey(ops, context, rawContactId, masterKeyId, userIdSplit.name);
try {
resolver.applyBatch(ContactsContract.AUTHORITY, ops);
@@ -715,7 +711,6 @@ public class ContactHelper {
*
* @return raw contact id or -1 if not found
*/
- @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private static long findRawContactId(ContentResolver resolver, long masterKeyId) {
long rawContactId = -1;
Cursor raw = resolver.query(ContactsContract.RawContacts.CONTENT_URI,
@@ -725,7 +720,7 @@ public class ContactHelper {
ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " + ContactsContract.RawContacts.SOURCE_ID + "=?",
new String[]{
Constants.ACCOUNT_TYPE, Long.toString(masterKeyId)
- }, null, null);
+ }, null);
if (raw != null) {
if (raw.moveToNext()) {
rawContactId = raw.getLong(0);
@@ -776,14 +771,14 @@ public class ContactHelper {
null, null);
if (ids != null) {
while (ids.moveToNext()) {
- String[] userId = KeyRing.splitUserId(ids.getString(0));
- if (userId[1] != null) {
+ KeyRing.UserId userId = KeyRing.splitUserId(ids.getString(0));
+ if (userId.email != null) {
ops.add(referenceRawContact(
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI),
rawContactId)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Email.DATA, userId[1])
+ .withValue(ContactsContract.CommonDataKinds.Email.DATA, userId.email)
.build());
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
index cda5892fe..7b164f2b2 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ExportHelper.java
@@ -47,21 +47,6 @@ public class ExportHelper {
this.mActivity = activity;
}
- public void deleteKey(Uri dataUri, Handler deleteHandler) {
- try {
- long masterKeyId = new ProviderHelper(mActivity).getCachedPublicKeyRing(dataUri)
- .extractOrGetMasterKeyId();
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(deleteHandler);
- DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
- new long[]{ masterKeyId });
- deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog");
- } catch (PgpKeyNotFoundException e) {
- Log.e(Constants.TAG, "key not found!", e);
- }
- }
-
/**
* Show dialog where to export keys
*/
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
new file mode 100644
index 000000000..e4e4e4d05
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2015 Kent Nguyen <kentnguyen@moneylover.me>
+ *
+ * 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.util;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcEvent;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * This class contains NFC functionality that can be shared across Fragments or Activities.
+ */
+
+public class NfcHelper {
+
+ private Activity mActivity;
+ private ProviderHelper mProviderHelper;
+
+ /**
+ * NFC: This handler receives a message from onNdefPushComplete
+ */
+ private static NfcHandler mNfcHandler;
+
+ private NfcAdapter mNfcAdapter;
+ private NfcAdapter.CreateNdefMessageCallback mNdefCallback;
+ private NfcAdapter.OnNdefPushCompleteCallback mNdefCompleteCallback;
+ private byte[] mNfcKeyringBytes;
+ private static final int NFC_SENT = 1;
+
+ /**
+ * Initializes the NfcHelper.
+ */
+ public NfcHelper(final Activity activity, final ProviderHelper providerHelper) {
+ mActivity = activity;
+ mProviderHelper = providerHelper;
+
+ mNfcHandler = new NfcHandler(mActivity);
+ }
+
+ /**
+ * Return true if the NFC Adapter of this Helper has any features enabled.
+ *
+ * @return true if this NFC Adapter has any features enabled
+ */
+ public boolean isEnabled() {
+ return mNfcAdapter.isEnabled();
+ }
+
+ /**
+ * NFC: Initialize NFC sharing if OS and device supports it
+ */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+ public void initNfc(final Uri dataUri) {
+ // check if NFC Beam is supported (>= Android 4.1)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+
+ // Implementation for the CreateNdefMessageCallback interface
+ mNdefCallback = new NfcAdapter.CreateNdefMessageCallback() {
+ @Override
+ public NdefMessage createNdefMessage(NfcEvent event) {
+ /*
+ * When a device receives a push with an AAR in it, the application specified in the AAR is
+ * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
+ * guarantee that this activity starts when receiving a beamed message. For now, this code
+ * uses the tag dispatch system.
+ */
+ return new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
+ mNfcKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
+ }
+ };
+
+ // Implementation for the OnNdefPushCompleteCallback interface
+ mNdefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() {
+ @Override
+ public void onNdefPushComplete(NfcEvent event) {
+ // A handler is needed to send messages to the activity when this
+ // callback occurs, because it happens from a binder thread
+ mNfcHandler.obtainMessage(NFC_SENT).sendToTarget();
+ }
+ };
+
+ // Check for available NFC Adapter
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
+ if (mNfcAdapter != null) {
+ /*
+ * Retrieve mNfcKeyringBytes here asynchronously (to not block the UI)
+ * and init nfc adapter afterwards.
+ * mNfcKeyringBytes can not be retrieved in createNdefMessage, because this process
+ * has no permissions to query the Uri.
+ */
+ AsyncTask<Void, Void, Void> initTask =
+ new AsyncTask<Void, Void, Void>() {
+ protected Void doInBackground(Void... unused) {
+ try {
+ Uri blobUri =
+ KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
+ mNfcKeyringBytes = (byte[]) mProviderHelper.getGenericData(
+ blobUri,
+ KeychainContract.KeyRingData.KEY_RING_DATA,
+ ProviderHelper.FIELD_TYPE_BLOB);
+ } catch (ProviderHelper.NotFoundException e) {
+ Log.e(Constants.TAG, "key not found!", e);
+ }
+
+ // no AsyncTask return (Void)
+ return null;
+ }
+
+ protected void onPostExecute(Void unused) {
+ // Register callback to set NDEF message
+ mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
+ mActivity);
+ // Register callback to listen for message-sent success
+ mNfcAdapter.setOnNdefPushCompleteCallback(mNdefCompleteCallback,
+ mActivity);
+ }
+ };
+
+ initTask.execute();
+ }
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public void invokeNfcBeam() {
+ // Check if device supports NFC
+ if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
+ Notify.create(mActivity, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show();
+ return;
+ }
+ // Check for available NFC Adapter
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity);
+ if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
+ Notify.create(mActivity, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
+ mActivity.startActivity(intentSettings);
+ }
+ }, R.string.menu_nfc_preferences).show();
+
+ return;
+ }
+
+ if (!mNfcAdapter.isNdefPushEnabled()) {
+ Notify.create(mActivity, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
+ @Override
+ public void onAction() {
+ Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
+ mActivity.startActivity(intentSettings);
+ }
+ }, R.string.menu_beam_preferences).show();
+
+ return;
+ }
+
+ mNfcAdapter.invokeBeam(mActivity);
+ }
+
+ /**
+ * A static subclass of {@link Handler} with a {@link WeakReference} to an {@link Activity} to avoid memory leaks.
+ */
+ private static class NfcHandler extends Handler {
+ private final WeakReference<Activity> mActivityReference;
+
+ public NfcHandler(Activity activity) {
+ mActivityReference = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ Activity activity = mActivityReference.get();
+
+ if (activity != null) {
+ switch (msg.what) {
+ case NFC_SENT:
+ Notify.create(activity, R.string.nfc_successful, Notify.Style.OK).show();
+ break;
+ }
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
new file mode 100644
index 000000000..06efdde4d
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2015 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.util;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.Editable;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.Constants;
+
+import java.util.Arrays;
+
+/**
+ * Passwords should not be stored as Strings in memory.
+ * This class wraps a char[] that can be erased after it is no longer used.
+ * See also:
+ * <p/>
+ * http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#PBEEx
+ * https://github.com/c-a-m/passfault/blob/master/core/src/main/java/org/owasp/passfault/SecureString.java
+ * http://stackoverflow.com/q/8881291
+ * http://stackoverflow.com/a/15844273
+ */
+public class Passphrase implements Parcelable {
+ private char[] mPassphrase;
+
+ /**
+ * According to http://stackoverflow.com/a/15844273 EditText is not using String internally
+ * but char[]. Thus, we can get the char[] directly from it.
+ */
+ public Passphrase(Editable editable) {
+ int pl = editable.length();
+ mPassphrase = new char[pl];
+ editable.getChars(0, pl, mPassphrase, 0);
+ // TODO: clean up internal char[] of EditText after getting the passphrase?
+// editText.getText().replace()
+ }
+
+ public Passphrase(EditText editText) {
+ this(editText.getText());
+ }
+
+ public Passphrase(char[] passphrase) {
+ mPassphrase = passphrase;
+ }
+
+ public Passphrase(String passphrase) {
+ mPassphrase = passphrase.toCharArray();
+ }
+
+ /**
+ * Creates a passphrase object with an empty ("") passphrase
+ */
+ public Passphrase() {
+ setEmpty();
+ }
+
+ public char[] getCharArray() {
+ return mPassphrase;
+ }
+
+ public void setEmpty() {
+ removeFromMemory();
+ mPassphrase = new char[0];
+ }
+
+ public boolean isEmpty() {
+ return (length() == 0);
+ }
+
+ public int length() {
+ return mPassphrase.length;
+ }
+
+ public char charAt(int index) {
+ return mPassphrase[index];
+ }
+
+ /**
+ * Manually clear the underlying array holding the characters
+ */
+ public void removeFromMemory() {
+ if (mPassphrase != null) {
+ Arrays.fill(mPassphrase, ' ');
+ }
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ removeFromMemory();
+ super.finalize();
+ }
+
+ @Override
+ public String toString() {
+ if (Constants.DEBUG) {
+ return "Passphrase{" +
+ "mPassphrase=" + Arrays.toString(mPassphrase) +
+ '}';
+ } else {
+ return "Passphrase: hidden";
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ Passphrase that = (Passphrase) o;
+ if (!Arrays.equals(mPassphrase, that.mPassphrase)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mPassphrase != null ? Arrays.hashCode(mPassphrase) : 0;
+ }
+
+ private Passphrase(Parcel source) {
+ mPassphrase = source.createCharArray();
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharArray(mPassphrase);
+ }
+
+ public static final Creator<Passphrase> CREATOR = new Creator<Passphrase>() {
+ public Passphrase createFromParcel(final Parcel source) {
+ return new Passphrase(source);
+ }
+
+ public Passphrase[] newArray(final int size) {
+ return new Passphrase[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+}