aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-03-08 01:49:22 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2015-03-08 01:49:22 +0100
commit2b5023a75d0c98738ed1aea2ea89de007cf2e3d7 (patch)
tree8617aa8dcad7e32c9cb5b8483534d888aaf0c7d0 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
parent581cad5b3f7b54fae652e2598b4e760eb19678d2 (diff)
parent4f11fb5a2f08ecf5fb81c86d590d04387cd1cd9a (diff)
downloadopen-keychain-2b5023a75d0c98738ed1aea2ea89de007cf2e3d7.tar.gz
open-keychain-2b5023a75d0c98738ed1aea2ea89de007cf2e3d7.tar.bz2
open-keychain-2b5023a75d0c98738ed1aea2ea89de007cf2e3d7.zip
Merge branch 'development' into linked-identities
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java54
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java2
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java39
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java27
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java149
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java124
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java36
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java10
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java97
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java101
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java117
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java360
14 files changed, 839 insertions, 281 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
index ac74e87ed..b496d40fd 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java
@@ -20,9 +20,6 @@ package org.sufficientlysecure.keychain.ui;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Patterns;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -33,17 +30,19 @@ 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.PasswordEditText;
+import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView;
import org.sufficientlysecure.keychain.util.ContactHelper;
-import java.util.regex.Matcher;
-
public class CreateKeyInputFragment extends Fragment {
CreateKeyActivity mCreateKeyActivity;
+ PasswordStrengthView mPassphraseStrengthView;
AutoCompleteTextView mNameEdit;
- AutoCompleteTextView mEmailEdit;
- EditText mPassphraseEdit;
+ EmailEditText mEmailEdit;
+ PasswordEditText mPassphraseEdit;
EditText mPassphraseEditAgain;
View mCreateButton;
@@ -69,9 +68,11 @@ public class CreateKeyInputFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.create_key_input_fragment, container, false);
+ mPassphraseStrengthView = (PasswordStrengthView) view.findViewById(R.id
+ .create_key_passphrase_strength);
mNameEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_name);
- mEmailEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_email);
- mPassphraseEdit = (EditText) view.findViewById(R.id.create_key_passphrase);
+ mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email);
+ mPassphraseEdit = (PasswordEditText) view.findViewById(R.id.create_key_passphrase);
mPassphraseEditAgain = (EditText) view.findViewById(R.id.create_key_passphrase_again);
mCreateButton = view.findViewById(R.id.create_key_button);
@@ -95,33 +96,7 @@ public class CreateKeyInputFragment extends Fragment {
ContactHelper.getPossibleUserEmails(getActivity())
)
);
- mEmailEdit.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
- }
- @Override
- public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
- }
-
- @Override
- public void afterTextChanged(Editable editable) {
- String email = editable.toString();
- if (email.length() > 0) {
- Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
- if (emailMatcher.matches()) {
- mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0,
- R.drawable.uid_mail_ok, 0);
- } else {
- mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0,
- R.drawable.uid_mail_bad, 0);
- }
- } else {
- // remove drawable if email is empty
- mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
- }
- }
- });
mNameEdit.setThreshold(1); // Start working from first character
mNameEdit.setAdapter(
@@ -131,6 +106,15 @@ public class CreateKeyInputFragment extends Fragment {
)
);
+ // Edit text padding doesn't work via xml (http://code.google.com/p/android/issues/detail?id=77982)
+ // so we set the right padding programmatically.
+ mPassphraseEdit.setPadding(mPassphraseEdit.getPaddingLeft(),
+ mPassphraseEdit.getPaddingTop(),
+ (int) (56 * getResources().getDisplayMetrics().density),
+ mPassphraseEdit.getPaddingBottom());
+
+ mPassphraseEdit.setPasswordStrengthView(mPassphraseStrengthView);
+
mCreateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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 7d8fd1388..60103f344 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -243,7 +243,7 @@ public abstract class DecryptFragment extends Fragment {
private void setShowAction(final long signatureKeyId) {
mSignatureAction.setText(R.string.decrypt_result_action_show);
- mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0);
+ mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_vpn_key_grey_24dp, 0);
mSignatureLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
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 54fe369a7..baf445293 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java
@@ -28,6 +28,7 @@ public interface EncryptActivityInterface {
}
public boolean isUseArmor();
+ public boolean isUseCompression();
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 1286617d3..11b596c24 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java
@@ -25,11 +25,13 @@ import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuItem;
+import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
@@ -66,6 +68,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
private long mSigningKeyId = Constants.key.none;
private String mPassphrase = "";
private boolean mUseArmor;
+ private boolean mUseCompression;
private boolean mDeleteAfterEncrypt = false;
private boolean mShareAfterEncrypt = false;
private ArrayList<Uri> mInputUris;
@@ -82,6 +85,11 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
}
@Override
+ public boolean isUseCompression() {
+ return mUseCompression;
+ }
+
+ @Override
public long getSignatureKey() {
return mSigningKeyId;
}
@@ -196,10 +204,13 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
data.addInputUris(mInputUris);
data.addOutputUris(mOutputUris);
- data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression());
-
- // Always use armor for messages
- data.setEnableAsciiArmorOutput(mUseArmor);
+ if (mUseCompression) {
+ data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0));
+ } else {
+ data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
+ }
+ data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
+ data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
if (isModeSymmetric()) {
Log.d(Constants.TAG, "Symmetric encryption enabled!");
@@ -315,8 +326,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
// Handle intent actions
handleActions(getIntent());
updateModeFragment();
-
- mUseArmor = Preferences.getPreferences(this).getDefaultAsciiArmor();
}
@Override
@@ -327,7 +336,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.encrypt_file_activity, menu);
- menu.findItem(R.id.check_use_armor).setChecked(mUseArmor);
return super.onCreateOptionsMenu(menu);
}
@@ -348,21 +356,30 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
item.setChecked(!item.isChecked());
}
switch (item.getItemId()) {
- case R.id.check_use_symmetric:
+ case R.id.check_use_symmetric: {
mCurrentMode = item.isChecked() ? MODE_SYMMETRIC : MODE_ASYMMETRIC;
updateModeFragment();
notifyUpdate();
break;
- case R.id.check_use_armor:
+ }
+ case R.id.check_use_armor: {
mUseArmor = item.isChecked();
notifyUpdate();
break;
- case R.id.check_delete_after_encrypt:
+ }
+ case R.id.check_delete_after_encrypt: {
mDeleteAfterEncrypt = item.isChecked();
notifyUpdate();
break;
- default:
+ }
+ case R.id.check_enable_compression: {
+ mUseCompression = item.isChecked();
+ notifyUpdate();
+ break;
+ }
+ default: {
return super.onOptionsItemSelected(item);
+ }
}
return true;
}
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 2dd861d07..08ff5b962 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java
@@ -25,12 +25,14 @@ import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuItem;
+import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.operations.results.SignEncryptResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.PgpConstants;
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
@@ -70,6 +72,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
private ArrayList<Uri> mInputUris;
private ArrayList<Uri> mOutputUris;
private String mMessage = "";
+ private boolean mUseCompression;
public boolean isModeSymmetric() {
return MODE_SYMMETRIC == mCurrentMode;
@@ -81,6 +84,11 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
}
@Override
+ public boolean isUseCompression() {
+ return mUseCompression;
+ }
+
+ @Override
public long getSignatureKey() {
return mSigningKeyId;
}
@@ -189,7 +197,13 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
data.setBytes(mMessage.getBytes());
data.setCleartextSignature(true);
- data.setCompressionId(Preferences.getPreferences(this).getDefaultMessageCompression());
+ if (mUseCompression) {
+ data.setCompressionId(PgpConstants.sPreferredCompressionAlgorithms.get(0));
+ } else {
+ data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED);
+ }
+ data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
+ data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED);
// Always use armor for messages
data.setEnableAsciiArmorOutput(true);
@@ -328,13 +342,20 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
item.setChecked(!item.isChecked());
}
switch (item.getItemId()) {
- case R.id.check_use_symmetric:
+ case R.id.check_use_symmetric: {
mCurrentMode = item.isChecked() ? MODE_SYMMETRIC : MODE_ASYMMETRIC;
updateModeFragment();
notifyUpdate();
break;
- default:
+ }
+ case R.id.check_enable_compression: {
+ mUseCompression = item.isChecked();
+ notifyUpdate();
+ break;
+ }
+ default: {
return super.onOptionsItemSelected(item);
+ }
}
return true;
}
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 a44eef216..43d893fa6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -678,9 +678,6 @@ public class KeyListFragment extends LoaderFragment
/**
* Bind cursor data to the item list view
- * <p/>
- * NOTE: CursorAdapter already implements the ViewHolder pattern in its getView() method.
- * Thus no ViewHolder is required here.
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
index 53986a392..210960b65 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java
@@ -33,8 +33,6 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import org.spongycastle.bcpg.CompressionAlgorithmTags;
-import org.spongycastle.bcpg.HashAlgorithmTags;
-import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
@@ -93,12 +91,6 @@ public class SettingsActivity extends PreferenceActivity {
initializePassphraseCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL));
- initializeEncryptionAlgorithm(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM));
-
- initializeHashAlgorithm(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM));
-
int[] valueIds = new int[]{
CompressionAlgorithmTags.UNCOMPRESSED,
CompressionAlgorithmTags.ZIP,
@@ -115,20 +107,6 @@ public class SettingsActivity extends PreferenceActivity {
values[i] = "" + valueIds[i];
}
- initializeMessageCompression(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION),
- entries, values);
-
- initializeFileCompression(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
- entries, values);
-
- initializeAsciiArmor(
- (CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR));
-
- initializeWriteVersionHeader(
- (CheckBoxPreference) findPreference(Constants.Pref.WRITE_VERSION_HEADER));
-
initializeUseDefaultYubikeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN));
@@ -265,12 +243,6 @@ public class SettingsActivity extends PreferenceActivity {
initializePassphraseCacheTtl(
(IntegerListPreference) findPreference(Constants.Pref.PASSPHRASE_CACHE_TTL));
- initializeEncryptionAlgorithm(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_ENCRYPTION_ALGORITHM));
-
- initializeHashAlgorithm(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_HASH_ALGORITHM));
-
int[] valueIds = new int[]{
CompressionAlgorithmTags.UNCOMPRESSED,
CompressionAlgorithmTags.ZIP,
@@ -290,20 +262,6 @@ public class SettingsActivity extends PreferenceActivity {
values[i] = "" + valueIds[i];
}
- initializeMessageCompression(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_MESSAGE_COMPRESSION),
- entries, values);
-
- initializeFileCompression(
- (IntegerListPreference) findPreference(Constants.Pref.DEFAULT_FILE_COMPRESSION),
- entries, values);
-
- initializeAsciiArmor(
- (CheckBoxPreference) findPreference(Constants.Pref.DEFAULT_ASCII_ARMOR));
-
- initializeWriteVersionHeader(
- (CheckBoxPreference) findPreference(Constants.Pref.WRITE_VERSION_HEADER));
-
initializeUseDefaultYubikeyPin(
(CheckBoxPreference) findPreference(Constants.Pref.USE_DEFAULT_YUBIKEY_PIN));
@@ -344,113 +302,6 @@ public class SettingsActivity extends PreferenceActivity {
});
}
- private static void initializeEncryptionAlgorithm(final IntegerListPreference mEncryptionAlgorithm) {
- int valueIds[] = {PGPEncryptedData.AES_128, PGPEncryptedData.AES_192,
- PGPEncryptedData.AES_256, PGPEncryptedData.BLOWFISH, PGPEncryptedData.TWOFISH,
- PGPEncryptedData.CAST5, PGPEncryptedData.DES, PGPEncryptedData.TRIPLE_DES,
- PGPEncryptedData.IDEA,};
- String entries[] = {"AES-128", "AES-192", "AES-256", "Blowfish", "Twofish", "CAST5",
- "DES", "Triple DES", "IDEA",};
- String values[] = new String[valueIds.length];
- for (int i = 0; i < values.length; ++i) {
- values[i] = "" + valueIds[i];
- }
- mEncryptionAlgorithm.setEntries(entries);
- mEncryptionAlgorithm.setEntryValues(values);
- mEncryptionAlgorithm.setValue("" + sPreferences.getDefaultEncryptionAlgorithm());
- mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry());
- mEncryptionAlgorithm
- .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mEncryptionAlgorithm.setValue(newValue.toString());
- mEncryptionAlgorithm.setSummary(mEncryptionAlgorithm.getEntry());
- sPreferences.setDefaultEncryptionAlgorithm(Integer.parseInt(newValue
- .toString()));
- return false;
- }
- });
- }
-
- private static void initializeHashAlgorithm(final IntegerListPreference mHashAlgorithm) {
- int[] valueIds = new int[]{HashAlgorithmTags.RIPEMD160,
- HashAlgorithmTags.SHA1, HashAlgorithmTags.SHA224, HashAlgorithmTags.SHA256,
- HashAlgorithmTags.SHA384, HashAlgorithmTags.SHA512,};
- String[] entries = new String[]{"RIPEMD-160", "SHA-1", "SHA-224", "SHA-256", "SHA-384",
- "SHA-512",};
- String[] values = new String[valueIds.length];
- for (int i = 0; i < values.length; ++i) {
- values[i] = "" + valueIds[i];
- }
- mHashAlgorithm.setEntries(entries);
- mHashAlgorithm.setEntryValues(values);
- mHashAlgorithm.setValue("" + sPreferences.getDefaultHashAlgorithm());
- mHashAlgorithm.setSummary(mHashAlgorithm.getEntry());
- mHashAlgorithm.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mHashAlgorithm.setValue(newValue.toString());
- mHashAlgorithm.setSummary(mHashAlgorithm.getEntry());
- sPreferences.setDefaultHashAlgorithm(Integer.parseInt(newValue.toString()));
- return false;
- }
- });
- }
-
- private static void initializeMessageCompression(final IntegerListPreference mMessageCompression,
- String[] entries, String[] values) {
- mMessageCompression.setEntries(entries);
- mMessageCompression.setEntryValues(values);
- mMessageCompression.setValue("" + sPreferences.getDefaultMessageCompression());
- mMessageCompression.setSummary(mMessageCompression.getEntry());
- mMessageCompression
- .setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mMessageCompression.setValue(newValue.toString());
- mMessageCompression.setSummary(mMessageCompression.getEntry());
- sPreferences.setDefaultMessageCompression(Integer.parseInt(newValue
- .toString()));
- return false;
- }
- });
- }
-
- private static void initializeFileCompression
- (final IntegerListPreference mFileCompression, String[] entries, String[] values) {
- mFileCompression.setEntries(entries);
- mFileCompression.setEntryValues(values);
- mFileCompression.setValue("" + sPreferences.getDefaultFileCompression());
- mFileCompression.setSummary(mFileCompression.getEntry());
- mFileCompression.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mFileCompression.setValue(newValue.toString());
- mFileCompression.setSummary(mFileCompression.getEntry());
- sPreferences.setDefaultFileCompression(Integer.parseInt(newValue.toString()));
- return false;
- }
- });
- }
-
- private static void initializeAsciiArmor(final CheckBoxPreference mAsciiArmor) {
- mAsciiArmor.setChecked(sPreferences.getDefaultAsciiArmor());
- mAsciiArmor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mAsciiArmor.setChecked((Boolean) newValue);
- sPreferences.setDefaultAsciiArmor((Boolean) newValue);
- return false;
- }
- });
- }
-
- private static void initializeWriteVersionHeader(final CheckBoxPreference mWriteVersionHeader) {
- mWriteVersionHeader.setChecked(sPreferences.getWriteVersionHeader());
- mWriteVersionHeader.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- mWriteVersionHeader.setChecked((Boolean) newValue);
- sPreferences.setWriteVersionHeader((Boolean) newValue);
- return false;
- }
- });
- }
-
private static void initializeSearchKeyserver(final CheckBoxPreference mSearchKeyserver) {
Preferences.CloudSearchPrefs prefs = sPreferences.getCloudSearchPrefs();
mSearchKeyserver.setChecked(prefs.searchKeyserver);
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 be1e0a4c1..c936fb6cc 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -90,6 +90,8 @@ public class ViewKeyActivity extends BaseActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
static final int REQUEST_QR_FINGERPRINT = 1;
+ static final int REQUEST_DELETE= 2;
+ static final int REQUEST_EXPORT= 3;
ExportHelper mExportHelper;
ProviderHelper mProviderHelper;
@@ -278,54 +280,69 @@ public class ViewKeyActivity extends BaseActivity implements
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- try {
- switch (item.getItemId()) {
- case android.R.id.home: {
- Intent homeIntent = new Intent(this, MainActivity.class);
- homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(homeIntent);
- return true;
- }
- case R.id.menu_key_view_export_file: {
- exportToFile(mDataUri, mExportHelper, mProviderHelper);
- return true;
- }
- case R.id.menu_key_view_delete: {
- deleteKey(mDataUri, mExportHelper);
- return true;
- }
- case R.id.menu_key_view_advanced: {
- Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class);
- advancedIntent.setData(mDataUri);
- startActivity(advancedIntent);
- return true;
- }
- case R.id.menu_key_view_refresh: {
- try {
- updateFromKeyserver(mDataUri, mProviderHelper);
- } catch (ProviderHelper.NotFoundException e) {
- Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
- }
- return true;
- }
- case R.id.menu_key_view_edit: {
- editKey(mDataUri);
- return true;
+ switch (item.getItemId()) {
+ case android.R.id.home: {
+ Intent homeIntent = new Intent(this, MainActivity.class);
+ homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(homeIntent);
+ 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();
}
- case R.id.menu_key_view_certify_fingerprint: {
- certifyFingeprint(mDataUri);
- return true;
+ 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();
}
- case R.id.menu_key_view_add_linked_identity: {
- Intent intent = new Intent(this, LinkedIdWizard.class);
- intent.setData(mDataUri);
- startActivity(intent);
- return true;
+ mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
+ startActivityForResult(mIntent,REQUEST_DELETE);
+ return true;
+ }
+ case R.id.menu_key_view_advanced: {
+ Intent advancedIntent = new Intent(this, ViewKeyAdvActivity.class);
+ advancedIntent.setData(mDataUri);
+ startActivity(advancedIntent);
+ return true;
+ }
+ case R.id.menu_key_view_refresh: {
+ try {
+ updateFromKeyserver(mDataUri, mProviderHelper);
+ } catch (ProviderHelper.NotFoundException e) {
+ Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
}
+ return true;
+ }
+ case R.id.menu_key_view_add_linked_identity: {
+ Intent intent = new Intent(this, LinkedIdWizard.class);
+ intent.setData(mDataUri);
+ startActivity(intent);
+ return true;
+ }
+ case R.id.menu_key_view_edit: {
+ editKey(mDataUri);
+ return true;
+ }
+ case R.id.menu_key_view_certify_fingerprint: {
+ certifyFingeprint(mDataUri);
+ return true;
}
- } catch (ProviderHelper.NotFoundException e) {
- Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
- Log.e(Constants.TAG, "Key not found", e);
}
return super.onOptionsItemSelected(item);
}
@@ -417,6 +434,12 @@ public class ViewKeyActivity extends BaseActivity implements
startActivityForResult(intent, 0);
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ //Note:-Done due to the same weird crashes as for commitAllowingStateLoss()
+ //super.onSaveInstanceState(outState);
+ }
+
private void showQrCodeDialog() {
Intent qrCodeIntent = new Intent(this, QrCodeViewActivity.class);
@@ -490,6 +513,19 @@ public class ViewKeyActivity extends BaseActivity implements
return;
}
+ if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){
+ deleteKey(mDataUri, mExportHelper);
+ }
+ if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK){
+ try {
+ exportToFile(mDataUri, mExportHelper, mProviderHelper);
+ } catch (ProviderHelper.NotFoundException e) {
+ Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
+ Log.e(Constants.TAG, "Key not found", e);
+ }
+ }
+
+
if (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/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java
index 094c4d8a9..ee4af8cbe 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
@@ -28,9 +28,6 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.Patterns;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -46,11 +43,10 @@ import android.widget.TextView.OnEditorActionListener;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
-import java.util.regex.Matcher;
-
public class AddUserIdDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "messenger";
private static final String ARG_NAME = "name";
@@ -62,7 +58,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
private Messenger mMessenger;
private AutoCompleteTextView mName;
- private AutoCompleteTextView mEmail;
+ private EmailEditText mEmail;
private EditText mComment;
public static AddUserIdDialogFragment newInstance(Messenger messenger, String predefinedName) {
@@ -99,38 +95,12 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA
alert.setView(view);
mName = (AutoCompleteTextView) view.findViewById(R.id.add_user_id_name);
- mEmail = (AutoCompleteTextView) view.findViewById(R.id.add_user_id_address);
+ mEmail = (EmailEditText) view.findViewById(R.id.add_user_id_address);
mComment = (EditText) view.findViewById(R.id.add_user_id_comment);
mName.setText(predefinedName);
- mEmail.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- @Override
- public void afterTextChanged(Editable editable) {
- String email = editable.toString();
- if (email.length() > 0) {
- Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
- if (emailMatcher.matches()) {
- mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0,
- R.drawable.uid_mail_ok, 0);
- } else {
- mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0,
- R.drawable.uid_mail_bad, 0);
- }
- } else {
- // remove drawable if email is empty
- mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
- }
- }
- });
mEmail.setThreshold(1); // Start working from first character
mEmail.setAdapter(autoCompleteEmailAdapter);
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 a3ffe250b..9e1f21f60 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
@@ -43,6 +43,8 @@ import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.ui.widget.PasswordEditText;
+import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView;
import org.sufficientlysecure.keychain.util.Log;
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
@@ -55,9 +57,10 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
public static final String MESSAGE_NEW_PASSPHRASE = "new_passphrase";
private Messenger mMessenger;
- private EditText mPassphraseEditText;
+ private PasswordEditText mPassphraseEditText;
private EditText mPassphraseAgainEditText;
private CheckBox mNoPassphraseCheckBox;
+ private PasswordStrengthView mPassphraseStrengthView;
/**
* Creates new instance of this dialog fragment
@@ -97,9 +100,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
View view = inflater.inflate(R.layout.passphrase_repeat_dialog, null);
alert.setView(view);
- mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
+ mPassphraseEditText = (PasswordEditText) view.findViewById(R.id.passphrase_passphrase);
mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again);
mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase);
+ mPassphraseStrengthView = (PasswordStrengthView) view.findViewById(R.id.passphrase_repeat_passphrase_strength);
+ mPassphraseEditText.setPasswordStrengthView(mPassphraseStrengthView);
+
if (TextUtils.isEmpty(oldPassphrase)) {
mNoPassphraseCheckBox.setChecked(true);
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
new file mode 100644
index 000000000..697f5a61e
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.util.Patterns;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.ContactHelper;
+
+import java.util.regex.Matcher;
+
+public class EmailEditText extends AutoCompleteTextView {
+ EmailEditText emailEditText;
+
+ public EmailEditText(Context context) {
+ super(context);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public EmailEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ emailEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String email = editable.toString();
+ if (email.length() > 0) {
+ Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
+ if (emailMatcher.matches()) {
+ emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.uid_mail_ok, 0);
+ } else {
+ emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0,
+ R.drawable.uid_mail_bad, 0);
+ }
+ } else {
+ // remove drawable if email is empty
+ emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
+ }
+ }
+ };
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java
new file mode 100644
index 000000000..04c48922b
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView;
+
+/**
+ * Developer: chipset
+ * Package : org.sufficientlysecure.keychain.layouts
+ * Project : open-keychain
+ * Date : 6/3/15
+ */
+public class PasswordEditText extends EditText {
+
+ PasswordEditText passwordEditText;
+ PasswordStrengthView passwordStrengthView;
+
+ public PasswordEditText(Context context) {
+ super(context);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public PasswordEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ passwordEditText = this;
+ this.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ this.addTextChangedListener(textWatcher);
+ }
+
+
+ TextWatcher textWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String passphrase = editable.toString();
+ passwordStrengthView.setPassword(passphrase);
+ }
+ };
+
+// public PasswordStrengthView getPasswordStrengthView() {
+// return passwordStrengthView;
+// }
+
+ public void setPasswordStrengthView(PasswordStrengthView mPasswordStrengthView) {
+ this.passwordStrengthView = mPasswordStrengthView;
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java
new file mode 100644
index 000000000..9e06c4cce
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthBarView.java
@@ -0,0 +1,117 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Matt Allen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.util.AttributeSet;
+
+/**
+ * Created by matt on 04/07/2014.
+ * https://github.com/matt-allen/android-password-strength-indicator
+ */
+public class PasswordStrengthBarView extends PasswordStrengthView {
+
+ public PasswordStrengthBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mMinHeight = 80;
+ mMinWidth = 300;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ generateIndicatorColor();
+ // Default to full width
+ int indWidth = mIndicatorWidth;
+ // If score, leave it as full - can cause it to become
+ // less than full width in this calculation
+ if (mCurrentScore < 20) indWidth = (mIndicatorWidth / 20) * mCurrentScore;
+ // Draw indicator
+ canvas.drawRect(
+ getPaddingLeft(),
+ getPaddingTop(),
+ indWidth,
+ mIndicatorHeight,
+ mIndicatorPaint
+ );
+ // Draw guides if true
+ if (mShowGuides) {
+ // TODO: Try and do this with a loop, for efficiency
+ // Draw bottom guide border
+ float positionY = getHeight() - getPaddingBottom() - getPaddingTop();
+ float notchHeight = (float) (positionY * 0.8);
+ canvas.drawLine(
+ getPaddingLeft(),
+ positionY,
+ getWidth() - getPaddingRight(),
+ positionY,
+ mGuidePaint);
+ // Show left-most notch
+ canvas.drawLine(
+ getPaddingLeft(),
+ positionY,
+ getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show middle-left notch
+ canvas.drawLine(
+ (float) (mIndicatorWidth * 0.25) + getPaddingLeft(),
+ positionY,
+ (float) (mIndicatorWidth * 0.25) + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show the middle notch
+ canvas.drawLine(
+ (float) (mIndicatorWidth * 0.5) + getPaddingLeft(),
+ positionY,
+ (float) (mIndicatorWidth * 0.5) + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show the middle-right notch
+ canvas.drawLine(
+ (float) (mIndicatorWidth * 0.75) + getPaddingLeft(),
+ positionY,
+ (float) (mIndicatorWidth * 0.75) + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ // Show the right-most notch
+ canvas.drawLine(
+ mIndicatorWidth + getPaddingLeft(),
+ positionY,
+ mIndicatorWidth + getPaddingLeft(),
+ notchHeight,
+ mGuidePaint
+ );
+ }
+ }
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java
new file mode 100644
index 000000000..d7270ff58
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java
@@ -0,0 +1,360 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Matt Allen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import org.sufficientlysecure.keychain.R;
+
+/**
+ * Created by Matt Allen
+ * 01/07/14
+ * http://www.mattallensoftware.co.uk
+ * mattallen092@gmail.com
+ * <p/>
+ * https://github.com/matt-allen/android-password-strength-indicator
+ * <p/>
+ * <p>
+ * This View is designed to indicate how secure a user-entered password is in a visual way to
+ * relay to the user if they need to make it stronger. The strength of the password can be set
+ * at creation (or after) which will decide whether their password is strong enough.
+ * </p>
+ * <p/>
+ * <p>
+ * The password strength is decided by an index of 20. The minimum score needed to pass is 10
+ * which means the String has met the conditions imposed by the strength test, but can be improved.
+ * If the password scores 10-19 it is considered weak, and only if it scores 20 will it be
+ * considered strong.
+ * </p>
+ */
+public class PasswordStrengthView extends View {
+
+ protected static final int COLOR_FAIL = Color.parseColor("#e74c3c");
+ protected static final int COLOR_WEAK = Color.parseColor("#e67e22");
+ protected static final int COLOR_STRONG = Color.parseColor("#2ecc71");
+
+ protected int mMinWidth;
+ protected int mMinHeight;
+
+ protected Paint mIndicatorPaint;
+ protected Paint mGuidePaint;
+
+ protected int mIndicatorHeight;
+ protected int mIndicatorWidth;
+ protected int mCurrentScore;
+
+ protected int mColorFail;
+ protected int mColorWeak;
+ protected int mColorStrong;
+
+ protected boolean mShowGuides = true;
+
+ /**
+ * Used to define that the indicator should only be looking
+ * for a weak password. The bare minimum is used here to let
+ * the user continue.
+ */
+ public static final int STRENGTH_WEAK = 0;
+
+ /**
+ * A fairly strict rule for generating a password. It encourages a password that is
+ * less easy to crack.
+ */
+ public static final int STRENGTH_MEDIUM = 1;
+
+ /**
+ * A strong algorithm that encourages very strong passwords that should be fairly long, with
+ * non-alphanumeric, numbers, and upper case.
+ */
+ public static final int STRENGTH_STRONG = 2;
+
+ private int mStrengthRequirement = -1;
+ protected String mPassword;
+
+ public PasswordStrengthView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ TypedArray style = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.PasswordStrengthView,
+ 0, 0);
+
+ try {
+ mStrengthRequirement = style.getInteger(R.styleable.PasswordStrengthView_strength,
+ STRENGTH_MEDIUM);
+ mShowGuides = style.getBoolean(R.styleable.PasswordStrengthView_showGuides, true);
+ mColorFail = style.getColor(R.styleable.PasswordStrengthView_color_fail, COLOR_FAIL);
+ mColorWeak = style.getColor(R.styleable.PasswordStrengthView_color_weak, COLOR_WEAK);
+ mColorStrong = style.getColor(R.styleable.PasswordStrengthView_color_strong,
+ COLOR_STRONG);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ // Create and style the paint used for drawing the guide on the indicator
+ mGuidePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mGuidePaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ mGuidePaint.setColor(Color.BLACK);
+ // Create and style paint for indicator
+ mIndicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mIndicatorPaint.setStyle(Paint.Style.FILL);
+ }
+
+ /**
+ * This view can determine if the password entered by the user is acceptable for
+ * use by your use case. This is based on the strength requirement you have set.
+ *
+ * @return True if requirement has been met
+ */
+ public boolean isStrengthRequirementMet() {
+ return (mCurrentScore >= 10);
+ }
+
+ /**
+ * Change the strength requirement of the password entered by the user. This will also
+ * re-check the password already entered against these new requirements.
+ *
+ * @param requiredStrength Use the public constants of this class to set
+ */
+ public void setStrengthRequirement(int requiredStrength) {
+ if (requiredStrength >= 0 && requiredStrength <= 2) {
+ mStrengthRequirement = requiredStrength;
+ if (mPassword != null && mPassword.length() > 0) {
+ generatePasswordScore();
+ // Update view with new score
+ invalidate();
+ requestLayout();
+ }
+ } else {
+ throw new IndexOutOfBoundsException("Input out of expected range");
+ }
+ }
+
+ /**
+ * Update the password string to check strength of
+ *
+ * @param passwordString String representation of user-input
+ */
+ public void setPassword(String passwordString) {
+ if (passwordString != null && passwordString.length() > 0) {
+ mPassword = passwordString;
+ generatePasswordScore();
+ } else {
+ mPassword = "";
+ mCurrentScore = 0;
+ }
+
+ // Update view with new score
+ invalidate();
+ requestLayout();
+ }
+
+ /**
+ * Private convenience method for adding to the password score
+ *
+ * @param score Amount to be added to current score
+ */
+ protected void addToPasswordScore(int score) {
+ int newScore = mCurrentScore + score;
+
+ // Limit max score
+ if (newScore > 20) {
+ mCurrentScore = 20;
+ } else {
+ mCurrentScore = newScore;
+ }
+ }
+
+ /**
+ * Call this to determine the current strength requirement set on the algorithm
+ *
+ * @return Int representation of the current strength set for the indicator
+ */
+ public int getStrengthRequirement() {
+ return mStrengthRequirement;
+ }
+
+ /**
+ * Generate a score based on the password. The password will already need to be stored
+ * as a class member before running this.
+ */
+ protected void generatePasswordScore() {
+ mCurrentScore = 0;
+ int upperCase = getUppercaseCount(mPassword);
+ int nonAlpha = getNonAlphanumericCount(mPassword);
+ int numbers = getNumberCount(mPassword);
+ switch (mStrengthRequirement) {
+ case STRENGTH_WEAK:
+ addToPasswordScore(mPassword.length() * 2);
+ addToPasswordScore(upperCase * 2);
+ addToPasswordScore(nonAlpha * 2);
+ addToPasswordScore(numbers * 2);
+ break;
+
+ case STRENGTH_MEDIUM:
+ addToPasswordScore(mPassword.length());
+ addToPasswordScore(upperCase);
+ addToPasswordScore(nonAlpha * 2);
+ addToPasswordScore(numbers);
+ break;
+
+ case STRENGTH_STRONG:
+ addToPasswordScore(mPassword.length() / 2);
+ // Cut the score in half to make this a very high requirement
+ addToPasswordScore(upperCase);
+ addToPasswordScore(nonAlpha);
+ addToPasswordScore(numbers);
+ break;
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldW, int oldH) {
+ super.onSizeChanged(w, h, oldW, oldH);
+ int paddingX = getPaddingLeft();
+ int paddingY = getPaddingTop();
+ mIndicatorHeight = h - paddingY;
+ mIndicatorWidth = w - paddingX;
+ }
+
+ /**
+ * The standard parts of the onMeasure needed to create the password strength
+ * indicator. Subclasses should call super.onMeasure, but also need to set
+ * the minimum height and width in the constructor.
+ *
+ * @param widthMeasureSpec The measurement given by the system
+ * @param heightMeasureSpec The measurement given by the system
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Set minimum space for the view to do it's thing
+ int minW = getPaddingLeft() + getPaddingRight() + mMinWidth;
+ int w = resolveSizeAndState(minW, widthMeasureSpec, 1);
+ // And give it enough height so it's visible
+ int minH = mMinHeight + getPaddingBottom() + getPaddingTop();
+ int h = resolveSizeAndState(minH, heightMeasureSpec, 0);
+ // Feed these back into UIKit
+ setMeasuredDimension(w, h);
+ }
+
+ /**
+ * Set the colour of the indicator {@code Paint} to one that is appropriate
+ * for the strength of the password.
+ */
+ protected void generateIndicatorColor() {
+ int color = mColorFail;
+ if (mCurrentScore >= 18) {
+ color = mColorStrong;
+ } else if (mCurrentScore >= 10) {
+ color = mColorWeak;
+ }
+ mIndicatorPaint.setColor(color);
+ }
+
+ /**
+ * Quick method to determine how many of the characters in a given string are upper case
+ *
+ * @param stringToCheck The string to examine
+ * @return Number of upper case characters
+ */
+ protected int getUppercaseCount(String stringToCheck) {
+ int score = 0;
+ int loops = stringToCheck.length() - 1;
+ for (int i = 0; i <= loops; i++) {
+ if (Character.isUpperCase(stringToCheck.charAt(i))) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ /**
+ * A convenience method to determine how many characters in the given String aren't
+ * letters or numbers.
+ *
+ * @param stringToCheck
+ * @return Number of characters that aren't numbers or letters
+ */
+ protected int getNonAlphanumericCount(String stringToCheck) {
+ int score = 0;
+ int loops = stringToCheck.length() - 1;
+ for (int i = 0; i <= loops; i++) {
+ if (!Character.isLetter(stringToCheck.charAt(i)) &&
+ !Character.isDigit(stringToCheck.charAt(i))) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ /**
+ * A convenience method for returning the count of numbers in a given String.
+ *
+ * @param stringToCheck
+ * @return The numbers of digits in the String
+ */
+ protected int getNumberCount(String stringToCheck) {
+ int score = 0;
+ int loops = stringToCheck.length() - 1;
+ for (int i = 0; i <= loops; i++) {
+ if (Character.isDigit(stringToCheck.charAt(i))) {
+ score++;
+ }
+ }
+ return score;
+ }
+
+ /**
+ * Set the guides to show on the view.<br />
+ * On the line style, the guides will show underneath<br />
+ * On the rounded style, the guides will be shown on the outer edges.<br />
+ * The view will be redrawn after the method is called.
+ *
+ * @param showGuides True if you want the guides to be shown
+ */
+ public void setShowGuides(boolean showGuides) {
+ mShowGuides = showGuides;
+ if (mPassword != null && mPassword.length() > 0) {
+ generatePasswordScore();
+ } else {
+ mCurrentScore = 0;
+ }
+
+ invalidate();
+ requestLayout();
+ }
+
+ /**
+ * Determine whether the view is showing the guides for the password score
+ *
+ * @return True if the guides are being shown
+ */
+ public boolean isShowingGuides() {
+ return mShowGuides;
+ }
+}