aboutsummaryrefslogtreecommitdiffstats
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
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
-rw-r--r--.gitmodules3
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java9
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java9
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java3
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java53
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java14
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java25
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java5
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java19
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java3
-rw-r--r--OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java23
-rw-r--r--OpenKeychain/build.gradle4
-rw-r--r--OpenKeychain/src/main/AndroidManifest.xml35
-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
-rw-r--r--OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.pngbin0 -> 1059 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.pngbin0 -> 701 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.pngbin0 -> 1359 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.pngbin0 -> 2040 bytes
-rw-r--r--OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.pngbin0 -> 2756 bytes
-rw-r--r--OpenKeychain/src/main/res/layout/api_select_sign_key_activity.xml22
-rw-r--r--OpenKeychain/src/main/res/layout/create_key_name_fragment.xml4
-rw-r--r--OpenKeychain/src/main/res/layout/create_key_start_fragment.xml104
-rw-r--r--OpenKeychain/src/main/res/layout/first_time_activity.xml137
-rw-r--r--OpenKeychain/src/main/res/layout/import_keys_activity.xml20
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml25
-rw-r--r--OpenKeychain/src/main/res/menu/encrypt_file_activity.xml24
-rw-r--r--OpenKeychain/src/main/res/menu/encrypt_text_activity.xml8
-rw-r--r--OpenKeychain/src/main/res/menu/key_list.xml2
-rw-r--r--OpenKeychain/src/main/res/raw/help_certification.html4
-rw-r--r--OpenKeychain/src/main/res/values-cs/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-de/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-es/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-eu/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-fi/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-fr/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-it/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-ja/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-nl/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-pl/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-ru/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-sl/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-sr/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-sv/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-tr/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-uk/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-zh-rTW/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values-zh/strings.xml2
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml12
-rw-r--r--README.md31
m---------extern/openpgp-api-lib0
m---------extern/snackbar0
m---------extern/spongycastle0
-rw-r--r--settings.gradle1
136 files changed, 1900 insertions, 1273 deletions
diff --git a/.gitmodules b/.gitmodules
index 4c1a9e403..e946dca3c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -34,3 +34,6 @@
path = extern/safeslinger-exchange
url = https://github.com/open-keychain/exchange-android
ignore = dirty
+[submodule "extern/snackbar"]
+ path = extern/snackbar
+ url = https://github.com/open-keychain/snackbar
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
index 07bc5508e..92482d004 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/CertifyOperationTest.java
@@ -47,6 +47,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.util.InputData;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
@@ -65,8 +66,8 @@ import java.util.Random;
public class CertifyOperationTest {
static UncachedKeyRing mStaticRing1, mStaticRing2;
- static String mKeyPhrase1 = TestingUtils.genPassphrase(true);
- static String mKeyPhrase2 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
static PrintStream oldShadowStream;
@@ -255,13 +256,13 @@ public class CertifyOperationTest {
}
private CertifyOperation operationWithFakePassphraseCache(
- final Long checkMasterKeyId, final Long checkSubKeyId, final String passphrase) {
+ final Long checkMasterKeyId, final Long checkSubKeyId, final Passphrase passphrase) {
return new CertifyOperation(Robolectric.application,
new ProviderHelper(Robolectric.application),
null, null) {
@Override
- public String getCachedPassphrase(long masterKeyId, long subKeyId)
+ public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
throws NoSecretKeyException {
if (checkMasterKeyId != null) {
Assert.assertEquals("requested passphrase should be for expected master key id",
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java
index b6fdbfc6c..23ea356c8 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/ExportTest.java
@@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
@@ -51,11 +52,11 @@ import java.util.Iterator;
@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
public class ExportTest {
- static String mPassphrase = TestingUtils.genPassphrase(true);
+ static Passphrase mPassphrase = TestingUtils.genPassphrase(true);
static UncachedKeyRing mStaticRing1, mStaticRing2;
- static String mKeyPhrase1 = TestingUtils.genPassphrase(true);
- static String mKeyPhrase2 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
static PrintStream oldShadowStream;
@@ -94,7 +95,7 @@ public class ExportTest {
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
Algorithm.ELGAMAL, 1024, null, KeyFlags.ENCRYPT_COMMS, 0L));
parcel.mAddUserIds.add("snails");
- parcel.mNewUnlock = new ChangeUnlockParcel(null, "1234");
+ parcel.mNewUnlock = new ChangeUnlockParcel(null, new Passphrase("1234"));
PgpEditKeyResult result = op.createSecretKeyRing(parcel);
Assert.assertTrue("initial test key creation must succeed", result.success());
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
index 40ade064b..34a4bed25 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/operations/PromoteKeyOperationTest.java
@@ -38,6 +38,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
@@ -50,7 +51,7 @@ import java.util.Iterator;
public class PromoteKeyOperationTest {
static UncachedKeyRing mStaticRing;
- static String mKeyPhrase1 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
static PrintStream oldShadowStream;
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java
new file mode 100644
index 000000000..6656c5131
--- /dev/null
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.pgp;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
+public class KeyRingTest {
+
+ @Test
+ public void splitCompleteUserIdShouldReturnAll3Components() throws Exception {
+ KeyRing.UserId info = KeyRing.splitUserId("Max Mustermann (this is a comment) <max@example.com>");
+ Assert.assertEquals("Max Mustermann", info.name);
+ Assert.assertEquals("this is a comment", info.comment);
+ Assert.assertEquals("max@example.com", info.email);
+ }
+
+ @Test
+ public void splitUserIdWithAllButCommentShouldReturnNameAndEmail() throws Exception {
+ KeyRing.UserId info = KeyRing.splitUserId("Max Mustermann <max@example.com>");
+ Assert.assertEquals("Max Mustermann", info.name);
+ Assert.assertNull(info.comment);
+ Assert.assertEquals("max@example.com", info.email);
+ }
+
+ @Test
+ public void splitUserIdWithAllButEmailShouldReturnNameAndComment() throws Exception {
+ KeyRing.UserId info = KeyRing.splitUserId("Max Mustermann (this is a comment)");
+ Assert.assertEquals(info.name, "Max Mustermann");
+ Assert.assertEquals(info.comment, "this is a comment");
+ Assert.assertNull(info.email);
+ }
+
+} \ No newline at end of file
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
index d782230c7..98713c6db 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java
@@ -39,6 +39,7 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
import org.sufficientlysecure.keychain.util.InputData;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
@@ -47,17 +48,18 @@ import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.security.Security;
+import java.util.Arrays;
import java.util.HashSet;
@RunWith(RobolectricTestRunner.class)
@org.robolectric.annotation.Config(emulateSdk = 18) // Robolectric doesn't yet support 19
public class PgpEncryptDecryptTest {
- static String mPassphrase = TestingUtils.genPassphrase(true);
+ static Passphrase mPassphrase = TestingUtils.genPassphrase(true);
static UncachedKeyRing mStaticRing1, mStaticRing2;
- static String mKeyPhrase1 = TestingUtils.genPassphrase(true);
- static String mKeyPhrase2 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase1 = TestingUtils.genPassphrase(true);
+ static Passphrase mKeyPhrase2 = TestingUtils.genPassphrase(true);
static PrintStream oldShadowStream;
@@ -180,7 +182,7 @@ public class PgpEncryptDecryptTest {
new ProviderHelper(Robolectric.application),
null, // new DummyPassphraseCache(mPassphrase, 0L),
data, out);
- b.setPassphrase(mPassphrase + "x");
+ b.setPassphrase(new Passphrase(Arrays.toString(mPassphrase.getCharArray()) + "x"));
DecryptVerifyResult result = b.build().execute();
Assert.assertFalse("decryption must succeed", result.success());
Assert.assertEquals("decrypted plaintext should be empty", 0, out.size());
@@ -511,7 +513,7 @@ public class PgpEncryptDecryptTest {
private PgpDecryptVerify.Builder builderWithFakePassphraseCache (
InputData data, OutputStream out,
- final String passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
+ final Passphrase passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
return new PgpDecryptVerify.Builder(Robolectric.application,
new ProviderHelper(Robolectric.application),
@@ -520,7 +522,7 @@ public class PgpEncryptDecryptTest {
public PgpDecryptVerify build() {
return new PgpDecryptVerify(this) {
@Override
- public String getCachedPassphrase(long masterKeyId, long subKeyId)
+ public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId)
throws NoSecretKeyException {
if (checkMasterKeyId != null) {
Assert.assertEquals("requested passphrase should be for expected master key id",
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
index 8feff4cc4..144501c89 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperationTest.java
@@ -53,6 +53,7 @@ import org.sufficientlysecure.keychain.support.KeyringBuilder;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
import org.sufficientlysecure.keychain.support.TestDataUtil;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import org.sufficientlysecure.keychain.util.TestingUtils;
@@ -72,7 +73,7 @@ import java.util.Random;
public class PgpKeyOperationTest {
static UncachedKeyRing staticRing;
- final static String passphrase = TestingUtils.genPassphrase();
+ final static Passphrase passphrase = TestingUtils.genPassphrase();
UncachedKeyRing ring;
PgpKeyOperation op;
@@ -295,9 +296,9 @@ public class PgpKeyOperationTest {
}
{
- String badphrase = "";
+ Passphrase badphrase = new Passphrase();
if (badphrase.equals(passphrase)) {
- badphrase = "a";
+ badphrase = new Passphrase("a");
}
assertModifyFailure("keyring modification with bad passphrase should fail",
@@ -1036,7 +1037,7 @@ public class PgpKeyOperationTest {
public void testPassphraseChange() throws Exception {
// change passphrase to empty
- parcel.mNewUnlock = new ChangeUnlockParcel("");
+ parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
// note that canonicalization here necessarily strips the empty notation packet
UncachedKeyRing modified = applyModificationWithChecks(parcel, ring, onlyA, onlyB,
passphrase);
@@ -1050,9 +1051,9 @@ public class PgpKeyOperationTest {
PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
// modify keyring, change to non-empty passphrase
- String otherPassphrase = TestingUtils.genPassphrase(true);
+ Passphrase otherPassphrase = TestingUtils.genPassphrase(true);
parcel.mNewUnlock = new ChangeUnlockParcel(otherPassphrase);
- modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, "");
+ modified = applyModificationWithChecks(parcel, modified, onlyA, onlyB, new Passphrase());
Assert.assertEquals("exactly three packets should have been modified (the secret keys)",
3, onlyB.size());
@@ -1075,7 +1076,7 @@ public class PgpKeyOperationTest {
Assert.assertEquals("extracted packet should be a secret subkey",
PacketTags.SECRET_SUBKEY, sKeyNoPassphrase.tag);
- String otherPassphrase2 = TestingUtils.genPassphrase(true);
+ Passphrase otherPassphrase2 = TestingUtils.genPassphrase(true);
parcel.mNewUnlock = new ChangeUnlockParcel(otherPassphrase2);
{
// if we replace a secret key with one without passphrase
@@ -1112,7 +1113,7 @@ public class PgpKeyOperationTest {
@Test
public void testUnlockPin() throws Exception {
- String pin = "5235125";
+ Passphrase pin = new Passphrase("5235125");
// change passphrase to a pin type
parcel.mNewUnlock = new ChangeUnlockParcel(null, pin);
@@ -1138,7 +1139,7 @@ public class PgpKeyOperationTest {
Thread.sleep(1000);
{
- parcel.mNewUnlock = new ChangeUnlockParcel("phrayse", null);
+ parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase("phrayse"), null);
applyModificationWithChecks(parcel, modified, onlyA, onlyB, pin, true, false);
Assert.assertEquals("exactly four packets should have been removed (the secret keys + notation packet)",
@@ -1171,7 +1172,7 @@ public class PgpKeyOperationTest {
UncachedKeyRing ring,
ArrayList<RawPacket> onlyA,
ArrayList<RawPacket> onlyB,
- String passphrase) {
+ Passphrase passphrase) {
return applyModificationWithChecks(parcel, ring, onlyA, onlyB, passphrase, true, true);
}
@@ -1180,7 +1181,7 @@ public class PgpKeyOperationTest {
UncachedKeyRing ring,
ArrayList<RawPacket> onlyA,
ArrayList<RawPacket> onlyB,
- String passphrase,
+ Passphrase passphrase,
boolean canonicalize,
boolean constantCanonicalize) {
@@ -1257,7 +1258,7 @@ public class PgpKeyOperationTest {
}
private void assertModifyFailure(String reason, UncachedKeyRing ring,
- SaveKeyringParcel parcel, String passphrase, LogType expected)
+ SaveKeyringParcel parcel, Passphrase passphrase, LogType expected)
throws Exception {
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(ring.getEncoded(), false, 0);
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java
index f9e0d52c3..bfe34b14b 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringCanonicalizeTest.java
@@ -61,6 +61,7 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.ByteArrayInputStream;
import java.security.Security;
@@ -111,7 +112,7 @@ public class UncachedKeyringCanonicalizeTest {
}
// passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel("");
+ parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.createSecretKeyRing(parcel);
@@ -546,7 +547,7 @@ public class UncachedKeyringCanonicalizeTest {
CanonicalizedSecretKeyRing canonicalized = (CanonicalizedSecretKeyRing) ring.canonicalize(log, 0);
CanonicalizedSecretKey masterSecretKey = canonicalized.getSecretKey();
- masterSecretKey.unlock("");
+ masterSecretKey.unlock(new Passphrase());
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
PGPSignature cert = PgpKeyOperation.generateSubkeyBindingSignature(
masterPublicKey, masterSecretKey.getPrivateKey(), masterSecretKey.getPrivateKey(),
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
index ccd47d0ee..712f0563d 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringMergeTest.java
@@ -40,6 +40,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper;
import org.sufficientlysecure.keychain.support.KeyringTestingHelper.RawPacket;
+import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.ProgressScaler;
import java.io.ByteArrayInputStream;
@@ -105,7 +106,7 @@ public class UncachedKeyringMergeTest {
}
// passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel("");
+ parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
PgpKeyOperation op = new PgpKeyOperation(null);
OperationResult.OperationLog log = new OperationResult.OperationLog();
@@ -122,7 +123,7 @@ public class UncachedKeyringMergeTest {
parcel.mAddUserIds.add("shy");
// passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel("");
+ parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
PgpKeyOperation op = new PgpKeyOperation(null);
OperationResult.OperationLog log = new OperationResult.OperationLog();
@@ -185,11 +186,11 @@ public class UncachedKeyringMergeTest {
parcel.reset();
parcel.mAddUserIds.add("flim");
- modifiedA = op.modifySecretKeyRing(secretRing, parcel, "").getRing();
+ modifiedA = op.modifySecretKeyRing(secretRing, parcel, new Passphrase()).getRing();
parcel.reset();
parcel.mAddUserIds.add("flam");
- modifiedB = op.modifySecretKeyRing(secretRing, parcel, "").getRing();
+ modifiedB = op.modifySecretKeyRing(secretRing, parcel, new Passphrase()).getRing();
}
{ // merge A into base
@@ -226,8 +227,8 @@ public class UncachedKeyringMergeTest {
parcel.reset();
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
Algorithm.RSA, 1024, null, KeyFlags.SIGN_DATA, 0L));
- modifiedA = op.modifySecretKeyRing(secretRing, parcel, "").getRing();
- modifiedB = op.modifySecretKeyRing(secretRing, parcel, "").getRing();
+ modifiedA = op.modifySecretKeyRing(secretRing, parcel, new Passphrase()).getRing();
+ modifiedB = op.modifySecretKeyRing(secretRing, parcel, new Passphrase()).getRing();
subKeyIdA = KeyringTestingHelper.getSubkeyId(modifiedA, 2);
subKeyIdB = KeyringTestingHelper.getSubkeyId(modifiedB, 2);
@@ -268,7 +269,7 @@ public class UncachedKeyringMergeTest {
parcel.mRevokeSubKeys.add(KeyringTestingHelper.getSubkeyId(ringA, 1));
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
ringA.getEncoded(), false, 0);
- modified = op.modifySecretKeyRing(secretRing, parcel, "").getRing();
+ modified = op.modifySecretKeyRing(secretRing, parcel, new Passphrase()).getRing();
}
{
@@ -293,7 +294,7 @@ public class UncachedKeyringMergeTest {
CanonicalizedSecretKey secretKey = new CanonicalizedSecretKeyRing(
ringB.getEncoded(), false, 0).getSecretKey();
- secretKey.unlock("");
+ secretKey.unlock(new Passphrase());
// sign all user ids
modified = secretKey.certifyUserIds(publicRing, publicRing.getPublicKey().getUnorderedUserIds(), null, null);
}
@@ -362,7 +363,7 @@ public class UncachedKeyringMergeTest {
CanonicalizedSecretKeyRing secretRing = new CanonicalizedSecretKeyRing(
ringA.getEncoded(), false, 0);
- modified = op.modifySecretKeyRing(secretRing, parcel, "").getRing();
+ modified = op.modifySecretKeyRing(secretRing, parcel, new Passphrase()).getRing();
}
{
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
index 65395f1ab..a6159de4e 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/UncachedKeyringTest.java
@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
+import org.sufficientlysecure.keychain.util.Passphrase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -70,7 +71,7 @@ public class UncachedKeyringTest {
parcel.mAddUserAttribute.add(uat);
}
// passphrase is tested in PgpKeyOperationTest, just use empty here
- parcel.mNewUnlock = new ChangeUnlockParcel("");
+ parcel.mNewUnlock = new ChangeUnlockParcel(new Passphrase());
PgpKeyOperation op = new PgpKeyOperation(null);
PgpEditKeyResult result = op.createSecretKeyRing(parcel);
diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java
index 1235e8cdd..1d7952464 100644
--- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java
+++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/util/TestingUtils.java
@@ -1,13 +1,30 @@
+/*
+ * 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.util;
import java.util.Random;
public class TestingUtils {
- public static String genPassphrase() {
+ public static Passphrase genPassphrase() {
return genPassphrase(false);
}
- public static String genPassphrase(boolean noEmpty) {
+ public static Passphrase genPassphrase(boolean noEmpty) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789!@#$%^&*()-_=";
Random r = new Random();
StringBuilder passbuilder = new StringBuilder();
@@ -16,6 +33,6 @@ public class TestingUtils {
passbuilder.append(chars.charAt(r.nextInt(chars.length())));
}
System.out.println("Generated passphrase: '" + passbuilder.toString() + "'");
- return passbuilder.toString();
+ return new Passphrase(passbuilder.toString());
}
}
diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle
index 8a39cafc6..00f291468 100644
--- a/OpenKeychain/build.gradle
+++ b/OpenKeychain/build.gradle
@@ -18,7 +18,6 @@ dependencies {
compile 'com.google.zxing:core:3.0.1'
compile 'com.jpardogo.materialtabstrip:library:1.0.9'
compile 'it.neokree:MaterialNavigationDrawer:1.3.1'
- compile 'com.nispok:snackbar:2.9.1'
compile 'com.getbase:floatingactionbutton:1.8.0'
compile 'com.ocpsoft:ocpsoft-pretty-time:1.0.6'
@@ -35,6 +34,7 @@ dependencies {
compile project(':extern:KeybaseLib:Lib')
compile project(':extern:TokenAutoComplete:library')
compile project(':extern:safeslinger-exchange')
+ compile project(':extern:snackbar:lib')
}
// Output of ./gradlew -q calculateChecksums
@@ -51,7 +51,7 @@ dependencyVerification {
'com.google.zxing:core:38c49045765281e4c170062fa3f48e4e988629bf985cab850c7497be5eaa72a1',
'com.jpardogo.materialtabstrip:library:c6ef812fba4f74be7dc4a905faa4c2908cba261a94c13d4f96d5e67e4aad4aaa',
'it.neokree:MaterialNavigationDrawer:1174d751a54689fccf53c1fbcdf439745926ae19024f4f1017afb6b29643c57d',
- 'com.nispok:snackbar:59dc092a44c877e9ce5f9040c632d99e62d8932b0a4d67ba0ec9e35467d9047c',
+ // 'com.nispok:snackbar:59dc092a44c877e9ce5f9040c632d99e62d8932b0a4d67ba0ec9e35467d9047c',
'com.getbase:floatingactionbutton:e63966148212e9685afad2370780ea239b6dbd2a06f6a3f919b98882318e6a32',
'com.android.support:support-annotations:fdee2354787ef66b268e75958de3f7f6c4f8f325510a6dac9f49c929f83a63de',
'com.balysv:material-ripple:587f19c1e27f16c7dc67ff9ac73838aa1451086ef05a15cee38bee3e4e1454ae',
diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml
index fc6a9e81e..6cfc0f5a1 100644
--- a/OpenKeychain/src/main/AndroidManifest.xml
+++ b/OpenKeychain/src/main/AndroidManifest.xml
@@ -87,15 +87,9 @@
</intent-filter>
</activity>
<activity
- android:name=".ui.FirstTimeActivity"
- android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
- android:label="@string/app_name"
- android:windowSoftInputMode="stateAlwaysHidden" />
- <activity
android:name=".ui.CreateKeyActivity"
- android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:windowSoftInputMode="adjustResize"
- android:label="@string/title_create_key"
+ android:label="@string/title_manage_my_keys"
android:parentActivityName=".ui.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -418,7 +412,7 @@
<activity
android:name=".ui.ViewKeyAdvActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
- android:label="@string/title_advanced_key_info"/>
+ android:label="@string/title_advanced_key_info" />
<activity
android:name=".ui.SettingsActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
@@ -661,6 +655,10 @@
android:value=".ui.MainActivity" />
</activity>
<activity
+ android:name=".ui.LogDisplayActivity"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
+ android:label="@string/title_log_display" />
+ <activity
android:name=".ui.ConsolidateDialogActivity"
android:theme="@android:style/Theme.NoDisplay" />
<activity
@@ -714,14 +712,12 @@
android:name=".remote.ui.RemoteServiceActivity"
android:exported="false"
android:label="@string/app_name"
- android:launchMode="singleTop"
- android:process=":remote_api" />
+ android:launchMode="singleTop" />
<activity
android:name=".remote.ui.SelectSignKeyIdActivity"
android:exported="false"
android:label="@string/app_name"
- android:launchMode="singleTop"
- android:process=":remote_api" />
+ android:launchMode="singleTop" />
<activity
android:name=".remote.ui.AppSettingsActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
@@ -749,13 +745,10 @@
</intent-filter>
</service>
- <activity
- android:name=".ui.LogDisplayActivity"
- android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
- android:label="@string/title_log_display"
- android:exported="false" />
-
- <service android:name=".service.DummyAccountService">
+ <!-- Contact Sync services -->
+ <service
+ android:name=".service.DummyAccountService"
+ tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
@@ -767,7 +760,8 @@
<service
android:name=".service.ContactSyncAdapterService"
android:exported="true"
- android:process=":sync">
+ android:process=":sync"
+ tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
@@ -780,6 +774,7 @@
android:resource="@xml/custom_pgp_contacts_structure" />
</service>
+ <!-- Storage Provider for temporary decrypted files -->
<provider
android:name=".provider.TemporaryStorageProvider"
android:authorities="org.sufficientlysecure.keychain.tempstorage"
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;
+ }
+}
diff --git a/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..fedf39013
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..f8f6c3812
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..04e0bf781
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..7e8fa6ba2
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png
new file mode 100644
index 000000000..ee00975dc
--- /dev/null
+++ b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png
Binary files differ
diff --git a/OpenKeychain/src/main/res/layout/api_select_sign_key_activity.xml b/OpenKeychain/src/main/res/layout/api_select_sign_key_activity.xml
index 0528fc11e..981e01dd1 100644
--- a/OpenKeychain/src/main/res/layout/api_select_sign_key_activity.xml
+++ b/OpenKeychain/src/main/res/layout/api_select_sign_key_activity.xml
@@ -35,6 +35,28 @@
android:text="@string/api_select_sign_key_text"
android:textAppearance="?android:attr/textAppearanceMedium" />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider" />
+
+ <TextView
+ android:id="@+id/api_select_sign_key_none"
+ android:background="?android:selectableItemBackground"
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:text="@string/none"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical"
+ android:clickable="true" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="?android:attr/listDivider" />
+
<FrameLayout
android:id="@+id/api_select_sign_key_list_fragment"
android:layout_width="match_parent"
diff --git a/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml
index ea064b00c..a2f81f74c 100644
--- a/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/create_key_name_fragment.xml
@@ -56,11 +56,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
+ android:text="@string/btn_back"
android:textAllCaps="true"
android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableLeft="@drawable/ic_chevron_left_grey_24dp"
android:drawablePadding="8dp"
android:gravity="left|center_vertical"
- android:clickable="false"
+ android:clickable="true"
style="?android:attr/borderlessButtonStyle" />
<TextView
diff --git a/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
new file mode 100644
index 000000000..79ffe58b1
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/create_key_start_fragment.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:layout_above="@+id/create_key_buttons">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:adjustViewBounds="true"
+ android:src="@drawable/first_time_1"
+ android:layout_gravity="center_horizontal"
+ android:layout_weight="1" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:background="@color/holo_gray_bright"
+ android:id="@+id/create_key_buttons">
+
+ <TextView
+ android:id="@+id/create_key_create_key_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/first_time_create_key"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ <!--<TextView-->
+ <!--android:id="@+id/create_key_yubikey_button"-->
+ <!--android:paddingLeft="16dp"-->
+ <!--android:paddingRight="16dp"-->
+ <!--android:textAppearance="?android:attr/textAppearanceMedium"-->
+ <!--android:layout_width="match_parent"-->
+ <!--android:layout_height="wrap_content"-->
+ <!--android:layout_weight="1"-->
+ <!--android:text="@string/first_time_yubikey"-->
+ <!--android:textAllCaps="true"-->
+ <!--android:minHeight="?android:attr/listPreferredItemHeight"-->
+ <!--android:drawableRight="@drawable/ic_chevron_right_grey_24dp"-->
+ <!--android:drawablePadding="8dp"-->
+ <!--android:gravity="right|center_vertical"-->
+ <!--android:clickable="true"-->
+ <!--style="?android:attr/borderlessButtonStyle" />-->
+
+ <TextView
+ android:id="@+id/create_key_import_button"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/first_time_import_key"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_chevron_right_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+
+ <TextView
+ android:id="@+id/create_key_cancel"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/btn_do_not_save"
+ android:textAllCaps="true"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:drawableRight="@drawable/ic_close_grey_24dp"
+ android:drawablePadding="8dp"
+ android:gravity="right|center_vertical"
+ android:clickable="true"
+ style="?android:attr/borderlessButtonStyle" />
+ </LinearLayout>
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/first_time_activity.xml b/OpenKeychain/src/main/res/layout/first_time_activity.xml
deleted file mode 100644
index 9b37766e9..000000000
--- a/OpenKeychain/src/main/res/layout/first_time_activity.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="16dp">
-
- <ImageView
- android:id="@+id/status_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/statusbar_height" />
-
- <LinearLayout
- android:id="@+id/first_time_buttons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:layout_alignParentBottom="true"
- android:orientation="vertical">
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/first_time_import_key"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/first_time_import_key"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:drawableRight="@drawable/ic_folder_grey_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical"
- android:clickable="true"
- android:background="?android:selectableItemBackground" />
-
- <View
- android:layout_width="1dp"
- android:layout_height="match_parent"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp"
- android:background="?android:attr/listDivider" />
-
- <TextView
- android:id="@+id/first_time_create_key"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/first_time_create_key"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:drawableRight="@drawable/ic_key_plus_grey600_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:layout_gravity="center_vertical"
- android:clickable="true"
- android:background="?android:selectableItemBackground" />
-
- </LinearLayout>
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="?android:attr/listDivider" />
-
- <TextView
- android:id="@+id/first_time_cancel"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/first_time_skip"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:gravity="center"
- android:clickable="true"
- android:background="?android:selectableItemBackground"
- android:layout_gravity="center_horizontal" />
-
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:layout_below="@+id/status_bar"
- android:layout_above="@+id/first_time_buttons">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="@string/app_name"
- android:drawableLeft="@drawable/ic_launcher"
- android:drawablePadding="8dp"
- android:gravity="center"
- android:layout_gravity="center_horizontal" />
-
- <ImageView
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:layout_marginTop="16dp"
- android:layout_marginBottom="16dp"
- android:adjustViewBounds="true"
- android:src="@drawable/first_time_1"
- android:layout_gravity="center_horizontal"
- android:layout_weight="1" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="64dp"
- android:layout_marginRight="64dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/first_time_text1"
- android:layout_gravity="center_horizontal"
- android:gravity="center_horizontal"
- android:layout_marginBottom="16dp" />
-
- </LinearLayout>
-
-</RelativeLayout>
diff --git a/OpenKeychain/src/main/res/layout/import_keys_activity.xml b/OpenKeychain/src/main/res/layout/import_keys_activity.xml
index 2cba78f37..332b95ce5 100644
--- a/OpenKeychain/src/main/res/layout/import_keys_activity.xml
+++ b/OpenKeychain/src/main/res/layout/import_keys_activity.xml
@@ -50,18 +50,19 @@
android:layout_weight="1"
android:background="@android:color/white" />
- <LinearLayout
+ <RelativeLayout
android:id="@+id/import_footer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
android:background="@android:color/white">
<View
+ android:id="@+id/import_divider"
android:layout_width="match_parent"
android:layout_height="1dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
android:background="?android:attr/listDivider" />
<TextView
@@ -70,7 +71,10 @@
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_below="@id/import_divider"
android:text="@string/import_import"
android:minHeight="?android:attr/listPreferredItemHeight"
android:drawableRight="@drawable/ic_file_download_grey_24dp"
@@ -79,6 +83,12 @@
android:clickable="true"
android:background="?android:selectableItemBackground" />
- </LinearLayout>
+ <RelativeLayout
+ android:id="@+id/import_snackbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@id/import_import" />
+
+ </RelativeLayout>
</LinearLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml
index 6a21e0dc1..c08d66cc1 100644
--- a/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_adv_share_fragment.xml
@@ -99,14 +99,12 @@
android:layout_weight="1" />
<LinearLayout
- android:id="@+id/view_key_action_key_share"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
- android:clickable="true"
- android:background="?android:selectableItemBackground"
android:orientation="horizontal">
<TextView
+ android:id="@+id/view_key_action_key_share"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
@@ -116,7 +114,25 @@
android:layout_weight="1"
android:drawableRight="@drawable/ic_share_grey_24dp"
android:drawablePadding="8dp"
- android:gravity="center_vertical" />
+ android:gravity="center_vertical"
+ android:background="?android:selectableItemBackground"/>
+
+ <View
+ android:layout_width="1dip"
+ android:layout_height="match_parent"
+ android:gravity="right"
+ android:layout_marginBottom="8dp"
+ android:layout_marginTop="8dp"
+ android:background="?android:attr/listDivider" />
+
+ <ImageButton
+ android:id="@+id/view_key_action_key_nfc"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:padding="8dp"
+ android:src="@drawable/ic_nfc_grey_24dp"
+ android:layout_gravity="center_vertical"
+ android:background="?android:selectableItemBackground" />
<View
android:layout_width="1dip"
@@ -154,6 +170,7 @@
</LinearLayout>
+
<View
android:layout_width="match_parent"
android:layout_height="1dip"
diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml
index f4aeb76c9..d6ed726fa 100644
--- a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml
+++ b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml
@@ -18,17 +18,33 @@
android:id="@+id/check_use_symmetric"
android:title="@string/label_symmetric"
android:checkable="true" />
- <item
- android:id="@+id/check_use_armor"
- android:title="@string/label_file_ascii_armor"
- android:checkable="true" />
+
<item
android:id="@+id/check_delete_after_encrypt"
android:title="@string/label_delete_after_encryption"
android:checkable="true" />
+
<item
android:id="@+id/check_enable_compression"
android:title="@string/label_enable_compression"
android:checked="true"
android:checkable="true" />
+
+ <item
+ android:id="@+id/check_encrypt_filenames"
+ android:title="@string/label_encrypt_filenames"
+ android:checked="true"
+ android:checkable="true" />
+
+ <item
+ android:id="@+id/check_use_armor"
+ android:title="@string/label_file_ascii_armor"
+ android:checkable="true" />
+
+ <!--<item-->
+ <!--android:id="@+id/check_hidden_recipients"-->
+ <!--android:title="@string/label_hidden_recipients"-->
+ <!--android:checked="false"-->
+ <!--android:checkable="true" />-->
+
</menu> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml
index bb9f4058a..5a262fdd8 100644
--- a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml
+++ b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml
@@ -18,9 +18,17 @@
android:id="@+id/check_use_symmetric"
android:title="@string/label_symmetric"
android:checkable="true" />
+
<item
android:id="@+id/check_enable_compression"
android:title="@string/label_enable_compression"
android:checked="true"
android:checkable="true" />
+
+ <!--<item-->
+ <!--android:id="@+id/check_hidden_recipients"-->
+ <!--android:title="@string/label_hidden_recipients"-->
+ <!--android:checked="false"-->
+ <!--android:checkable="true" />-->
+
</menu> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/menu/key_list.xml b/OpenKeychain/src/main/res/menu/key_list.xml
index 386a9d46e..15e098138 100644
--- a/OpenKeychain/src/main/res/menu/key_list.xml
+++ b/OpenKeychain/src/main/res/menu/key_list.xml
@@ -16,7 +16,7 @@
<item
android:id="@+id/menu_key_list_create"
- android:title="@string/menu_create_key"
+ android:title="@string/menu_manage_keys"
app:showAsAction="never" />
<item
diff --git a/OpenKeychain/src/main/res/raw/help_certification.html b/OpenKeychain/src/main/res/raw/help_certification.html
index 8228a4ac1..d4aff1ad7 100644
--- a/OpenKeychain/src/main/res/raw/help_certification.html
+++ b/OpenKeychain/src/main/res/raw/help_certification.html
@@ -22,10 +22,10 @@ To confirm keys between more than two persons, we suggest to use the key exchang
This certification is a <a href="http://tools.ietf.org/html/rfc4880#section-5.2.1">"generic certification (0x10)"</a> described in the standard by:
"The issuer of this certification does not make any particular assertion as to how well the certifier has checked that the owner of the key is in fact the person described by the User ID."</p>
-<p>Traditionally, certifications (often with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
+<p>Traditionally, certifications (also with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust.
Our model of key confirmation is a much simpler concept to avoid common usability problems related to this Web of Trust.
We assume that keys are verified only to a certain degree that is still usable enough to be executed "on the go".
-We also do not implement (potentially transitive) trust signatures or any other internal trust model.
+We also do not implement (potentially transitive) trust signatures or an ownertrust database like in GnuPG.
Furthermore, keys which contain at least one user ID certified by a trusted key will be marked as "confirmed" in the key listings.</p>
</body>
diff --git a/OpenKeychain/src/main/res/values-cs/strings.xml b/OpenKeychain/src/main/res/values-cs/strings.xml
index 9c16fa413..ab8b00eca 100644
--- a/OpenKeychain/src/main/res/values-cs/strings.xml
+++ b/OpenKeychain/src/main/res/values-cs/strings.xml
@@ -71,7 +71,7 @@
<string name="menu_help">Nápověda</string>
<string name="menu_export_key">Exportovat do souboru</string>
<string name="menu_delete_key">Smazat klíč</string>
- <string name="menu_create_key">Vytvořit moje klíče</string>
+ <string name="menu_manage_keys">Vytvořit moje klíče</string>
<string name="menu_import_existing_key">Importovat ze souboru</string>
<string name="menu_search">Hledat</string>
<string name="menu_beam_preferences">Beam settings</string>
diff --git a/OpenKeychain/src/main/res/values-de/strings.xml b/OpenKeychain/src/main/res/values-de/strings.xml
index fbae159a3..20c8d933d 100644
--- a/OpenKeychain/src/main/res/values-de/strings.xml
+++ b/OpenKeychain/src/main/res/values-de/strings.xml
@@ -88,7 +88,7 @@
<string name="menu_help">Hilfe</string>
<string name="menu_export_key">In Datei exportieren</string>
<string name="menu_delete_key">Schlüssel löschen</string>
- <string name="menu_create_key">Erzeuge meinen Schlüssel</string>
+ <string name="menu_manage_keys">Erzeuge meinen Schlüssel</string>
<string name="menu_import_existing_key">Von Datei importieren</string>
<string name="menu_search">Suchen</string>
<string name="menu_nfc_preferences">NFC-Einstellungen</string>
diff --git a/OpenKeychain/src/main/res/values-es/strings.xml b/OpenKeychain/src/main/res/values-es/strings.xml
index d7557074a..6ba096420 100644
--- a/OpenKeychain/src/main/res/values-es/strings.xml
+++ b/OpenKeychain/src/main/res/values-es/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">Ayuda</string>
<string name="menu_export_key">Exportar hacia archivo</string>
<string name="menu_delete_key">Borrar clave</string>
- <string name="menu_create_key">Crear mi clave</string>
+ <string name="menu_manage_keys">Crear mi clave</string>
<string name="menu_import_existing_key">Importar desde fichero</string>
<string name="menu_search">Buscar</string>
<string name="menu_nfc_preferences">Configuraciones NFC</string>
diff --git a/OpenKeychain/src/main/res/values-eu/strings.xml b/OpenKeychain/src/main/res/values-eu/strings.xml
index 32fdfc4cb..73ac12403 100644
--- a/OpenKeychain/src/main/res/values-eu/strings.xml
+++ b/OpenKeychain/src/main/res/values-eu/strings.xml
@@ -76,7 +76,7 @@
<string name="menu_help">Laguntza</string>
<string name="menu_export_key">Esportatu agirira</string>
<string name="menu_delete_key">Ezabatu giltza</string>
- <string name="menu_create_key">Sortu nire giltza</string>
+ <string name="menu_manage_keys">Sortu nire giltza</string>
<string name="menu_import_existing_key">inportatu agiritik</string>
<string name="menu_search">Bilatu</string>
<string name="menu_nfc_preferences">NFC ezarpenak</string>
diff --git a/OpenKeychain/src/main/res/values-fi/strings.xml b/OpenKeychain/src/main/res/values-fi/strings.xml
index 4b75d203d..508b17d0a 100644
--- a/OpenKeychain/src/main/res/values-fi/strings.xml
+++ b/OpenKeychain/src/main/res/values-fi/strings.xml
@@ -70,7 +70,7 @@
<string name="menu_help">Apua</string>
<string name="menu_export_key">Vie tiedostoon</string>
<string name="menu_delete_key">Poista avain</string>
- <string name="menu_create_key">Luo minun avaimeni</string>
+ <string name="menu_manage_keys">Luo minun avaimeni</string>
<string name="menu_import_existing_key">Tuo tiedostosta</string>
<string name="menu_search">Etsi</string>
<string name="menu_beam_preferences">Beam asetukset</string>
diff --git a/OpenKeychain/src/main/res/values-fr/strings.xml b/OpenKeychain/src/main/res/values-fr/strings.xml
index ba6f2e2af..3b3add86a 100644
--- a/OpenKeychain/src/main/res/values-fr/strings.xml
+++ b/OpenKeychain/src/main/res/values-fr/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">Aide</string>
<string name="menu_export_key">Exporter vers un fichier</string>
<string name="menu_delete_key">Supprimer la clef</string>
- <string name="menu_create_key">Créer ma clef</string>
+ <string name="menu_manage_keys">Créer ma clef</string>
<string name="menu_import_existing_key">Importer depuis un fichier</string>
<string name="menu_search">Rechercher</string>
<string name="menu_nfc_preferences">Paramètres NFC</string>
diff --git a/OpenKeychain/src/main/res/values-it/strings.xml b/OpenKeychain/src/main/res/values-it/strings.xml
index 5de5a1579..4b88aa494 100644
--- a/OpenKeychain/src/main/res/values-it/strings.xml
+++ b/OpenKeychain/src/main/res/values-it/strings.xml
@@ -69,7 +69,7 @@
<string name="menu_help">Aiuto</string>
<string name="menu_export_key">Esporta su un file</string>
<string name="menu_delete_key">Cancella chiave</string>
- <string name="menu_create_key">Crea mia chiave</string>
+ <string name="menu_manage_keys">Crea mia chiave</string>
<string name="menu_import_existing_key">Importa da file</string>
<string name="menu_search">Cerca</string>
<string name="menu_beam_preferences">Impostazioni Beam</string>
diff --git a/OpenKeychain/src/main/res/values-ja/strings.xml b/OpenKeychain/src/main/res/values-ja/strings.xml
index 183938811..16b9c3cc4 100644
--- a/OpenKeychain/src/main/res/values-ja/strings.xml
+++ b/OpenKeychain/src/main/res/values-ja/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">ヘルプ</string>
<string name="menu_export_key">ファイルへのエクスポート</string>
<string name="menu_delete_key">鍵の削除</string>
- <string name="menu_create_key">自分の鍵の生成</string>
+ <string name="menu_manage_keys">自分の鍵の生成</string>
<string name="menu_import_existing_key">ファイルからインポート</string>
<string name="menu_search">検索</string>
<string name="menu_nfc_preferences">NFC設定</string>
diff --git a/OpenKeychain/src/main/res/values-nl/strings.xml b/OpenKeychain/src/main/res/values-nl/strings.xml
index 0d3cb0094..d77d4e331 100644
--- a/OpenKeychain/src/main/res/values-nl/strings.xml
+++ b/OpenKeychain/src/main/res/values-nl/strings.xml
@@ -96,7 +96,7 @@
<string name="menu_help">Help</string>
<string name="menu_export_key">Exporteren naar bestand</string>
<string name="menu_delete_key">Sleutel verwijderen</string>
- <string name="menu_create_key">Mijn sleutel aanmaken</string>
+ <string name="menu_manage_keys">Mijn sleutel aanmaken</string>
<string name="menu_import_existing_key">Importeren van bestand</string>
<string name="menu_search">Zoeken</string>
<string name="menu_nfc_preferences">NFC-instellingen</string>
diff --git a/OpenKeychain/src/main/res/values-pl/strings.xml b/OpenKeychain/src/main/res/values-pl/strings.xml
index 1ee5a86e7..e4fce6bcc 100644
--- a/OpenKeychain/src/main/res/values-pl/strings.xml
+++ b/OpenKeychain/src/main/res/values-pl/strings.xml
@@ -78,7 +78,7 @@
<string name="menu_help">Pomoc</string>
<string name="menu_export_key">Eksportuj do pliku</string>
<string name="menu_delete_key">Usuń klucz</string>
- <string name="menu_create_key">Utwórz mój klucz</string>
+ <string name="menu_manage_keys">Utwórz mój klucz</string>
<string name="menu_import_existing_key">Importuj z pliku</string>
<string name="menu_search">Szukaj</string>
<string name="menu_beam_preferences">Ustawienia Beam</string>
diff --git a/OpenKeychain/src/main/res/values-ru/strings.xml b/OpenKeychain/src/main/res/values-ru/strings.xml
index 9559ecf51..7cd0cec9b 100644
--- a/OpenKeychain/src/main/res/values-ru/strings.xml
+++ b/OpenKeychain/src/main/res/values-ru/strings.xml
@@ -85,7 +85,7 @@
<string name="menu_help">Помощь</string>
<string name="menu_export_key">Экспорт в файл</string>
<string name="menu_delete_key">Удалить ключ</string>
- <string name="menu_create_key">Создать свой ключ</string>
+ <string name="menu_manage_keys">Создать свой ключ</string>
<string name="menu_import_existing_key">Импорт из файла</string>
<string name="menu_search">Поиск</string>
<string name="menu_nfc_preferences">Настройки NFC</string>
diff --git a/OpenKeychain/src/main/res/values-sl/strings.xml b/OpenKeychain/src/main/res/values-sl/strings.xml
index 3eb8eeba8..3f0def752 100644
--- a/OpenKeychain/src/main/res/values-sl/strings.xml
+++ b/OpenKeychain/src/main/res/values-sl/strings.xml
@@ -75,7 +75,7 @@
<string name="menu_help">Pomoč</string>
<string name="menu_export_key">Izvozi v datoteko</string>
<string name="menu_delete_key">Izbriši ključ</string>
- <string name="menu_create_key">Ustvari zasebni ključ</string>
+ <string name="menu_manage_keys">Ustvari zasebni ključ</string>
<string name="menu_import_existing_key">Uvozi iz datoteke</string>
<string name="menu_search">Išči</string>
<string name="menu_beam_preferences">Nastavitve Beam</string>
diff --git a/OpenKeychain/src/main/res/values-sr/strings.xml b/OpenKeychain/src/main/res/values-sr/strings.xml
index b5ba0b361..c4c92dce5 100644
--- a/OpenKeychain/src/main/res/values-sr/strings.xml
+++ b/OpenKeychain/src/main/res/values-sr/strings.xml
@@ -89,7 +89,7 @@
<string name="menu_help">Помоћ</string>
<string name="menu_export_key">Извези у фајл</string>
<string name="menu_delete_key">Обриши кључ</string>
- <string name="menu_create_key">Направи ми кључ</string>
+ <string name="menu_manage_keys">Направи ми кључ</string>
<string name="menu_import_existing_key">Увези из фајла</string>
<string name="menu_search">Претрага</string>
<string name="menu_nfc_preferences">НФЦ поставке</string>
diff --git a/OpenKeychain/src/main/res/values-sv/strings.xml b/OpenKeychain/src/main/res/values-sv/strings.xml
index 93b833590..605e14695 100644
--- a/OpenKeychain/src/main/res/values-sv/strings.xml
+++ b/OpenKeychain/src/main/res/values-sv/strings.xml
@@ -78,7 +78,7 @@
<string name="menu_help">Hjälp</string>
<string name="menu_export_key">Exportera till fil</string>
<string name="menu_delete_key">Radera nyckel</string>
- <string name="menu_create_key">Skapa min nyckel</string>
+ <string name="menu_manage_keys">Skapa min nyckel</string>
<string name="menu_import_existing_key">Importera från fil</string>
<string name="menu_search">Sök</string>
<string name="menu_beam_preferences">Beam-inställningar</string>
diff --git a/OpenKeychain/src/main/res/values-tr/strings.xml b/OpenKeychain/src/main/res/values-tr/strings.xml
index 2b60c9758..b939faf0d 100644
--- a/OpenKeychain/src/main/res/values-tr/strings.xml
+++ b/OpenKeychain/src/main/res/values-tr/strings.xml
@@ -69,7 +69,7 @@
<string name="menu_help">Yardım</string>
<string name="menu_export_key">Dosyaya ver</string>
<string name="menu_delete_key">Anahtar sil</string>
- <string name="menu_create_key">Anahtarımı oluştur</string>
+ <string name="menu_manage_keys">Anahtarımı oluştur</string>
<string name="menu_import_existing_key">Dosyadan al</string>
<string name="menu_search">Ara</string>
<string name="menu_beam_preferences">NFC ayarları</string>
diff --git a/OpenKeychain/src/main/res/values-uk/strings.xml b/OpenKeychain/src/main/res/values-uk/strings.xml
index b3a161758..f192cb07a 100644
--- a/OpenKeychain/src/main/res/values-uk/strings.xml
+++ b/OpenKeychain/src/main/res/values-uk/strings.xml
@@ -69,7 +69,7 @@
<string name="menu_help">Довідка</string>
<string name="menu_export_key">Експорт до файлу</string>
<string name="menu_delete_key">Вилучити ключ</string>
- <string name="menu_create_key">Створити мій ключ</string>
+ <string name="menu_manage_keys">Створити мій ключ</string>
<string name="menu_import_existing_key">Імпорт з файлу</string>
<string name="menu_search">Пошук</string>
<string name="menu_beam_preferences">Налаштування променя</string>
diff --git a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
index 286e98b79..bb8462bf3 100644
--- a/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh-rTW/strings.xml
@@ -65,7 +65,7 @@
<string name="menu_help">說明</string>
<string name="menu_export_key">匯出到檔案</string>
<string name="menu_delete_key">刪除金鑰</string>
- <string name="menu_create_key">建立金鑰</string>
+ <string name="menu_manage_keys">建立金鑰</string>
<string name="menu_import_existing_key">從檔案匯入</string>
<string name="menu_search">搜尋</string>
<string name="menu_beam_preferences">Beam 設定</string>
diff --git a/OpenKeychain/src/main/res/values-zh/strings.xml b/OpenKeychain/src/main/res/values-zh/strings.xml
index d59b2a2e0..31df7e587 100644
--- a/OpenKeychain/src/main/res/values-zh/strings.xml
+++ b/OpenKeychain/src/main/res/values-zh/strings.xml
@@ -57,7 +57,7 @@
<string name="menu_help">帮助</string>
<string name="menu_export_key">导出密钥</string>
<string name="menu_delete_key">删除密钥</string>
- <string name="menu_create_key">创建密钥</string>
+ <string name="menu_manage_keys">创建密钥</string>
<string name="menu_search">搜索</string>
<string name="menu_beam_preferences">参数</string>
<string name="menu_key_edit_cancel">取消</string>
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index a0142b264..1ce8936b5 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -45,6 +45,7 @@
<string name="title_keys">"Keys"</string>
<string name="title_delete_secret_key">"Delete YOUR key '%s'?"</string>
<string name="title_export_log">"Export Log"</string>
+ <string name="title_manage_my_keys">"Manage my keys"</string>
<!-- section -->
<string name="section_user_ids">"Identities"</string>
@@ -107,7 +108,7 @@
<string name="menu_help">"Help"</string>
<string name="menu_export_key">"Export to file"</string>
<string name="menu_delete_key">"Delete key"</string>
- <string name="menu_create_key">"Create my key"</string>
+ <string name="menu_manage_keys">"Manage my keys"</string>
<string name="menu_import_existing_key">"Import from file"</string>
<string name="menu_search">"Search"</string>
<string name="menu_nfc_preferences">"NFC settings"</string>
@@ -142,7 +143,7 @@
<string name="label_label_use_default_yubikey_pin_summary">"Uses default PIN (123456) to access YubiKeys over NFC"</string>
<string name="label_asymmetric_from">"Signed by:"</string>
<string name="label_to">"Encrypt to:"</string>
- <string name="label_delete_after_encryption">"Delete file after encryption"</string>
+ <string name="label_delete_after_encryption">"Delete files after encryption"</string>
<string name="label_delete_after_decryption">"Delete after decryption"</string>
<string name="label_encryption_algorithm">"Encryption algorithm"</string>
<string name="label_hash_algorithm">"Hash algorithm"</string>
@@ -168,6 +169,8 @@
<string name="label_first_keyserver_is_used">"(First keyserver listed is preferred)"</string>
<string name="label_preferred">"preferred"</string>
<string name="label_enable_compression">"Enable compression"</string>
+ <string name="label_encrypt_filenames">"Encrypt filenames"</string>
+ <string name="label_hidden_recipients">"Hide recipients"</string>
<string name="user_id_no_name">"&lt;no name&gt;"</string>
<string name="none">"&lt;none&gt;"</string>
@@ -1211,8 +1214,9 @@
<!-- First Time -->
<string name="first_time_text1">"Take back your privacy with OpenKeychain!"</string>
- <string name="first_time_create_key">"Create my key"</string>
- <string name="first_time_import_key">"Import from file"</string>
+ <string name="first_time_create_key">"Create my key (recommended)"</string>
+ <string name="first_time_import_key">"Import key from file"</string>
+ <string name="first_time_yubikey">"Use YubiKey NEO"</string>
<string name="first_time_skip">"Skip Setup"</string>
<!-- unsorted -->
diff --git a/README.md b/README.md
index 5a0a7c809..d7e64f294 100644
--- a/README.md
+++ b/README.md
@@ -63,33 +63,8 @@ We are using the newest [Android Studio](http://developer.android.com/sdk/instal
1. Clone the project from Github
2. From Android Studio: File -> Import Project -> Select the cloned top folder
-## OpenKeychain's API
-
-OpenKeychain provides two APIs, namely the Intent API and the Remote OpenPGP API.
-The Intent API can be used without permissions to start OpenKeychain's activities for cryptographic operations, import of keys, etc.
-However, it always requires user input, so that no malicious application can use this API without user intervention.
-The Remote OpenPGP API is more sophisticated and allows to to operations without user interaction in the background.
-When utilizing this API, OpenKeychain asks the user on first use to grant access for the calling client application.
-
-More technical information and examples about these APIs can be found in the project's wiki:
-* [Intent API](https://github.com/open-keychain/open-keychain/wiki/Intent-API)
-* [Remote OpenPGP API](https://github.com/open-keychain/open-keychain/wiki/OpenPGP-API)
-
-
## Libraries
-
-### ZXing Barcode Scanner Android Integration
-
-Classes can be found under https://github.com/open-keychain/zxing-android-integration.
-
-1. Copy all classes from https://github.com/zxing/zxing/tree/master/android-integration folder to our git repository.
-
-### ZXing QR-Code Classes
-
-Classes can be found under https://github.com/open-keychain/zxing-qr-code.
-All QR Code related classes were extracted from the ZXing library (https://github.com/zxing/zxing).
-
### Bouncy Castle
#### Spongy Castle
@@ -184,17 +159,17 @@ The full coding style can be found at http://source.android.com/source/code-styl
### Automated syntax check with CheckStyle
-####Linux
+#### Linux
1. Paste the `tools/checkstyle.xml` file to `~/.AndroidStudioPreview/config/codestyles/`
2. Go to Settings > Code Style > Java, select OpenPgpChecker, as well as Code Style > XML and select OpenPgpChecker again.
3. Start code inspection and see the results by selecting Analyze > Inspect Code from Android-Studio or you can directly run checkstyle via cli with `.tools/checkstyle`. Make sure it's executable first.
-####Mac OSX
+#### Mac OSX
1. Paste the `tools/checkstyle.xml` file to `~/Library/Preferences/AndroidStudioPreview/codestyles`
2. Go to Preferences > Code Style > Java, select OpenPgpChecker, as well as Code Style > XML and select OpenPgpChecker again.
3. Start code inspection and see the results by selecting Analyze > Inspect Code from Android-Studio or you can directly run checkstyle via cli with `.tools/checkstyle`. Make sure it's executable first.
-####Windows
+#### Windows
1. Paste the `tools/checkstyle.xml` file to `C:\Users\<UserName>\.AndroidStudioPreview\config\codestyles`
2. Go to File > Settings > Code Style > Java, select OpenPgpChecker, as well as Code Style > XML and select OpenPgpChecker again.
3. Start code inspection and see the results by selecting Analyze > Inspect Code from Android-Studio.
diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib
-Subproject 71af808820032de9b508bcde7f283f5aa8ccf15
+Subproject 70a17dcbeb5d8de095f09a7ce756543deff0165
diff --git a/extern/snackbar b/extern/snackbar
new file mode 160000
+Subproject 025ecadc592e591a96fa081265667efc0b0f0e1
diff --git a/extern/spongycastle b/extern/spongycastle
-Subproject 939914d9ffd1e8cc2710de6c600c9ccfc86aa54
+Subproject 4bb0180faa920f4e8cf3d482976a34e4df982a8
diff --git a/settings.gradle b/settings.gradle
index bb7db9f86..e15270e49 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -11,4 +11,5 @@ include ':extern:minidns'
include ':extern:KeybaseLib:Lib'
include ':extern:TokenAutoComplete:library'
include ':extern:safeslinger-exchange'
+include ':extern:snackbar:lib'
include ':OpenKeychain-Test'