From 75368034bd620d3d958ba6962f19e82edcb3a562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 15 Mar 2015 19:35:03 +0100 Subject: Put API activites in normal process to allow hydrate/dehydrate of logs --- OpenKeychain/src/main/AndroidManifest.xml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 0e7baf039..cd4dc6940 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -710,14 +710,12 @@ android:name=".remote.ui.RemoteServiceActivity" android:exported="false" android:label="@string/app_name" - android:launchMode="singleTop" - android:process=":remote_api" /> + android:launchMode="singleTop" /> + android:launchMode="singleTop" /> Date: Sun, 15 Mar 2015 21:17:24 +0100 Subject: Clarify MIME usage --- .../src/main/java/org/sufficientlysecure/keychain/Constants.java | 5 +++++ .../org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java | 2 +- .../java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 30d855a74..2ae20bec3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -42,6 +42,11 @@ 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"; + // 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/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index b862d5b11..416ddcb3f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -268,7 +268,7 @@ 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 users = new HashSet<>(); 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..cd11a60c9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -247,7 +247,7 @@ 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) { -- cgit v1.2.3 From ad9c35f522645ccf551767bf4bbc15d7b73d48ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 15 Mar 2015 22:05:12 +0100 Subject: Allow selection of none in SelectSignKeyIdActivity --- .../remote/ui/SelectSignKeyIdActivity.java | 17 +++++++++++++++-- .../res/layout/api_select_sign_key_activity.xml | 22 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) 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..b3096ef99 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,18 +69,29 @@ 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); } } 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" /> + + + + + + Date: Mon, 16 Mar 2015 00:16:20 +0100 Subject: Fix nullpointer when scanning malformed qr codes --- .../org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } -- cgit v1.2.3 From 0e71fcd638195003af36f4cf8f3192a381794516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 13:03:17 +0100 Subject: Update openpgp-api lib --- extern/openpgp-api-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 71af80882..bc177ed5e 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 71af808820032de9b508bcde7f283f5aa8ccf159 +Subproject commit bc177ed5e3f110cf372d6303c8e9d21e46fc76d2 -- cgit v1.2.3 From a655664c0bd177278826720dbac6b22f4e9e1cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 13:54:01 +0100 Subject: object oriented split user id --- .../keychain/keyimport/ImportKeysListEntry.java | 18 +++--- .../sufficientlysecure/keychain/pgp/KeyRing.java | 64 +++++++++++----------- .../remote/ui/AccountSettingsFragment.java | 6 +- .../remote/ui/SelectSignKeyIdActivity.java | 6 +- .../keychain/ui/CertifyKeyFragment.java | 7 +-- .../keychain/ui/CreateKeyFinalFragment.java | 4 +- .../keychain/ui/DecryptFragment.java | 10 ++-- .../keychain/ui/EditKeyFragment.java | 2 +- .../keychain/ui/EncryptFilesActivity.java | 6 +- .../keychain/ui/EncryptTextActivity.java | 7 +-- .../keychain/ui/KeyListFragment.java | 10 ++-- .../keychain/ui/PassphraseDialogActivity.java | 6 +- .../keychain/ui/ViewKeyActivity.java | 6 +- .../keychain/ui/ViewKeyAdvActivity.java | 6 +- .../keychain/ui/ViewKeyAdvCertsFragment.java | 6 +- .../keychain/ui/adapter/ImportKeysAdapter.java | 12 ++-- .../keychain/ui/adapter/MultiUserIdsAdapter.java | 21 ++++--- .../ui/adapter/SelectKeyCursorAdapter.java | 10 ++-- .../keychain/ui/adapter/UserIdsAdapter.java | 14 ++--- .../keychain/ui/adapter/UserIdsAddedAdapter.java | 14 ++--- .../ui/dialog/AddUserIdDialogFragment.java | 4 +- .../ui/dialog/DeleteKeyDialogFragment.java | 6 +- .../ui/widget/EncryptKeyCompletionView.java | 14 ++--- .../keychain/ui/widget/KeySpinner.java | 7 +-- .../keychain/util/ContactHelper.java | 21 ++++--- extern/openpgp-api-lib | 2 +- 26 files changed, 140 insertions(+), 149 deletions(-) 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 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()); + mMergedUserIds.put(userIdSplit.name, new HashSet()); } } else { // fallback 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..eb1f93a8b 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,35 +62,21 @@ public abstract class KeyRing { /** * Splits userId string into naming part, email part, and comment part + *

+ * User ID matching: + * http://fiddle.re/t4p6f * * @param userId - * @return array with naming (0), email (1), comment (2) + * @return theParsedUserInfo */ - 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 Mustermann " - * "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); } /** @@ -101,16 +87,28 @@ public abstract class KeyRing { * @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/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/SelectSignKeyIdActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectSignKeyIdActivity.java index b3096ef99..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 @@ -96,11 +96,11 @@ public class SelectSignKeyIdActivity extends BaseActivity { } 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/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 1e1bd32c1..9cb4e5f65 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -31,7 +31,6 @@ import android.os.Bundle; import android.os.Message; import android.os.Messenger; import android.os.Parcel; -import android.os.Parcelable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -247,14 +246,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")); 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..4871b5ae2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -186,12 +186,12 @@ 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(mName, 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); + String thisUserId = KeyRing.createUserId(new KeyRing.UserId(mName, email, null)); mSaveKeyringParcel.mAddUserIds.add(thisUserId); } } 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..513300cc5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -128,14 +128,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/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index 8b9323f19..8d16fe47e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -545,7 +545,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); 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 416ddcb3f..fa7717726 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -273,9 +273,9 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi if (!isModeSymmetric() && mEncryptionUserIds != null) { Set 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()])); 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 cd11a60c9..d3dfd73df 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,6 @@ 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.ShareHelper; import java.util.ArrayList; @@ -253,9 +252,9 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv if (!isModeSymmetric() && mEncryptionUserIds != null) { Set 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 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..4b604add8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -688,14 +688,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); 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 bb669f6b8..48509710a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java @@ -211,9 +211,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); } 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 b25f6bbf2..13a5ac269 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -841,9 +841,9 @@ public class ViewKeyActivity 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) { - 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); } 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/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 { // 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 5a0782e54..028f0fc9c 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 3486f1516..d1103ac1f 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 { // 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/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 226588aaa..2c75c3a7d 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; @@ -162,9 +161,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/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java index 6efc0a5ea..894a7d0d9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -37,7 +37,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; @@ -447,7 +446,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 +469,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 +520,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 +533,7 @@ public class ContactHelper { ArrayList 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); @@ -776,14 +775,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/extern/openpgp-api-lib b/extern/openpgp-api-lib index bc177ed5e..10be5948d 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit bc177ed5e3f110cf372d6303c8e9d21e46fc76d2 +Subproject commit 10be5948d68bb5e80aed77fdf93cada598ee7667 -- cgit v1.2.3 From 484c3092eecbf775f355879587c2bea7612edac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 13:54:12 +0100 Subject: object oriented split user id --- .../keychain/pgp/KeyRingTest.java | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/KeyRingTest.java 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 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.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) "); + 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 "); + 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 -- cgit v1.2.3 From ae0b85a2e0e01cd05905b7d9af6e09fcd1280eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 14:06:55 +0100 Subject: Update api lib --- extern/openpgp-api-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 10be5948d..57a7da59b 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 10be5948d68bb5e80aed77fdf93cada598ee7667 +Subproject commit 57a7da59bd6d2a8b4e0d81d82abeb154215d920f -- cgit v1.2.3 From 98b942982e82927be12f1d16302387e3f16e106e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 14:27:26 +0100 Subject: Update api lib --- extern/openpgp-api-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 57a7da59b..d10df1d40 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 57a7da59bd6d2a8b4e0d81d82abeb154215d920f +Subproject commit d10df1d40f23475445d0abca217683e911ffa0a0 -- cgit v1.2.3 From 146fa8d6c0ace2f9560341171a491e9ddb0361ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 15:05:39 +0100 Subject: Clarify certification help screen --- OpenKeychain/src/main/res/raw/help_certification.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 "generic certification (0x10)" 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."

-

Traditionally, certifications (often with higher certification levels, such as "positive certifications" (0x13)) are organized in OpenPGP's Web of Trust. +

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.

-- cgit v1.2.3 From 5d7c1e6fb0ec042066b2b7629961ac165ecf2e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 16:32:13 +0100 Subject: Remove old info from readme --- README.md | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 38b486346..964267450 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Development mailinglist at http://groups.google.com/d/forum/openpgp-keychain-dev ### Build with Gradle + +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). 1. Get all external submodules with ``git submodule update --init --recursive`` 2. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html) 3. Open the Android SDK Manager (shell command: ``android``). @@ -57,33 +59,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 @@ -178,17 +155,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\\.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. -- cgit v1.2.3 From 916ff0e0fa3b4c6ec9b69ef4bda2673e6cea1959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 16:33:37 +0100 Subject: Remove old info from readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 964267450..db61ab65a 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,6 @@ Development mailinglist at http://groups.google.com/d/forum/openpgp-keychain-dev ### Build with Gradle - -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). 1. Get all external submodules with ``git submodule update --init --recursive`` 2. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html) 3. Open the Android SDK Manager (shell command: ``android``). -- cgit v1.2.3 From a5271bf2297fc49474b5f1ab2755fb073cb7f3fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 17:00:53 +0100 Subject: Allow encrypt of filenames via overflow menu --- .../keychain/ui/EncryptActivityInterface.java | 1 + .../keychain/ui/EncryptFilesActivity.java | 12 ++++++++++++ .../keychain/ui/EncryptFilesFragment.java | 15 +++++++++------ .../keychain/ui/EncryptTextActivity.java | 5 +++++ .../src/main/res/menu/encrypt_file_activity.xml | 18 ++++++++++++++---- .../src/main/res/menu/encrypt_text_activity.xml | 1 + OpenKeychain/src/main/res/values/strings.xml | 3 ++- 7 files changed, 44 insertions(+), 11 deletions(-) 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..037366164 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -29,6 +29,7 @@ public interface EncryptActivityInterface { public boolean isUseArmor(); public boolean isUseCompression(); + public boolean isEncryptFilenames(); public long getSignatureKey(); public long[] getEncryptionKeys(); 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 fa7717726..8277e2ccc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -70,6 +70,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi private boolean mUseCompression = true; private boolean mDeleteAfterEncrypt = false; private boolean mShareAfterEncrypt = false; + private boolean mEncryptFilenames = true; private ArrayList mInputUris; private ArrayList mOutputUris; private String mMessage = ""; @@ -88,6 +89,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi return mUseCompression; } + @Override + public boolean isEncryptFilenames() { + return mEncryptFilenames; + } + @Override public long getSignatureKey() { return mSigningKeyId; @@ -371,6 +377,12 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi notifyUpdate(); break; } + case R.id.encrypt_filenames: { + mEncryptFilenames = 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..6ea6ecec1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -137,17 +137,17 @@ 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() ? ".asc" : ".gpg"); 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); } } @@ -158,10 +158,13 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt } 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() ? ".asc" : ".gpg"); mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName)); + filenameCounter++; } mEncryptInterface.startEncrypt(true); } else { 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 d3dfd73df..e8c8bd5b5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -82,6 +82,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv return true; } + @Override + public boolean isEncryptFilenames() { + return false; + } + @Override public boolean isUseCompression() { return mUseCompression; diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml index f4aeb76c9..1dd9896bc 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml @@ -18,17 +18,27 @@ android:id="@+id/check_use_symmetric" android:title="@string/label_symmetric" android:checkable="true" /> - + + + + + + + \ 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..408b70822 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml @@ -18,6 +18,7 @@ android:id="@+id/check_use_symmetric" android:title="@string/label_symmetric" android:checkable="true" /> + "Uses default PIN (123456) to access YubiKeys over NFC"
"Signed by:" "Encrypt to:" - "Delete file after encryption" + "Delete files after encryption" "Delete after decryption" "Encryption algorithm" "Hash algorithm" @@ -167,6 +167,7 @@ "(First keyserver listed is preferred)" "preferred" "Enable compression" + "Encrypt filenames" "<no name>" "<none>" -- cgit v1.2.3 From fd8f5ebb2fb9c3ee1e66432b9537b2cb421269de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 18:20:44 +0100 Subject: Allow for hidden recipients in encrypt methods --- .../keychain/pgp/CanonicalizedPublicKey.java | 4 +-- .../sufficientlysecure/keychain/pgp/KeyRing.java | 8 ----- .../keychain/pgp/PassphraseCacheInterface.java | 18 ++++++++++++ .../keychain/pgp/PgpSignEncryptInput.java | 34 ++++++++++++++++++++-- .../keychain/pgp/PgpSignEncryptOperation.java | 20 ++++++------- .../keychain/pgp/SignEncryptParcel.java | 20 +++++++++++++ .../keychain/ui/EncryptActivityInterface.java | 1 + .../keychain/ui/EncryptFilesActivity.java | 25 ++++++++++++---- .../keychain/ui/EncryptTextActivity.java | 18 ++++++++++-- .../src/main/res/menu/encrypt_file_activity.xml | 10 +++++-- .../src/main/res/menu/encrypt_text_activity.xml | 7 +++++ OpenKeychain/src/main/res/values/strings.xml | 1 + extern/spongycastle | 2 +- 13 files changed, 134 insertions(+), 34 deletions(-) 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(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/KeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java index eb1f93a8b..825795cc6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/KeyRing.java @@ -65,9 +65,6 @@ public abstract class KeyRing { *

* User ID matching: * http://fiddle.re/t4p6f - * - * @param userId - * @return theParsedUserInfo */ public static UserId splitUserId(final String userId) { if (!TextUtils.isEmpty(userId)) { @@ -81,11 +78,6 @@ public abstract class KeyRing { /** * Returns a composed user id. Returns null if name is null! - * - * @param name - * @param email - * @param comment - * @return */ public static String createUserId(UserId userId) { String userIdString = userId.name; // consider name a required value 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..0066bd23e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.sufficientlysecure.keychain.pgp; public interface PassphraseCacheInterface { 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..2dec4b9c2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.sufficientlysecure.keychain.pgp; import org.spongycastle.bcpg.CompressionAlgorithmTags; @@ -23,7 +41,8 @@ public class PgpSignEncryptInput { 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 +52,7 @@ public class PgpSignEncryptInput { this.mCharset = mCharset; } - public boolean ismFailOnMissingEncryptionKeyIds() { + public boolean isFailOnMissingEncryptionKeyIds() { return mFailOnMissingEncryptionKeyIds; } @@ -126,7 +145,7 @@ public class PgpSignEncryptInput { return this; } - public boolean ismEnableAsciiArmorOutput() { + public boolean isEnableAsciiArmorOutput() { return mEnableAsciiArmorOutput; } @@ -172,5 +191,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..94e04060d 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 + * Copyright (C) 2012-2015 Dominik Schürmann * Copyright (C) 2010-2014 Thialfihar * Copyright (C) 2014 Vincent Breitmoser * @@ -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()); @@ -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..8e71e8815 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.sufficientlysecure.keychain.pgp; import android.net.Uri; @@ -52,6 +70,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); @@ -116,6 +135,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/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index 037366164..c89707c34 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -30,6 +30,7 @@ public interface EncryptActivityInterface { public boolean isUseArmor(); public boolean isUseCompression(); public boolean isEncryptFilenames(); + public boolean isHiddenRecipients(); public long getSignatureKey(); public long[] getEncryptionKeys(); 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 8277e2ccc..4deaed736 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -62,15 +62,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 String mPassphrase = ""; + private ArrayList mInputUris; private ArrayList mOutputUris; private String mMessage = ""; @@ -94,6 +97,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi return mEncryptFilenames; } + @Override + public boolean isHiddenRecipients() { + return mHiddenRecipients; + } + @Override public long getSignatureKey() { return mSigningKeyId; @@ -228,6 +236,7 @@ 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); @@ -377,12 +386,16 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi notifyUpdate(); break; } - case R.id.encrypt_filenames: { + 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/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index e8c8bd5b5..05132b50c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -62,16 +62,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 ArrayList mInputUris; private ArrayList mOutputUris; private String mMessage = ""; - private boolean mUseCompression = true; public boolean isModeSymmetric() { return MODE_SYMMETRIC == mCurrentMode; @@ -92,6 +95,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv return mUseCompression; } + @Override + public boolean isHiddenRecipients() { + return mHiddenRecipients; + } + @Override public long getSignatureKey() { return mSigningKeyId; @@ -206,6 +214,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); @@ -357,6 +366,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/res/menu/encrypt_file_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml index 1dd9896bc..2c5e9d738 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml @@ -31,7 +31,7 @@ android:checkable="true" /> @@ -40,5 +40,11 @@ android:id="@+id/check_use_armor" android:title="@string/label_file_ascii_armor" android:checkable="true" /> - + + + \ 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 408b70822..33862b730 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml @@ -24,4 +24,11 @@ android:title="@string/label_enable_compression" android:checked="true" android:checkable="true" /> + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 48d58d7b1..f1c14bd32 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -168,6 +168,7 @@ "preferred" "Enable compression" "Encrypt filenames" + "Hide recipients" "<no name>" "<none>" diff --git a/extern/spongycastle b/extern/spongycastle index 939914d9f..4bb0180fa 160000 --- a/extern/spongycastle +++ b/extern/spongycastle @@ -1 +1 @@ -Subproject commit 939914d9ffd1e8cc2710de6c600c9ccfc86aa545 +Subproject commit 4bb0180faa920f4e8cf3d482976a34e4df982a8d -- cgit v1.2.3 From 025eaf075708c939497c2e6ad85b368efeee4a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 16 Mar 2015 20:34:27 +0100 Subject: Disable hidden recipients for now --- OpenKeychain/src/main/res/menu/encrypt_file_activity.xml | 10 +++++----- OpenKeychain/src/main/res/menu/encrypt_text_activity.xml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml index 2c5e9d738..d6ed726fa 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_file_activity.xml @@ -41,10 +41,10 @@ android:title="@string/label_file_ascii_armor" android:checkable="true" /> - + + + + + \ 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 33862b730..5a262fdd8 100644 --- a/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml +++ b/OpenKeychain/src/main/res/menu/encrypt_text_activity.xml @@ -25,10 +25,10 @@ android:checked="true" android:checkable="true" /> - + + + + + \ No newline at end of file -- cgit v1.2.3 From 6f496730be30aab8de3f80de47de4091d8cb8c6a Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Tue, 17 Mar 2015 02:26:18 +0530 Subject: removed unnecessary @TargetApi annotation --- .../java/org/sufficientlysecure/keychain/util/ContactHelper.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 894a7d0d9..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; @@ -302,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)); @@ -714,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, @@ -724,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); -- cgit v1.2.3 From 444123d040d2288628e38beaf06cc05ce5768617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 17 Mar 2015 13:22:13 +0100 Subject: File extensions into Constants --- .../main/java/org/sufficientlysecure/keychain/Constants.java | 4 ++++ .../sufficientlysecure/keychain/ui/DecryptFilesFragment.java | 4 +++- .../sufficientlysecure/keychain/ui/EncryptFilesActivity.java | 10 +++++----- .../sufficientlysecure/keychain/ui/EncryptFilesFragment.java | 4 ++-- .../sufficientlysecure/keychain/ui/EncryptTextActivity.java | 10 +++++----- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java index 2ae20bec3..fc1cb8acc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/Constants.java @@ -47,6 +47,10 @@ public final class Constants { 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/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index c808557a6..7e33843ea 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -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; 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 4deaed736..f1784fab3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -391,11 +391,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi notifyUpdate(); break; } - case R.id.check_hidden_recipients: { - mHiddenRecipients = 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 6ea6ecec1..9c9b44511 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -139,7 +139,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt Uri inputUri = mEncryptInterface.getInputUris().get(0); String targetName = (mEncryptInterface.isEncryptFilenames() ? "1" : FileHelper.getFilename(getActivity(), inputUri)) - + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); + + (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; @@ -162,7 +162,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt for (Uri uri : mEncryptInterface.getInputUris()) { String targetName = (mEncryptInterface.isEncryptFilenames() ? String.valueOf(filenameCounter) : FileHelper.getFilename(getActivity(), uri)) - + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); + + (mEncryptInterface.isUseArmor() ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN); mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName)); filenameCounter++; } 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 05132b50c..14f2c492d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -366,11 +366,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv notifyUpdate(); break; } - case R.id.check_hidden_recipients: { - mHiddenRecipients = item.isChecked(); - notifyUpdate(); - break; - } +// case R.id.check_hidden_recipients: { +// mHiddenRecipients = item.isChecked(); +// notifyUpdate(); +// break; +// } default: { return super.onOptionsItemSelected(item); } -- cgit v1.2.3 From dbcb7a9e10ec4418337e0dce1b4227cbc3b7bd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 17 Mar 2015 13:29:54 +0100 Subject: Manifest cleanup --- OpenKeychain/src/main/AndroidManifest.xml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index cd4dc6940..91c84fb18 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -414,7 +414,7 @@ + android:label="@string/title_advanced_key_info" /> + @@ -743,13 +747,10 @@ - - - + + @@ -761,7 +762,8 @@ + android:process=":sync" + tools:ignore="ExportedService"> @@ -774,6 +776,7 @@ android:resource="@xml/custom_pgp_contacts_structure" /> + Date: Tue, 17 Mar 2015 19:07:28 +0530 Subject: contacts work on all supported api levels --- .../keychain/KeychainApplication.java | 29 ++++++++++------------ 1 file changed, 13 insertions(+), 16 deletions(-) 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(); } } -- cgit v1.2.3 From 74c474e3e26c428153f15b7fab6b29738e882682 Mon Sep 17 00:00:00 2001 From: Max Mertens Date: Wed, 18 Mar 2015 17:49:57 +0100 Subject: Show HKP server results first in key cloud search. Fixes #1066 --- .../sufficientlysecure/keychain/keyimport/ImportKeysList.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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..ed096e9dc 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,7 @@ public class ImportKeysList extends ArrayList { modified = true; } + 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 +79,19 @@ public class ImportKeysList extends ArrayList { // to work properly, Keybase-sourced entries need to pass along the extra if (KeybaseKeyserver.ORIGIN.equals(origin)) { existing.setExtraData(incoming.getExtraData()); + incomingFromHkpServer = false; } } + ArrayList incomingIDs = incoming.getUserIds(); ArrayList existingIDs = existing.getUserIds(); for (String incomingID : incomingIDs) { if (!existingIDs.contains(incomingID)) { - existingIDs.add(incomingID); + if (incomingFromHkpServer) { + existingIDs.add(0, incomingID); + } else { + existingIDs.add(incomingID); + } modified = true; } } -- cgit v1.2.3 From aab32b81b9b54e1a978006f33718a9525772ce53 Mon Sep 17 00:00:00 2001 From: Max Mertens Date: Wed, 18 Mar 2015 22:23:35 +0100 Subject: Added comments for server result sorting in key search --- .../org/sufficientlysecure/keychain/keyimport/ImportKeysList.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 ed096e9dc..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,7 @@ public class ImportKeysList extends ArrayList { 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 @@ -79,6 +80,7 @@ public class ImportKeysList extends ArrayList { // 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; } } @@ -87,6 +89,10 @@ public class ImportKeysList extends ArrayList { ArrayList existingIDs = existing.getUserIds(); for (String incomingID : incomingIDs) { if (!existingIDs.contains(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 { -- cgit v1.2.3 From 9c9f95c7acb92aad1f02e65271610fb3dca6c0dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 19 Mar 2015 03:03:46 +0100 Subject: New Passphrase class for safer passphrase handling in memory --- .../keychain/operations/BaseOperation.java | 5 +- .../keychain/operations/CertifyOperation.java | 3 +- .../keychain/operations/EditKeyOperation.java | 3 +- .../operations/results/DecryptVerifyResult.java | 11 +- .../operations/results/PgpSignEncryptResult.java | 8 +- .../keychain/pgp/CanonicalizedSecretKey.java | 5 +- .../keychain/pgp/PassphraseCacheInterface.java | 6 +- .../keychain/pgp/PgpDecryptVerify.java | 9 +- .../keychain/pgp/PgpKeyOperation.java | 25 ++-- .../keychain/pgp/PgpSignEncryptInput.java | 13 +- .../keychain/pgp/PgpSignEncryptOperation.java | 2 +- .../keychain/pgp/SignEncryptParcel.java | 10 +- .../keychain/remote/OpenPgpService.java | 7 +- .../keychain/service/KeychainIntentService.java | 7 +- .../keychain/service/PassphraseCacheService.java | 36 +++--- .../keychain/service/SaveKeyringParcel.java | 20 ++-- .../keychain/ui/CertifyKeyFragment.java | 4 +- .../keychain/ui/CreateKeyActivity.java | 11 +- .../keychain/ui/CreateKeyEmailFragment.java | 2 +- .../keychain/ui/CreateKeyFinalFragment.java | 9 +- .../keychain/ui/CreateKeyNameFragment.java | 15 +-- .../keychain/ui/CreateKeyPassphraseFragment.java | 13 +- .../keychain/ui/DecryptFilesFragment.java | 6 +- .../keychain/ui/DecryptFragment.java | 5 +- .../keychain/ui/DecryptTextFragment.java | 4 +- .../keychain/ui/EditKeyFragment.java | 11 +- .../keychain/ui/EncryptActivity.java | 7 +- .../keychain/ui/EncryptActivityInterface.java | 4 +- .../keychain/ui/EncryptFilesActivity.java | 9 +- .../keychain/ui/EncryptSymmetricFragment.java | 10 +- .../keychain/ui/EncryptTextActivity.java | 10 +- .../keychain/ui/PassphraseDialogActivity.java | 5 +- .../ui/dialog/SetPassphraseDialogFragment.java | 21 ++-- .../keychain/util/Passphrase.java | 131 +++++++++++++++++++++ 34 files changed, 307 insertions(+), 140 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java 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/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 CREATOR = new Creator() { 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/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/PassphraseCacheInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java index 0066bd23e..88ccccc6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PassphraseCacheInterface.java @@ -18,14 +18,16 @@ 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 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 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(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 2dec4b9c2..4a920685a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInput.java @@ -20,6 +20,7 @@ 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; @@ -29,12 +30,12 @@ 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; @@ -73,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; } @@ -118,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; } 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 94e04060d..bd3c31d3a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -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); 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 8e71e8815..975548c95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java @@ -22,6 +22,8 @@ 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; @@ -57,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; @@ -112,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) { @@ -122,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) { 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..98a9ff44f 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); @@ -508,7 +509,7 @@ public class OpenPgpService extends RemoteService { KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg)); } - String passphrase = data.getStringExtra(OpenPgpApi.EXTRA_PASSPHRASE); + Passphrase passphrase = data.getParcelableExtra(OpenPgpApi.EXTRA_PASSPHRASE); long inputLength = is.available(); InputData inputData = new InputData(is, inputLength); 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 bf6a62782..d5f13f7ce 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -65,6 +65,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; @@ -281,7 +282,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); @@ -411,7 +412,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); @@ -469,7 +470,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/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 9cb4e5f65..a0f89b06a 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; @@ -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; 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..0eb9e948a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -23,11 +23,20 @@ import android.support.v4.app.FragmentTransaction; import org.sufficientlysecure.keychain.R; +import java.util.ArrayList; + public class CreateKeyActivity extends BaseActivity { public static final String EXTRA_NAME = "name"; public static final String EXTRA_EMAIL = "email"; + public class State { + String name; + String email; + ArrayList additionalEmails; + char[] passphrase; + } + public static enum FragAction { START, TO_RIGHT, @@ -44,7 +53,7 @@ public class CreateKeyActivity extends BaseActivity { getIntent().getStringExtra(EXTRA_NAME), getIntent().getStringExtra(EXTRA_EMAIL) ); - loadFragment(null, frag, FragAction.START); + loadFragment(savedInstanceState, frag, FragAction.START); } @Override 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..6a4dd7a41 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -85,7 +85,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; 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 4871b5ae2..5f6bfdb11 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; @@ -72,7 +73,7 @@ public class CreateKeyFinalFragment extends Fragment { String mName; String mEmail; ArrayList mAdditionalEmails; - String mPassphrase; + Passphrase mPassphrase; SaveKeyringParcel mSaveKeyringParcel; @@ -81,14 +82,14 @@ public class CreateKeyFinalFragment extends Fragment { */ public static CreateKeyFinalFragment newInstance(String name, String email, ArrayList additionalEmails, - String passphrase) { + Passphrase passphrase) { 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); + args.putParcelable(ARG_PASSPHRASE, passphrase); frag.setArguments(args); @@ -111,7 +112,7 @@ public class CreateKeyFinalFragment extends Fragment { mName = getArguments().getString(ARG_NAME); mEmail = getArguments().getString(ARG_EMAIL); mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS); - mPassphrase = getArguments().getString(ARG_PASSPHRASE); + mPassphrase = getArguments().getParcelable(ARG_PASSPHRASE); // set values mNameEdit.setText(mName); 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..093d427b7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java @@ -68,7 +68,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,19 +79,6 @@ 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); 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..a10c94093 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java @@ -34,6 +34,7 @@ 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; @@ -83,7 +84,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 +96,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); } @@ -171,7 +174,7 @@ public class CreateKeyPassphraseFragment extends Fragment { mName, mEmail, mAdditionalEmails, - mPassphraseEdit.getText().toString() + new Passphrase(mPassphraseEdit.getText()) ); hideKeyboard(); 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 7e33843ea..71832daa5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -191,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); @@ -265,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); @@ -341,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 513300cc5..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); 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..30cf739fc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -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 8d16fe47e..d2c1ab74c 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 { @@ -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 ); } @@ -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 c89707c34..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 { @@ -39,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 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 f1784fab3..0dd672c90 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; @@ -72,7 +73,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi private long mEncryptionKeyIds[] = null; private String mEncryptionUserIds[] = null; private long mSigningKeyId = Constants.key.none; - private String mPassphrase = ""; + private Passphrase mPassphrase = new Passphrase(); private ArrayList mInputUris; private ArrayList mOutputUris; @@ -136,7 +137,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi } @Override - public void setPassphrase(String passphrase) { + public void setPassphrase(Passphrase passphrase) { mPassphrase = passphrase; } @@ -243,8 +244,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi 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); 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 14f2c492d..847f745d7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -36,6 +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.Passphrase; import org.sufficientlysecure.keychain.util.ShareHelper; import java.util.ArrayList; @@ -70,7 +71,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv 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 Passphrase mPassphrase = new Passphrase(); private ArrayList mInputUris; private ArrayList mOutputUris; @@ -134,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; } @@ -223,8 +225,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); 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 48509710a..360d30c82 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; /** @@ -318,7 +319,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) { @@ -395,7 +396,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/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/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java new file mode 100644 index 000000000..34cb9af8e --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.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; + +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() + System.gc(); + } + + public Passphrase(EditText editText) { + this(editText.getText()); + } + + public Passphrase(String passphrase) { + mPassphrase = passphrase.toCharArray(); + } + + public Passphrase() { + setEmpty(); + } + + public char[] getCharArray() { + return mPassphrase; + } + + public boolean isEmpty() { + return (mPassphrase.length == 0); + } + + public void setEmpty() { + removeFromMemory(); + mPassphrase = new char[0]; + } + + public void removeFromMemory() { + if (mPassphrase != null) { + Arrays.fill(mPassphrase, ' '); + System.gc(); + } + } + + @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 CREATOR = new Creator() { + 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; + } +} -- cgit v1.2.3 From e65efce333f700eb7f5303e5994e6a1b36f81462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 19 Mar 2015 03:30:12 +0100 Subject: Fix tests for Passphrase class --- .../keychain/operations/CertifyOperationTest.java | 9 ++++---- .../keychain/operations/ExportTest.java | 9 ++++---- .../operations/PromoteKeyOperationTest.java | 3 ++- .../keychain/pgp/PgpEncryptDecryptTest.java | 14 ++++++------ .../keychain/pgp/PgpKeyOperationTest.java | 25 +++++++++++----------- .../pgp/UncachedKeyringCanonicalizeTest.java | 5 +++-- .../keychain/pgp/UncachedKeyringMergeTest.java | 19 ++++++++-------- .../keychain/pgp/UncachedKeyringTest.java | 3 ++- .../keychain/util/TestingUtils.java | 25 ++++++++++++++++------ .../keychain/util/Passphrase.java | 4 ++++ 10 files changed, 71 insertions(+), 45 deletions(-) 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 0af87ada4..7c4b2e91e 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/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 onlyA, ArrayList onlyB, - String passphrase) { + Passphrase passphrase) { return applyModificationWithChecks(parcel, ring, onlyA, onlyB, passphrase, true, true); } @@ -1180,7 +1181,7 @@ public class PgpKeyOperationTest { UncachedKeyRing ring, ArrayList onlyA, ArrayList 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 ee0379653..f45e82c3e 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,16 +1,29 @@ package org.sufficientlysecure.keychain.util; +/* + * Copyright (C) 2014 Vincent Breitmoser + * + * 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 . + */ import java.util.Random; -/** - * Created by valodim on 9/15/14. - */ 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(); @@ -19,6 +32,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/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java index 34cb9af8e..45dac3b64 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java @@ -46,6 +46,10 @@ public class Passphrase implements Parcelable { this(editText.getText()); } + public Passphrase(char[] passphrase) { + mPassphrase = passphrase; + } + public Passphrase(String passphrase) { mPassphrase = passphrase.toCharArray(); } -- cgit v1.2.3 From 834ce03f9e4de465782b67bf7827445c6028eb8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 19 Mar 2015 03:30:49 +0100 Subject: Fix header --- .../test/java/org/sufficientlysecure/keychain/util/TestingUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 f45e82c3e..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,4 +1,3 @@ -package org.sufficientlysecure.keychain.util; /* * Copyright (C) 2014 Vincent Breitmoser * @@ -16,6 +15,8 @@ package org.sufficientlysecure.keychain.util; * along with this program. If not, see . */ +package org.sufficientlysecure.keychain.util; + import java.util.Random; public class TestingUtils { -- cgit v1.2.3 From 0bcc2793c334ad04d3f7fd9f401eb6ab485f8c39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 19 Mar 2015 13:58:26 +0100 Subject: Improve Passphrase class with finalize() --- .../keychain/util/Passphrase.java | 40 ++++++++++++++++++---- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java index 45dac3b64..06efdde4d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Passphrase.java @@ -26,6 +26,16 @@ 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: + *

+ * 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; @@ -39,7 +49,6 @@ public class Passphrase implements Parcelable { editable.getChars(0, pl, mPassphrase, 0); // TODO: clean up internal char[] of EditText after getting the passphrase? // editText.getText().replace() - System.gc(); } public Passphrase(EditText editText) { @@ -54,6 +63,9 @@ public class Passphrase implements Parcelable { mPassphrase = passphrase.toCharArray(); } + /** + * Creates a passphrase object with an empty ("") passphrase + */ public Passphrase() { setEmpty(); } @@ -62,22 +74,38 @@ public class Passphrase implements Parcelable { return mPassphrase; } - public boolean isEmpty() { - return (mPassphrase.length == 0); - } - 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, ' '); - System.gc(); } } + @Override + public void finalize() throws Throwable { + removeFromMemory(); + super.finalize(); + } + @Override public String toString() { if (Constants.DEBUG) { -- cgit v1.2.3 From d122d27ebadbc883ba85e2256f1a0a29f791ee60 Mon Sep 17 00:00:00 2001 From: Manoj Khanna Date: Wed, 18 Mar 2015 17:53:24 +0530 Subject: Fixed a crash on ViewKeyActivity This occurs when deleting a key with a stripped master key from the ViewKeyActivity. --- .../keychain/ui/ViewKeyActivity.java | 91 ++++++++++++---------- .../keychain/util/ExportHelper.java | 15 ---- 2 files changed, 51 insertions(+), 55 deletions(-) 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 13a5ac269..5834fa502 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -74,6 +74,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; 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; @@ -310,31 +312,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: { @@ -473,22 +475,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 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 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.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); + 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 @@ -500,7 +512,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 @@ -531,18 +547,13 @@ public class ViewKeyActivity extends BaseActivity implements } if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){ - deleteKey(mDataUri, mExportHelper); + deleteKey(); } + 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); - } + exportToFile(mDataUri, mExportHelper, mProviderHelper); } - if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); result.createNotify(this).show(); 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 */ -- cgit v1.2.3 From 6120365ee1e425acbc270b17c5cad621710777a9 Mon Sep 17 00:00:00 2001 From: Manoj Khanna Date: Thu, 19 Mar 2015 19:58:24 +0530 Subject: Fix for Issue #1114 Displays the snackbar above the keyboard on all activities. --- .../keychain/ui/util/Notify.java | 35 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 5 deletions(-) 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..9736b5765 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 @@ -19,6 +19,11 @@ package org.sufficientlysecure.keychain.ui.util; import android.app.Activity; import android.content.res.Resources; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.view.View; +import android.view.ViewGroup; import com.nispok.snackbar.Snackbar; import com.nispok.snackbar.Snackbar.SnackbarDuration; @@ -61,11 +66,11 @@ public class Notify { break; } - SnackbarManager.show(bar); + showSnackbar(activity, bar); } - public static Showable createNotify (Activity activity, int resId, int duration, Style style) { + public static Showable createNotify (final Activity activity, int resId, int duration, Style style) { final Snackbar bar = getSnackbar(activity) .text(resId); @@ -90,7 +95,7 @@ public class Notify { return new Showable () { @Override public void show() { - SnackbarManager.show(bar); + showSnackbar(activity, bar); } }; } @@ -104,7 +109,7 @@ public class Notify { return createNotify(activity, msg, duration, style, null, 0); } - public static Showable createNotify(Activity activity, String msg, int duration, Style style, + public static Showable createNotify(final Activity activity, String msg, int duration, Style style, final ActionListener listener, int resIdAction) { final Snackbar bar = getSnackbar(activity) @@ -141,7 +146,7 @@ public class Notify { return new Showable () { @Override public void show() { - SnackbarManager.show(bar); + showSnackbar(activity, bar); } }; @@ -178,6 +183,26 @@ public class Notify { return bar; } + private static void showSnackbar(Activity activity, Snackbar snackbar) { + if (activity instanceof FragmentActivity) { + FragmentManager fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager(); + + int count = fragmentManager.getBackStackEntryCount(); + Fragment fragment = fragmentManager.getFragments().get(count > 0 ? count - 1 : 0); + + if (fragment != null) { + View view = fragment.getView(); + + if (view != null) { + SnackbarManager.show(snackbar, (ViewGroup) view); + return; + } + } + } + + SnackbarManager.show(snackbar); + } + public interface Showable { public void show(); -- cgit v1.2.3 From 98817d13ee2e33b92f3a339df312709be027e964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 19 Mar 2015 17:16:23 +0100 Subject: Manage my keys wizard --- OpenKeychain/src/main/AndroidManifest.xml | 8 +- .../keychain/ui/CreateKeyActivity.java | 92 ++++++++---- .../keychain/ui/CreateKeyEmailFragment.java | 60 ++++---- .../keychain/ui/CreateKeyFinalFragment.java | 60 ++++---- .../keychain/ui/CreateKeyNameFragment.java | 40 +++--- .../keychain/ui/CreateKeyPassphraseFragment.java | 45 +++--- .../keychain/ui/CreateKeyStartFragment.java | 157 +++++++++++++++++++++ .../keychain/ui/FirstTimeActivity.java | 110 --------------- .../keychain/ui/KeyListFragment.java | 3 +- .../keychain/ui/MainActivity.java | 4 +- .../keychain/ui/widget/EmailEditText.java | 9 +- .../keychain/ui/widget/NameEditText.java | 6 +- .../main/res/layout/create_key_name_fragment.xml | 4 +- .../main/res/layout/create_key_start_fragment.xml | 104 ++++++++++++++ .../src/main/res/layout/first_time_activity.xml | 137 ------------------ OpenKeychain/src/main/res/menu/key_list.xml | 2 +- OpenKeychain/src/main/res/values-cs/strings.xml | 2 +- OpenKeychain/src/main/res/values-de/strings.xml | 2 +- OpenKeychain/src/main/res/values-es/strings.xml | 2 +- OpenKeychain/src/main/res/values-eu/strings.xml | 2 +- OpenKeychain/src/main/res/values-fi/strings.xml | 2 +- OpenKeychain/src/main/res/values-fr/strings.xml | 2 +- OpenKeychain/src/main/res/values-it/strings.xml | 2 +- OpenKeychain/src/main/res/values-ja/strings.xml | 2 +- OpenKeychain/src/main/res/values-nl/strings.xml | 2 +- OpenKeychain/src/main/res/values-pl/strings.xml | 2 +- OpenKeychain/src/main/res/values-ru/strings.xml | 2 +- OpenKeychain/src/main/res/values-sl/strings.xml | 2 +- OpenKeychain/src/main/res/values-sr/strings.xml | 2 +- OpenKeychain/src/main/res/values-sv/strings.xml | 2 +- OpenKeychain/src/main/res/values-tr/strings.xml | 2 +- OpenKeychain/src/main/res/values-uk/strings.xml | 2 +- .../src/main/res/values-zh-rTW/strings.xml | 2 +- OpenKeychain/src/main/res/values-zh/strings.xml | 2 +- OpenKeychain/src/main/res/values/strings.xml | 8 +- 35 files changed, 455 insertions(+), 430 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java create mode 100644 OpenKeychain/src/main/res/layout/create_key_start_fragment.xml delete mode 100644 OpenKeychain/src/main/res/layout/first_time_activity.xml diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 91c84fb18..d9f9766c9 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -86,16 +86,10 @@ - additionalEmails; - char[] passphrase; - } + public static final String FRAGMENT_TAG = "currentFragment"; - public static enum FragAction { - START, - TO_RIGHT, - TO_LEFT - } + String mName; + String mEmail; + ArrayList 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(savedInstanceState, 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); + } 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 @@ -61,23 +93,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(); @@ -86,8 +118,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 6a4dd7a41..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 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; @@ -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 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 getAdditionalEmails() { + ArrayList 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 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 { private List 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 5f6bfdb11..75f49a426 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -65,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 mAdditionalEmails; - Passphrase mPassphrase; - SaveKeyringParcel mSaveKeyringParcel; /** * Creates new instance of this fragment */ - public static CreateKeyFinalFragment newInstance(String name, String email, - ArrayList additionalEmails, - Passphrase 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.putParcelable(ARG_PASSPHRASE, passphrase); - frag.setArguments(args); return frag; @@ -108,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().getParcelable(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; @@ -128,7 +105,7 @@ public class CreateKeyFinalFragment extends Fragment { } mEmailEdit.setText(emailText); } else { - mEmailEdit.setText(mEmail); + mEmailEdit.setText(mCreateKeyActivity.mEmail); } mCreateButton.setOnClickListener(new View.OnClickListener() { @@ -141,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 +134,12 @@ public class CreateKeyFinalFragment extends Fragment { return view; } + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mCreateKeyActivity = (CreateKeyActivity) getActivity(); + } + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -187,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(new KeyRing.UserId(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(new KeyRing.UserId(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; } } 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 093d427b7..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); @@ -84,21 +76,26 @@ public class CreateKeyNameFragment extends Fragment { 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(); } }); @@ -111,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 a10c94093..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; @@ -37,18 +38,10 @@ 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 mAdditionalEmails; - // view CreateKeyActivity mCreateKeyActivity; PassphraseEditText mPassphraseEdit; @@ -60,15 +53,10 @@ public class CreateKeyPassphraseFragment extends Fragment { /** * Creates new instance of this fragment */ - public static CreateKeyPassphraseFragment newInstance(String name, String email, - ArrayList 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; @@ -121,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 @@ -134,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() { @@ -162,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, - new Passphrase(mPassphraseEdit.getText()) - ); + // 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 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.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/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 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - -import android.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/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 4b604add8..f8939f3d1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -489,7 +489,8 @@ public class KeyListFragment extends LoaderFragment 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; 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/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/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/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" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 @@ Nápověda Exportovat do souboru Smazat klíč - Vytvořit moje klíče + Vytvořit moje klíče Importovat ze souboru Hledat Beam settings 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 @@ Hilfe In Datei exportieren Schlüssel löschen - Erzeuge meinen Schlüssel + Erzeuge meinen Schlüssel Von Datei importieren Suchen NFC-Einstellungen 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 @@ Ayuda Exportar hacia archivo Borrar clave - Crear mi clave + Crear mi clave Importar desde fichero Buscar Configuraciones NFC 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 @@ Laguntza Esportatu agirira Ezabatu giltza - Sortu nire giltza + Sortu nire giltza inportatu agiritik Bilatu NFC ezarpenak 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 @@ Apua Vie tiedostoon Poista avain - Luo minun avaimeni + Luo minun avaimeni Tuo tiedostosta Etsi Beam asetukset 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 @@ Aide Exporter vers un fichier Supprimer la clef - Créer ma clef + Créer ma clef Importer depuis un fichier Rechercher Paramètres NFC 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 @@ Aiuto Esporta su un file Cancella chiave - Crea mia chiave + Crea mia chiave Importa da file Cerca Impostazioni Beam 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 @@ ヘルプ ファイルへのエクスポート 鍵の削除 - 自分の鍵の生成 + 自分の鍵の生成 ファイルからインポート 検索 NFC設定 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 @@ Help Exporteren naar bestand Sleutel verwijderen - Mijn sleutel aanmaken + Mijn sleutel aanmaken Importeren van bestand Zoeken NFC-instellingen 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 @@ Pomoc Eksportuj do pliku Usuń klucz - Utwórz mój klucz + Utwórz mój klucz Importuj z pliku Szukaj Ustawienia Beam 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 @@ Помощь Экспорт в файл Удалить ключ - Создать свой ключ + Создать свой ключ Импорт из файла Поиск Настройки NFC 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 @@ Pomoč Izvozi v datoteko Izbriši ključ - Ustvari zasebni ključ + Ustvari zasebni ključ Uvozi iz datoteke Išči Nastavitve Beam 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 @@ Помоћ Извези у фајл Обриши кључ - Направи ми кључ + Направи ми кључ Увези из фајла Претрага НФЦ поставке 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 @@ Hjälp Exportera till fil Radera nyckel - Skapa min nyckel + Skapa min nyckel Importera från fil Sök Beam-inställningar 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 @@ Yardım Dosyaya ver Anahtar sil - Anahtarımı oluştur + Anahtarımı oluştur Dosyadan al Ara NFC ayarları 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 @@ Довідка Експорт до файлу Вилучити ключ - Створити мій ключ + Створити мій ключ Імпорт з файлу Пошук Налаштування променя 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 @@ 說明 匯出到檔案 刪除金鑰 - 建立金鑰 + 建立金鑰 從檔案匯入 搜尋 Beam 設定 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 @@ 帮助 导出密钥 删除密钥 - 创建密钥 + 创建密钥 搜索 参数 取消 diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index f1c14bd32..f22a0c533 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -44,6 +44,7 @@ "Keys" "Delete YOUR key '%s'?" "Export Log" + "Manage my keys" "Identities" @@ -106,7 +107,7 @@ "Help" "Export to file" "Delete key" - "Create my key" + "Manage my keys" "Import from file" "Search" "NFC settings" @@ -1197,8 +1198,9 @@ "Take back your privacy with OpenKeychain!" - "Create my key" - "Import from file" + "Create my key (recommended)" + "Import key from file" + "Use YubiKey NEO" "Skip Setup" -- cgit v1.2.3 From cfef53be01f72da477d0cb66e40865d7dcd9b125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 19 Mar 2015 17:21:26 +0100 Subject: Remove on click on icon --- .../main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java | 2 ++ 1 file changed, 2 insertions(+) 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 eb484302c..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,6 +20,7 @@ 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; @@ -72,6 +73,7 @@ public class CreateKeyActivity extends BaseActivity { if (mFirstTime) { setTitle(R.string.app_name); setActionBarIcon(R.drawable.ic_launcher); + mToolbar.setNavigationOnClickListener(null); } else { setTitle(R.string.title_manage_my_keys); } -- cgit v1.2.3 From 4d43950841b567d83e7879ed00702253fd9ba5b2 Mon Sep 17 00:00:00 2001 From: Kent Date: Fri, 20 Mar 2015 06:11:50 +0800 Subject: - Added footer so that the Floating Action Button won't block the last few items' content --- .../keychain/ui/KeyListFragment.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index f8939f3d1..793fb4524 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,7 +385,7 @@ 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 @@ -909,5 +925,4 @@ public class KeyListFragment extends LoaderFragment } - } -- cgit v1.2.3 From 8d6d4328f23b527be9ea794433b3f160cd58e5a5 Mon Sep 17 00:00:00 2001 From: Kent Date: Fri, 20 Mar 2015 06:31:18 +0800 Subject: Implemented #1162: Invoke NFC in Advanced View - Extracted NFC code from ViewKeyActivity to NfcHelper to share code between classes - Changed the private anonymous Handler for NFC into a static private subclass, that uses WeakReference to avoid memory leaks - Added resources needed (retrieved from Graphics) for the NFC button inside ViewKeyAdvShareFragment. - Fixed the ripple boundary of the Share With... button to prevent it from bleeding to other buttons on the right (UX improvement) --- .../keychain/ui/ViewKeyActivity.java | 169 ++--------------- .../keychain/ui/ViewKeyAdvShareFragment.java | 21 ++- .../keychain/util/NfcHelper.java | 204 +++++++++++++++++++++ .../main/res/drawable-hdpi/ic_nfc_grey_24dp.png | Bin 0 -> 1059 bytes .../main/res/drawable-mdpi/ic_nfc_grey_24dp.png | Bin 0 -> 701 bytes .../main/res/drawable-xhdpi/ic_nfc_grey_24dp.png | Bin 0 -> 1359 bytes .../main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png | Bin 0 -> 2040 bytes .../main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png | Bin 0 -> 2756 bytes .../res/layout/view_key_adv_share_fragment.xml | 25 ++- 9 files changed, 261 insertions(+), 158 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java create mode 100644 OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png create mode 100644 OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png create mode 100644 OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png create mode 100644 OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png create mode 100644 OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png 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 5834fa502..45ad944c4 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.LoaderManager; import android.support.v4.content.CursorLoader; @@ -58,9 +51,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; @@ -84,6 +75,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 +85,8 @@ public class ViewKeyActivity extends BaseActivity implements LoaderManager.LoaderCallbacks { 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 +107,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 +244,7 @@ public class ViewKeyActivity extends BaseActivity implements mActionNfc.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - invokeNfcBeam(); + mNfcHelper.invokeNfcBeam(); } }); @@ -264,7 +252,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); startFragment(savedInstanceState, mDataUri); } @@ -375,41 +364,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); @@ -426,7 +380,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); } @@ -487,11 +441,11 @@ public class ViewKeyActivity extends BaseActivity implements HashMap 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}); + 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)}, + 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) { @@ -515,7 +469,7 @@ public class ViewKeyActivity extends BaseActivity implements // Create a new Messenger for the communication back Messenger messenger = new Messenger(returnHandler); DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - new long[]{ mMasterKeyId }); + new long[] {mMasterKeyId}); deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog"); } @@ -546,11 +500,11 @@ public class ViewKeyActivity extends BaseActivity implements return; } - if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){ + if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK) { deleteKey(); } - if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK){ + if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK) { exportToFile(mDataUri, mExportHelper, mProviderHelper); } @@ -572,7 +526,7 @@ public class ViewKeyActivity extends BaseActivity implements 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); @@ -710,98 +664,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 initTask = - new AsyncTask() { - 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, @@ -1018,4 +883,4 @@ public class ViewKeyActivity extends BaseActivity implements public void onLoaderReset(Loader loader) { } -} +} \ No newline at end of file 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..29586ae9f 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) { @@ -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/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java new file mode 100644 index 000000000..bae42d965 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java @@ -0,0 +1,204 @@ +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. + *

+ * Created on Mar 20, 2015. + * + * @author Kent + */ + +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 initTask = + new AsyncTask() { + 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.createNotify(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.createNotify(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.createNotify(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 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.showNotify( + activity, R.string.nfc_successful, Notify.Style.INFO); + break; + } + } + } + } + +} \ No newline at end of file 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 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-hdpi/ic_nfc_grey_24dp.png 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 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-mdpi/ic_nfc_grey_24dp.png 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 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xhdpi/ic_nfc_grey_24dp.png 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 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxhdpi/ic_nfc_grey_24dp.png 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 Binary files /dev/null and b/OpenKeychain/src/main/res/drawable-xxxhdpi/ic_nfc_grey_24dp.png differ 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" /> + android:gravity="center_vertical" + android:background="?android:selectableItemBackground"/> + + + + + Date: Fri, 20 Mar 2015 12:24:06 +0800 Subject: Removed create and added GPLv3 header --- .../sufficientlysecure/keychain/util/NfcHelper.java | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java index bae42d965..3d225eb04 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.sufficientlysecure.keychain.util; import android.annotation.TargetApi; @@ -24,10 +41,6 @@ import java.lang.ref.WeakReference; /** * This class contains NFC functionality that can be shared across Fragments or Activities. - *

- * Created on Mar 20, 2015. - * - * @author Kent */ public class NfcHelper { -- cgit v1.2.3 From 50913d0ff1f29d4d32c36b1924b20fc8ef3a76bc Mon Sep 17 00:00:00 2001 From: Kent Date: Fri, 20 Mar 2015 12:38:16 +0800 Subject: Updated GNU header --- .../src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java index 3d225eb04..a65576613 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java @@ -1,5 +1,6 @@ /* - * Copyright (C) 2014 Vincent Breitmoser + * Copyright (C) 2013-2014 Dominik Schrmann + * Copyright (C) 2015 Kent Nguyen * * 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 -- cgit v1.2.3 From 9e668eadcb5dc5737f3df94339a1fa1e8662f0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 20 Mar 2015 13:38:07 +0100 Subject: Fix PASSPHRASE handling in API --- .../keychain/remote/OpenPgpService.java | 20 ++++++++++++++++++-- extern/openpgp-api-lib | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) 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 98a9ff44f..4707a2ad5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -240,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)); @@ -278,6 +283,7 @@ public class OpenPgpService extends RemoteService { // sign-only PgpSignEncryptInput pseInput = new PgpSignEncryptInput() + .setSignaturePassphrase(passphrase) .setEnableAsciiArmorOutput(asciiArmor) .setCleartextSignature(cleartextSign) .setDetachedSignature(!cleartextSign) @@ -366,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) { @@ -391,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) @@ -499,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 allowedKeyIds; if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) { @@ -509,7 +526,6 @@ public class OpenPgpService extends RemoteService { KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg)); } - Passphrase passphrase = data.getParcelableExtra(OpenPgpApi.EXTRA_PASSPHRASE); long inputLength = is.available(); InputData inputData = new InputData(is, inputLength); diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index d10df1d40..34ccf4df4 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit d10df1d40f23475445d0abca217683e911ffa0a0 +Subproject commit 34ccf4df41a30cb586f06eb3b9bc90efc8dd7a2c -- cgit v1.2.3 From ebf9bb3a6392cc5f2938c57e83bdb908c5b6e1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 20 Mar 2015 13:51:06 +0100 Subject: Fix API RESULT_TYPE --- .../java/org/sufficientlysecure/keychain/remote/OpenPgpService.java | 6 ++++-- .../main/java/org/sufficientlysecure/keychain/util/NfcHelper.java | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) 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 4707a2ad5..660556509 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -571,15 +571,14 @@ public class OpenPgpService extends RemoteService { } } else if (pgpResult.success()) { Intent result = new Intent(); - int resultType = OpenPgpApi.RESULT_TYPE_UNENCRYPTED_UNSIGNED; OpenPgpSignatureResult signatureResult = pgpResult.getSignatureResult(); + 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); @@ -599,7 +598,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/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java index a65576613..33510fb7e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 Dominik Schrmann + * Copyright (C) 2013-2014 Dominik Schürmann * Copyright (C) 2015 Kent Nguyen * * This program is free software: you can redistribute it and/or modify @@ -32,6 +32,7 @@ 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; -- cgit v1.2.3 From 75cd80fd379a86929056e8adbf40c8cebdaa691e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 20 Mar 2015 14:35:16 +0100 Subject: Update OpenPGP API lib --- extern/openpgp-api-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 34ccf4df4..70a17dcbe 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 34ccf4df41a30cb586f06eb3b9bc90efc8dd7a2c +Subproject commit 70a17dcbeb5d8de095f09a7ce756543deff0165a -- cgit v1.2.3 From 2153aea1976f1609eda547f5fdb55f615f7c18dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 20 Mar 2015 15:15:47 +0100 Subject: Update api lib --- extern/openpgp-api-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 70a17dcbe..9abb91d3a 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 70a17dcbeb5d8de095f09a7ce756543deff0165a +Subproject commit 9abb91d3a69964a547f26aa1d56de233e75c4410 -- cgit v1.2.3 From 4e4b8efd6ea275d5fe2d07c188ab8a2581617ec6 Mon Sep 17 00:00:00 2001 From: Manoj Khanna Date: Fri, 20 Mar 2015 18:23:23 +0530 Subject: Reworked Notify class --- .../keychain/operations/results/CertifyResult.java | 2 +- .../keychain/operations/results/DeleteResult.java | 2 +- .../operations/results/ImportKeyResult.java | 2 +- .../operations/results/OperationResult.java | 26 +-- .../keychain/remote/ui/RemoteServiceActivity.java | 2 +- .../service/KeychainIntentServiceHandler.java | 4 +- .../keychain/ui/CertifyKeyFragment.java | 8 +- .../keychain/ui/CreateKeyFinalFragment.java | 4 +- .../keychain/ui/DecryptFilesFragment.java | 2 +- .../keychain/ui/DecryptTextActivity.java | 4 +- .../keychain/ui/DecryptTextFragment.java | 2 +- .../keychain/ui/EditKeyFragment.java | 4 +- .../keychain/ui/EncryptFilesActivity.java | 12 +- .../keychain/ui/EncryptFilesFragment.java | 8 +- .../keychain/ui/EncryptTextActivity.java | 17 +- .../keychain/ui/ImportKeysActivity.java | 6 +- .../keychain/ui/KeyListFragment.java | 12 +- .../keychain/ui/QrCodeViewActivity.java | 4 +- .../keychain/ui/SafeSlingerActivity.java | 2 +- .../keychain/ui/ViewKeyActivity.java | 10 +- .../keychain/ui/ViewKeyAdvShareFragment.java | 10 +- .../keychain/ui/dialog/FileDialogFragment.java | 2 +- .../keychain/ui/util/Notify.java | 196 ++++++++------------- .../keychain/util/NfcHelper.java | 9 +- extern/openpgp-api-lib | 2 +- 25 files changed, 154 insertions(+), 198 deletions(-) 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/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 068e314d5..f2a27b0fc 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/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/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/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index a0f89b06a..b3738851c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -169,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(); } @@ -360,8 +360,8 @@ public class CertifyKeyFragment extends LoaderFragment // Bail out if there is not at least one user id selected ArrayList 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/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java index 75f49a426..cbe3eecd4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -277,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/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index 71832daa5..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; } 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 30cf739fc..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 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 d2c1ab74c..61a02720e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -577,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; } 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 0dd672c90..fe9b05226 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -303,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... @@ -317,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; } @@ -333,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; } } 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 9c9b44511..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; } @@ -153,7 +153,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt 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) { @@ -169,7 +169,7 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt 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/EncryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java index 847f745d7..c800153ae 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -198,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)); } } @@ -281,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; } @@ -289,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; } @@ -304,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; } } 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..d59936967 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -277,7 +277,7 @@ 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(); return false; } else { return true; @@ -372,7 +372,7 @@ 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(); } } else if (ls instanceof ImportKeysListFragment.CloudLoaderState) { ImportKeysListFragment.CloudLoaderState sls = (ImportKeysListFragment.CloudLoaderState) ls; @@ -412,7 +412,7 @@ 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(); } } 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 793fb4524..5f1189deb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -390,8 +390,8 @@ public class KeyListFragment extends LoaderFragment 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; } @@ -484,21 +484,21 @@ 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; 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 45ad944c4..484956e6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -338,7 +338,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; } @@ -449,7 +449,7 @@ public class ViewKeyActivity extends BaseActivity implements Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0) ); } 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(); Log.e(Constants.TAG, "Key not found", e); } } @@ -486,14 +486,14 @@ 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(); } @@ -519,7 +519,7 @@ 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 { 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 29586ae9f..6bd3a9303 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -199,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; } @@ -223,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(); } } 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/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java index 9736b5765..4224fb9a2 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,10 +18,7 @@ package org.sufficientlysecure.keychain.ui.util; import android.app.Activity; -import android.content.res.Resources; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; import android.view.View; import android.view.ViewGroup; @@ -40,135 +37,49 @@ 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 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; - } - - showSnackbar(activity, bar); - - } - - public static Showable createNotify (final 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)); + snackbar.actionColorResource(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() { - showSnackbar(activity, 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); - } - - public static Showable createNotify(final Activity activity, String msg, int duration, Style style, - final ActionListener listener, int resIdAction) { - - final Snackbar bar = getSnackbar(activity) - .text(msg); - - if (listener != null) { - bar.actionLabel(resIdAction); - bar.actionListener(new ActionClickListener() { - @Override - public void onActionClicked(Snackbar snackbar) { - listener.onAction(); - } - }); - } - - if (duration == LENGTH_INDEFINITE) { - bar.duration(SnackbarDuration.LENGTH_INDEFINITE); - } else { - bar.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)); + snackbar.textColorResource(R.color.android_orange_light); break; + case ERROR: - bar.textColor(activity.getResources().getColor(R.color.android_red_light)); + snackbar.textColorResource(R.color.android_red_light); break; } - return new Showable () { - @Override - public void show() { - showSnackbar(activity, bar); - } - }; - - } - - /** - * 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); - } - - private static Snackbar getSnackbar(final Activity activity) { - Snackbar bar = Snackbar.with(activity) - .type(SnackbarType.MULTI_LINE) - .duration(SnackbarDuration.LENGTH_LONG); + if (actionListener != null) { + snackbar.actionLabel(actionResId) + .actionListener(new ActionClickListener() { + @Override + public void onActionClicked(Snackbar snackbar) { + actionListener.onAction(); + } + }); + } if (activity instanceof FabContainer) { - bar.eventListener(new EventListenerAdapter() { + snackbar.eventListener(new EventListenerAdapter() { @Override public void onShow(Snackbar snackbar) { ((FabContainer) activity).fabMoveUp(snackbar.getHeight()); @@ -180,37 +91,74 @@ public class Notify { } }); } - return bar; - } - private static void showSnackbar(Activity activity, Snackbar snackbar) { - if (activity instanceof FragmentActivity) { - FragmentManager fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager(); + return new Showable() { + @Override + public void show() { + SnackbarManager.show(snackbar, activity); + } - int count = fragmentManager.getBackStackEntryCount(); - Fragment fragment = fragmentManager.getFragments().get(count > 0 ? count - 1 : 0); + @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; + } + } - if (fragment != null) { - View view = fragment.getView(); + show(); + } - if (view != null) { - SnackbarManager.show(snackbar, (ViewGroup) view); + @Override + 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); + } - SnackbarManager.show(snackbar); + public static Showable create(Activity activity, String text, Style style) { + return create(activity, text, LENGTH_LONG, style); + } + + 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); + } + + public static Showable create(Activity activity, int textResId, int duration, Style style) { + return create(activity, activity.getString(textResId), duration, style); + } + + public static Showable create(Activity activity, int textResId, Style style) { + return create(activity, activity.getString(textResId), style); } public interface Showable { + public void show(); + public void show(Fragment fragment); + + 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/util/NfcHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java index 33510fb7e..e4e4e4d05 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/NfcHelper.java @@ -159,13 +159,13 @@ public class NfcHelper { public void invokeNfcBeam() { // Check if device supports NFC if (!mActivity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) { - Notify.createNotify(mActivity, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + 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.createNotify(mActivity, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() { + 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); @@ -177,7 +177,7 @@ public class NfcHelper { } if (!mNfcAdapter.isNdefPushEnabled()) { - Notify.createNotify(mActivity, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() { + 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); @@ -208,8 +208,7 @@ public class NfcHelper { if (activity != null) { switch (msg.what) { case NFC_SENT: - Notify.showNotify( - activity, R.string.nfc_successful, Notify.Style.INFO); + Notify.create(activity, R.string.nfc_successful, Notify.Style.OK).show(); break; } } diff --git a/extern/openpgp-api-lib b/extern/openpgp-api-lib index 9abb91d3a..70a17dcbe 160000 --- a/extern/openpgp-api-lib +++ b/extern/openpgp-api-lib @@ -1 +1 @@ -Subproject commit 9abb91d3a69964a547f26aa1d56de233e75c4410 +Subproject commit 70a17dcbeb5d8de095f09a7ce756543deff0165a -- cgit v1.2.3 From fa8d5657bec8fc8106635fd7a5d4ad17256fb93b Mon Sep 17 00:00:00 2001 From: Manoj Khanna Date: Fri, 20 Mar 2015 18:35:20 +0530 Subject: Fixed Snackbar behind keyboard on ImportKeysActivity --- .../keychain/ui/ImportKeysActivity.java | 13 +++++++++---- .../src/main/res/layout/import_keys_activity.xml | 20 +++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) 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 d59936967..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.create(this, R.string.import_qr_code_too_short_fingerprint, Notify.Style.ERROR).show(); + 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.create(this, "Problem writing cache file!", Notify.Style.ERROR).show(); + 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.create(this, R.string.error_nothing_import, Notify.Style.ERROR).show(); + Notify.create(this, R.string.error_nothing_import, Notify.Style.ERROR) + .show((ViewGroup) findViewById(R.id.import_snackbar)); } } 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" /> - - + + + \ No newline at end of file -- cgit v1.2.3 From 850a3747886064d648e7fe2436eff9531eb6011c Mon Sep 17 00:00:00 2001 From: Manoj Khanna Date: Fri, 20 Mar 2015 19:19:35 +0530 Subject: Added docs for Notify class --- .../java/org/sufficientlysecure/keychain/ui/util/Notify.java | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 4224fb9a2..3121e02ef 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 @@ -147,10 +147,20 @@ public class Notify { 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); } -- cgit v1.2.3 From 10f9dcd7a1e59a3302639e43df6b57a360f9563b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 21 Mar 2015 15:43:36 +0100 Subject: Add TODO to remote API --- .../java/org/sufficientlysecure/keychain/remote/OpenPgpService.java | 2 ++ 1 file changed, 2 insertions(+) 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 660556509..bd2866985 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -573,6 +573,8 @@ public class OpenPgpService extends RemoteService { Intent result = new Intent(); 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; -- cgit v1.2.3 From 8b4388e1a2d5cb2b7f0524c18ad3383e3375ba7b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 22 Mar 2015 16:55:46 +0100 Subject: use top line in snackbar for status indication --- .gitmodules | 3 ++ OpenKeychain/build.gradle | 4 +-- .../keychain/ui/util/Notify.java | 37 ++++++++++++++-------- extern/snackbar | 1 + settings.gradle | 1 + 5 files changed, 30 insertions(+), 16 deletions(-) create mode 160000 extern/snackbar 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/build.gradle b/OpenKeychain/build.gradle index 97c8a6d5e..b3ab0b3ef 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' // libs as submodules @@ -34,6 +33,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 @@ -50,7 +50,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/java/org/sufficientlysecure/keychain/ui/util/Notify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/Notify.java index 3121e02ef..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 @@ -37,7 +37,28 @@ import org.sufficientlysecure.keychain.util.FabContainer; */ public class Notify { - public static enum Style {OK, WARN, 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; @@ -54,19 +75,7 @@ public class Notify { snackbar.duration(duration); } - switch (style) { - case OK: - snackbar.actionColorResource(R.color.android_green_light); - break; - - case WARN: - snackbar.textColorResource(R.color.android_orange_light); - break; - - case ERROR: - snackbar.textColorResource(R.color.android_red_light); - break; - } + style.applyToBar(snackbar); if (actionListener != null) { snackbar.actionLabel(actionResId) diff --git a/extern/snackbar b/extern/snackbar new file mode 160000 index 000000000..025ecadc5 --- /dev/null +++ b/extern/snackbar @@ -0,0 +1 @@ +Subproject commit 025ecadc592e591a96fa081265667efc0b0f0e15 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' -- cgit v1.2.3