aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java3
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java57
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java25
-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/HelpActivity.java19
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java20
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java198
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java58
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java9
-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.java61
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java7
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java9
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java12
-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/CustomAlertDialogBuilder.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java5
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java17
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java78
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java11
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java80
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java7
-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/EncryptKeyCompletionView.java2
-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/SignKeySpinner.java7
-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
38 files changed, 1207 insertions, 475 deletions
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 62c38d136..60cc404b6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java
@@ -28,9 +28,11 @@ public class CreateKeyActivity extends BaseActivity {
public static final String EXTRA_NAME = "name";
public static final String EXTRA_EMAIL = "email";
- public static final int FRAG_ACTION_START = 0;
- public static final int FRAG_ACTION_TO_RIGHT = 1;
- public static final int FRAG_ACTION_TO_LEFT = 2;
+ public static enum FragAction {
+ START,
+ TO_RIGHT,
+ TO_LEFT
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -42,7 +44,7 @@ public class CreateKeyActivity extends BaseActivity {
getIntent().getStringExtra(EXTRA_NAME),
getIntent().getStringExtra(EXTRA_EMAIL)
);
- loadFragment(null, frag, FRAG_ACTION_START);
+ loadFragment(null, frag, FragAction.START);
}
@Override
@@ -50,7 +52,7 @@ public class CreateKeyActivity extends BaseActivity {
setContentView(R.layout.create_key_activity);
}
- public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) {
+ 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.
@@ -63,15 +65,15 @@ public class CreateKeyActivity extends BaseActivity {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
switch (action) {
- case FRAG_ACTION_START:
+ case START:
transaction.setCustomAnimations(0, 0);
transaction.replace(R.id.create_key_fragment_container, fragment)
.commitAllowingStateLoss();
break;
- case FRAG_ACTION_TO_LEFT:
+ case TO_LEFT:
getSupportFragmentManager().popBackStackImmediate();
break;
- case FRAG_ACTION_TO_RIGHT:
+ case TO_RIGHT:
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);
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 6e0115342..920488e3e 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java
@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
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.Preferences;
@@ -117,7 +118,7 @@ public class CreateKeyFinalFragment extends Fragment {
mBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- mCreateKeyActivity.loadFragment(null, null, CreateKeyActivity.FRAG_ACTION_TO_LEFT);
+ mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
}
});
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 8aa9fa6db..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;
@@ -32,17 +29,20 @@ import android.widget.AutoCompleteTextView;
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;
@@ -68,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);
@@ -94,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(
@@ -130,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) {
@@ -161,7 +146,7 @@ public class CreateKeyInputFragment extends Fragment {
);
hideKeyboard();
- mCreateKeyActivity.loadFragment(null, frag, CreateKeyActivity.FRAG_ACTION_TO_RIGHT);
+ mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
}
}
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 8723c7255..60103f344 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
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;
public abstract class DecryptFragment extends Fragment {
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
@@ -141,16 +142,16 @@ public abstract class DecryptFragment extends Fragment {
if (signatureResult.isSignatureOnly()) {
mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
- KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_NOT_ENCRYPTED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED);
} else {
mEncryptionText.setText(R.string.decrypt_result_encrypted);
- KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
}
switch (signatureResult.getStatus()) {
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
mSignatureText.setText(R.string.decrypt_result_signature_certified);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_VERIFIED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED);
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(mSignatureKeyId);
@@ -161,7 +162,7 @@ public abstract class DecryptFragment extends Fragment {
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
mSignatureText.setText(R.string.decrypt_result_signature_uncertified);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNVERIFIED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED);
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(mSignatureKeyId);
@@ -172,11 +173,11 @@ public abstract class DecryptFragment extends Fragment {
case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: {
mSignatureText.setText(R.string.decrypt_result_signature_missing_key);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNKNOWN_KEY);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY);
setSignatureLayoutVisibility(View.VISIBLE);
mSignatureAction.setText(R.string.decrypt_result_action_Lookup);
- mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_download, 0);
+ mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_file_download_grey_24dp, 0);
mSignatureLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -190,7 +191,7 @@ public abstract class DecryptFragment extends Fragment {
case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: {
mSignatureText.setText(R.string.decrypt_result_signature_expired_key);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_EXPIRED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED);
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(mSignatureKeyId);
@@ -201,7 +202,7 @@ public abstract class DecryptFragment extends Fragment {
case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: {
mSignatureText.setText(R.string.decrypt_result_signature_revoked_key);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_REVOKED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.REVOKED);
setSignatureLayoutVisibility(View.VISIBLE);
setShowAction(mSignatureKeyId);
@@ -212,7 +213,7 @@ public abstract class DecryptFragment extends Fragment {
case OpenPgpSignatureResult.SIGNATURE_ERROR: {
mSignatureText.setText(R.string.decrypt_result_invalid_signature);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_INVALID);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID);
setSignatureLayoutVisibility(View.GONE);
@@ -224,9 +225,9 @@ public abstract class DecryptFragment extends Fragment {
setSignatureLayoutVisibility(View.GONE);
mSignatureText.setText(R.string.decrypt_result_no_signature);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_NOT_SIGNED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.NOT_SIGNED);
mEncryptionText.setText(R.string.decrypt_result_encrypted);
- KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED);
+ KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
valid = true;
}
@@ -242,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/HelpActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
index 2eb35351e..cd6cdf4d6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/HelpActivity.java
@@ -32,10 +32,9 @@ public class HelpActivity extends BaseActivity {
public static final int TAB_START = 0;
public static final int TAB_FAQ = 1;
- public static final int TAB_WOT = 2;
- public static final int TAB_NFC = 3;
- public static final int TAB_CHANGELOG = 4;
- public static final int TAB_ABOUT = 5;
+ public static final int TAB_TRUST = 2;
+ public static final int TAB_CHANGELOG = 3;
+ public static final int TAB_ABOUT = 4;
ViewPager mViewPager;
private PagerTabStripAdapter mTabsAdapter;
@@ -69,21 +68,11 @@ public class HelpActivity extends BaseActivity {
mTabsAdapter.addTab(HelpHtmlFragment.class, startBundle,
getString(R.string.help_tab_start));
- Bundle faqBundle = new Bundle();
- faqBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_faq);
- mTabsAdapter.addTab(HelpHtmlFragment.class, faqBundle,
- getString(R.string.help_tab_faq));
-
Bundle wotBundle = new Bundle();
- wotBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_wot);
+ wotBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_certification);
mTabsAdapter.addTab(HelpHtmlFragment.class, wotBundle,
getString(R.string.help_tab_wot));
- Bundle nfcBundle = new Bundle();
- nfcBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_nfc_beam);
- mTabsAdapter.addTab(HelpHtmlFragment.class, nfcBundle,
- getString(R.string.help_tab_nfc_beam));
-
Bundle changelogBundle = new Bundle();
changelogBundle.putInt(HelpHtmlFragment.ARG_HTML_FILE, R.raw.help_changelog);
mTabsAdapter.addTab(HelpHtmlFragment.class, changelogBundle,
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 b56da463a..43d893fa6 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java
@@ -70,6 +70,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.FabContainer;
@@ -77,7 +78,6 @@ import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
-import java.util.Date;
import java.util.HashMap;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
@@ -268,7 +268,7 @@ public class KeyListFragment extends LoaderFragment
KeyRings.MASTER_KEY_ID,
KeyRings.USER_ID,
KeyRings.IS_REVOKED,
- KeyRings.EXPIRY,
+ KeyRings.IS_EXPIRED,
KeyRings.VERIFIED,
KeyRings.HAS_ANY_SECRET
};
@@ -276,7 +276,7 @@ public class KeyListFragment extends LoaderFragment
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_USER_ID = 2;
static final int INDEX_IS_REVOKED = 3;
- static final int INDEX_EXPIRY = 4;
+ static final int INDEX_IS_EXPIRED = 4;
static final int INDEX_VERIFIED = 5;
static final int INDEX_HAS_ANY_SECRET = 6;
@@ -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) {
@@ -708,21 +705,20 @@ public class KeyListFragment extends LoaderFragment
long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
boolean isSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0;
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
- boolean isExpired = !cursor.isNull(INDEX_EXPIRY)
- && new Date(cursor.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;
boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0;
h.mMasterKeyId = masterKeyId;
// Note: order is important!
if (isRevoked) {
- KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, State.REVOKED, R.color.bg_gray);
h.mStatus.setVisibility(View.VISIBLE);
h.mSlinger.setVisibility(View.GONE);
h.mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
h.mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray));
} else if (isExpired) {
- KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, null, State.EXPIRED, R.color.bg_gray);
h.mStatus.setVisibility(View.VISIBLE);
h.mSlinger.setVisibility(View.GONE);
h.mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
@@ -735,10 +731,10 @@ public class KeyListFragment extends LoaderFragment
} else {
// this is a public key - show if it's verified
if (isVerified) {
- KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_VERIFIED);
+ KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, State.VERIFIED);
h.mStatus.setVisibility(View.VISIBLE);
} else {
- KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_UNVERIFIED);
+ KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, State.UNVERIFIED);
h.mStatus.setVisibility(View.VISIBLE);
}
h.mSlinger.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
index b655a7e55..138f2f4e7 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java
@@ -22,9 +22,13 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
+import android.os.Parcel;
import android.support.v4.app.ListFragment;
import android.util.TypedValue;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -33,11 +37,19 @@ import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogLevel;
import org.sufficientlysecure.keychain.operations.results.OperationResult.SubLogEntryParcel;
+import org.sufficientlysecure.keychain.util.FileHelper;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.util.Iterator;
public class LogDisplayFragment extends ListFragment implements OnItemClickListener {
@@ -46,6 +58,12 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
OperationResult mResult;
public static final String EXTRA_RESULT = "log";
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setHasOptionsMenu(true);
+ }
@Override
public void onActivityCreated(Bundle savedInstanceState) {
@@ -70,6 +88,183 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
getListView().setFastScrollEnabled(true);
getListView().setDividerHeight(0);
+
+ }
+
+ @Override
+ public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+ inflater.inflate(R.menu.log_display, menu);
+
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_log_display_export_log:
+ exportLog();
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void exportLog() {
+
+ showExportLogDialog(new File(Constants.Path.APP_DIR, "export.log"));
+ }
+
+ private void writeToLogFile(final OperationResult.OperationLog operationLog, final File f) {
+ OperationResult.OperationLog currLog = new OperationResult.OperationLog();
+ currLog.add(OperationResult.LogType.MSG_EXPORT_LOG, 0);
+
+ boolean error = false;
+
+ PrintWriter pw = null;
+ try {
+ pw = new PrintWriter(f);
+ pw.print(getPrintableOperationLog(operationLog, ""));
+ if (pw.checkError()) {//IOException
+ Log.e(Constants.TAG, "Log Export I/O Exception " + f.getAbsolutePath());
+ currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_ERROR_WRITING, 1);
+ error = true;
+ }
+ } catch (FileNotFoundException e) {
+ Log.e(Constants.TAG, "File not found for exporting log " + f.getAbsolutePath());
+ currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_ERROR_FOPEN, 1);
+ error = true;
+ }
+ if (pw != null) {
+ pw.close();
+ if (!error && pw.checkError()) {//check if it is only pw.close() which generated error
+ currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_ERROR_WRITING, 1);
+ error = true;
+ }
+ }
+
+ if (!error) currLog.add(OperationResult.LogType.MSG_EXPORT_LOG_EXPORT_SUCCESS, 1);
+
+ int opResultCode = error ? OperationResult.RESULT_ERROR : OperationResult.RESULT_OK;
+ OperationResult opResult = new LogExportResult(opResultCode, currLog);
+ opResult.createNotify(getActivity()).show();
+ }
+
+ /**
+ * returns an indented String of an entire OperationLog
+ *
+ * @param opLog log to be converted to indented, printable format
+ * @param basePadding padding to add at the start of all log entries, made for use with SubLogs
+ * @return printable, indented version of passed operationLog
+ */
+ private String getPrintableOperationLog(OperationResult.OperationLog opLog, String basePadding) {
+ String log = "";
+ for (Iterator<LogEntryParcel> logIterator = opLog.iterator(); logIterator.hasNext(); ) {
+ log += getPrintableLogEntry(logIterator.next(), basePadding) + "\n";
+ }
+ log = log.substring(0, log.length() - 1);//gets rid of extra new line
+ return log;
+ }
+
+ /**
+ * returns an indented String of a LogEntryParcel including any sub-logs it may contain
+ *
+ * @param entryParcel log entryParcel whose String representation is to be obtained
+ * @return indented version of passed log entryParcel in a readable format
+ */
+ private String getPrintableLogEntry(OperationResult.LogEntryParcel entryParcel,
+ String basePadding) {
+
+ final String indent = " ";//4 spaces = 1 Indent level
+
+ String padding = basePadding;
+ for (int i = 0; i < entryParcel.mIndent; i++) {
+ padding += indent;
+ }
+ String logText = padding;
+
+ switch (entryParcel.mType.mLevel) {
+ case DEBUG:
+ logText += "[DEBUG]";
+ break;
+ case INFO:
+ logText += "[INFO]";
+ break;
+ case WARN:
+ logText += "[WARN]";
+ break;
+ case ERROR:
+ logText += "[ERROR]";
+ break;
+ case START:
+ logText += "[START]";
+ break;
+ case OK:
+ logText += "[OK]";
+ break;
+ case CANCELLED:
+ logText += "[CANCELLED]";
+ break;
+ }
+
+ // special case: first parameter may be a quantity
+ if (entryParcel.mParameters != null && entryParcel.mParameters.length > 0
+ && entryParcel.mParameters[0] instanceof Integer) {
+ logText += getResources().getQuantityString(entryParcel.mType.getMsgId(),
+ (Integer) entryParcel.mParameters[0],
+ entryParcel.mParameters);
+ } else {
+ logText += getResources().getString(entryParcel.mType.getMsgId(),
+ entryParcel.mParameters);
+ }
+
+ if (entryParcel instanceof SubLogEntryParcel) {
+ OperationResult subResult = ((SubLogEntryParcel) entryParcel).getSubResult();
+ LogEntryParcel subEntry = subResult.getLog().getLast();
+ if (subEntry != null) {
+ //the first line of log of subResult is same as entryParcel, so replace logText
+ logText = getPrintableOperationLog(subResult.getLog(), padding);
+ }
+ }
+
+ return logText;
+ }
+
+ private void showExportLogDialog(final File exportFile) {
+
+ String title = this.getString(R.string.title_export_log);
+
+ String message = this.getString(R.string.specify_file_to_export_log_to);
+
+ FileHelper.saveFile(new FileHelper.FileDialogCallback() {
+ @Override
+ public void onFileSelected(File file, boolean checked) {
+ writeToLogFile(mResult.getLog(), file);
+ }
+ }, this.getActivity().getSupportFragmentManager(), title, message, exportFile, null);
+ }
+
+ private static class LogExportResult extends OperationResult {
+
+ public static Creator<LogExportResult> CREATOR = new Creator<LogExportResult>() {
+ public LogExportResult createFromParcel(final Parcel source) {
+ return new LogExportResult(source);
+ }
+
+ public LogExportResult[] newArray(final int size) {
+ return new LogExportResult[size];
+ }
+ };
+
+ public LogExportResult(int result, OperationLog log) {
+ super(result, log);
+ }
+
+ /**
+ * trivial but necessary to implement the Parcelable protocol.
+ */
+ public LogExportResult(Parcel source) {
+ super(source);
+ }
}
@Override
@@ -109,7 +304,7 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
mSecondImg = secondImg;
}
}
-
+ // Check if convertView.setPadding is redundant
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LogEntryParcel entry = getItem(position);
@@ -132,7 +327,6 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
if (entry instanceof SubLogEntryParcel) {
ih.mSub.setVisibility(View.VISIBLE);
convertView.setClickable(false);
-
convertView.setPadding((entry.mIndent) * dipFactor, 0, 0, 0);
OperationResult result = ((SubLogEntryParcel) entry).getSubResult();
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 d5ca08936..bb669f6b8 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/PassphraseDialogActivity.java
@@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey;
import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
+import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing;
@@ -149,6 +150,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
public static class PassphraseDialogFragment extends DialogFragment implements TextView.OnEditorActionListener {
private EditText mPassphraseEditText;
+ private TextView mPassphraseText;
private View mInput, mProgress;
private CanonicalizedSecretKeyRing mSecretRing = null;
@@ -167,7 +169,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
// if the dialog is displayed from the application class, design is missing
// hack to get holo design (which is not automatically applied due to activity's Theme.NoDisplay
ContextThemeWrapper theme = new ContextThemeWrapper(activity,
- R.style.Theme_AppCompat_Light);
+ R.style.Theme_AppCompat_Light_Dialog);
mSubKeyId = getArguments().getLong(EXTRA_SUBKEY_ID);
mServiceIntent = getArguments().getParcelable(EXTRA_DATA);
@@ -176,13 +178,30 @@ public class PassphraseDialogActivity extends FragmentActivity {
alert.setTitle(R.string.title_unlock);
+ LayoutInflater inflater = LayoutInflater.from(theme);
+ View view = inflater.inflate(R.layout.passphrase_dialog, null);
+ alert.setView(view);
+
+ mPassphraseText = (TextView) view.findViewById(R.id.passphrase_text);
+ mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
+ mInput = view.findViewById(R.id.input);
+ mProgress = view.findViewById(R.id.progress);
+
+ alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ });
+
String userId;
CanonicalizedSecretKey.SecretKeyType keyType = CanonicalizedSecretKey.SecretKeyType.PASSPHRASE;
+ String message;
if (mSubKeyId == Constants.key.symmetric || mSubKeyId == Constants.key.none) {
- alert.setMessage(R.string.passphrase_for_symmetric_encryption);
+ message = getString(R.string.passphrase_for_symmetric_encryption);
} else {
- String message;
try {
ProviderHelper helper = new ProviderHelper(activity);
mSecretRing = helper.getCanonicalizedSecretKeyRing(
@@ -191,7 +210,13 @@ public class PassphraseDialogActivity extends FragmentActivity {
// above can't be statically verified to have been set in all cases because
// the catch clause doesn't return.
try {
- userId = mSecretRing.getPrimaryUserIdWithFallback();
+ String mainUserId = mSecretRing.getPrimaryUserIdWithFallback();
+ String[] mainUserIdSplit = KeyRing.splitUserId(mainUserId);
+ if (mainUserIdSplit[0] != null) {
+ userId = mainUserIdSplit[0];
+ } else {
+ userId = getString(R.string.user_id_no_name);
+ }
} catch (PgpKeyNotFoundException e) {
userId = null;
}
@@ -228,33 +253,16 @@ public class PassphraseDialogActivity extends FragmentActivity {
alert.setCancelable(false);
return alert.create();
}
-
- alert.setMessage(message);
}
- LayoutInflater inflater = LayoutInflater.from(theme);
- View view = inflater.inflate(R.layout.passphrase_dialog, null);
- alert.setView(view);
-
- mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
- mInput = view.findViewById(R.id.input);
- mProgress = view.findViewById(R.id.progress);
-
- alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- dialog.cancel();
- }
- });
-
+ mPassphraseText.setText(message);
if (keyType == CanonicalizedSecretKey.SecretKeyType.PATTERN) {
// start pattern dialog and show progress circle here...
// Intent patternActivity = new Intent(getActivity(), LockPatternActivity.class);
// patternActivity.putExtra(LockPatternActivity.EXTRA_PATTERN, "123");
// startActivityForResult(patternActivity, REQUEST_CODE_ENTER_PATTERN);
- mInput.setVisibility(View.GONE);
+ mInput.setVisibility(View.INVISIBLE);
mProgress.setVisibility(View.VISIBLE);
} else {
// Hack to open keyboard.
@@ -322,7 +330,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
return;
}
- mInput.setVisibility(View.GONE);
+ mInput.setVisibility(View.INVISIBLE);
mProgress.setVisibility(View.VISIBLE);
positive.setEnabled(false);
@@ -364,7 +372,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
mPassphraseEditText.setText("");
mPassphraseEditText.setError(getString(R.string.wrong_passphrase));
mInput.setVisibility(View.VISIBLE);
- mProgress.setVisibility(View.GONE);
+ mProgress.setVisibility(View.INVISIBLE);
positive.setEnabled(true);
return;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
index afec3bf06..65d7eca37 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SelectPublicKeyFragment.java
@@ -46,6 +46,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.ui.adapter.SelectKeyCursorAdapter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import java.util.Vector;
@@ -136,7 +137,7 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
mSearchView.setId(SEARCH_ID);
mSearchView.setHint(R.string.menu_search);
mSearchView.setCompoundDrawablesWithIntrinsicBounds(
- getResources().getDrawable(R.drawable.ic_action_search), null, null, null);
+ getResources().getDrawable(R.drawable.ic_search_grey_24dp), null, null, null);
linearLayout.addView(mSearchView, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
@@ -376,15 +377,15 @@ public class SelectPublicKeyFragment extends ListFragmentWorkaround implements T
// Check if key is viable for our purposes
if (cursor.getInt(mIndexHasEncrypt) == 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, KeyFormattingUtils.STATE_UNAVAILABLE);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, State.UNAVAILABLE);
enabled = false;
} else if (cursor.getInt(mIndexIsVerified) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, KeyFormattingUtils.STATE_VERIFIED);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, State.VERIFIED);
enabled = true;
} else {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, KeyFormattingUtils.STATE_UNVERIFIED);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, State.UNVERIFIED);
enabled = true;
}
}
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 5a5e1ec36..c94b29bac 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -74,16 +74,15 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
-import org.sufficientlysecure.keychain.ui.widget.AspectRatioImageView;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
-import java.util.Date;
import java.util.HashMap;
public class ViewKeyActivity extends BaseActivity implements
@@ -107,7 +106,7 @@ public class ViewKeyActivity extends BaseActivity implements
private ImageButton mActionEncryptText;
private ImageButton mActionNfc;
private FloatingActionButton mFab;
- private AspectRatioImageView mPhoto;
+ private ImageView mPhoto;
private ImageView mQrCode;
private CardView mQrCodeLayout;
@@ -123,6 +122,9 @@ public class ViewKeyActivity extends BaseActivity implements
private boolean mIsSecret = false;
private boolean mHasEncrypt = false;
private boolean mIsVerified = false;
+ private boolean mIsRevoked = false;
+ private boolean mIsExpired = false;
+
private MenuItem mRefreshItem;
private boolean mIsRefreshing;
private Animation mRotate, mRotateSpin;
@@ -149,7 +151,7 @@ public class ViewKeyActivity extends BaseActivity implements
mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text);
mActionNfc = (ImageButton) findViewById(R.id.view_key_action_nfc);
mFab = (FloatingActionButton) findViewById(R.id.fab);
- mPhoto = (AspectRatioImageView) findViewById(R.id.view_key_photo);
+ mPhoto = (ImageView) findViewById(R.id.view_key_photo);
mQrCode = (ImageView) findViewById(R.id.view_key_qr_code);
mQrCodeLayout = (CardView) findViewById(R.id.view_key_qr_code_layout);
@@ -175,7 +177,7 @@ public class ViewKeyActivity extends BaseActivity implements
}
});
- mRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
+ mRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
mRotate.setRepeatCount(Animation.INFINITE);
mRotate.setAnimationListener(new Animation.AnimationListener() {
@Override
@@ -364,7 +366,7 @@ public class ViewKeyActivity extends BaseActivity implements
MenuItem editKey = menu.findItem(R.id.menu_key_view_edit);
editKey.setVisible(mIsSecret);
MenuItem certifyFingerprint = menu.findItem(R.id.menu_key_view_certify_fingerprint);
- certifyFingerprint.setVisible(!mIsSecret && !mIsVerified);
+ certifyFingerprint.setVisible(!mIsSecret && !mIsVerified && !mIsExpired && !mIsRevoked);
return true;
}
@@ -415,12 +417,12 @@ 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);
}
- private void startCertifyIntent (Intent intent) {
+ private void startCertifyIntent(Intent intent) {
// Message is received after signing is done in KeychainIntentService
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this) {
public void handleMessage(Message message) {
@@ -786,7 +788,7 @@ public class ViewKeyActivity extends BaseActivity implements
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
KeychainContract.KeyRings.IS_REVOKED,
- KeychainContract.KeyRings.EXPIRY,
+ KeychainContract.KeyRings.IS_EXPIRED,
KeychainContract.KeyRings.VERIFIED,
KeychainContract.KeyRings.HAS_ANY_SECRET,
KeychainContract.KeyRings.FINGERPRINT,
@@ -796,7 +798,7 @@ public class ViewKeyActivity extends BaseActivity implements
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_USER_ID = 2;
static final int INDEX_IS_REVOKED = 3;
- static final int INDEX_EXPIRY = 4;
+ static final int INDEX_IS_EXPIRED = 4;
static final int INDEX_VERIFIED = 5;
static final int INDEX_HAS_ANY_SECRET = 6;
static final int INDEX_FINGERPRINT = 7;
@@ -845,9 +847,8 @@ public class ViewKeyActivity extends BaseActivity implements
mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
- boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
- boolean isExpired = !data.isNull(INDEX_EXPIRY)
- && new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
+ mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
// if the refresh animation isn't playing
@@ -857,10 +858,10 @@ public class ViewKeyActivity extends BaseActivity implements
// this is done at the end of the animation otherwise
}
- AsyncTask<String, Void, Bitmap> photoTask =
- new AsyncTask<String, Void, Bitmap>() {
- protected Bitmap doInBackground(String... fingerprint) {
- return ContactHelper.photoFromFingerprint(getContentResolver(), fingerprint[0]);
+ AsyncTask<Long, Void, Bitmap> photoTask =
+ new AsyncTask<Long, Void, Bitmap>() {
+ protected Bitmap doInBackground(Long... mMasterKeyId) {
+ return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(), mMasterKeyId[0], true);
}
protected void onPostExecute(Bitmap photo) {
@@ -871,11 +872,11 @@ public class ViewKeyActivity extends BaseActivity implements
// Note: order is important
int color;
- if (isRevoked) {
+ if (mIsRevoked) {
mStatusText.setText(R.string.view_key_revoked);
mStatusImage.setVisibility(View.VISIBLE);
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
- KeyFormattingUtils.STATE_REVOKED, R.color.icons, true);
+ State.REVOKED, R.color.icons, true);
color = getResources().getColor(R.color.android_red_light);
mActionEncryptFile.setVisibility(View.GONE);
@@ -883,7 +884,7 @@ public class ViewKeyActivity extends BaseActivity implements
mActionNfc.setVisibility(View.GONE);
mFab.setVisibility(View.GONE);
mQrCodeLayout.setVisibility(View.GONE);
- } else if (isExpired) {
+ } else if (mIsExpired) {
if (mIsSecret) {
mStatusText.setText(R.string.view_key_expired_secret);
} else {
@@ -891,7 +892,7 @@ public class ViewKeyActivity extends BaseActivity implements
}
mStatusImage.setVisibility(View.VISIBLE);
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
- KeyFormattingUtils.STATE_EXPIRED, R.color.icons, true);
+ State.EXPIRED, R.color.icons, true);
color = getResources().getColor(R.color.android_red_light);
mActionEncryptFile.setVisibility(View.GONE);
@@ -904,10 +905,10 @@ public class ViewKeyActivity extends BaseActivity implements
mStatusImage.setVisibility(View.GONE);
color = getResources().getColor(R.color.primary);
// reload qr code only if the fingerprint changed
- if ( !mFingerprint.equals(oldFingerprint)) {
+ if (!mFingerprint.equals(oldFingerprint)) {
loadQrCode(mFingerprint);
}
- photoTask.execute(mFingerprint);
+ photoTask.execute(mMasterKeyId);
mQrCodeLayout.setVisibility(View.VISIBLE);
// and place leftOf qr code
@@ -951,16 +952,16 @@ public class ViewKeyActivity extends BaseActivity implements
mStatusText.setText(R.string.view_key_verified);
mStatusImage.setVisibility(View.VISIBLE);
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
- KeyFormattingUtils.STATE_VERIFIED, R.color.icons, true);
+ State.VERIFIED, R.color.icons, true);
color = getResources().getColor(R.color.primary);
- photoTask.execute(mFingerprint);
+ photoTask.execute(mMasterKeyId);
mFab.setVisibility(View.GONE);
} else {
mStatusText.setText(R.string.view_key_unverified);
mStatusImage.setVisibility(View.VISIBLE);
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
- KeyFormattingUtils.STATE_UNVERIFIED, R.color.icons, true);
+ State.UNVERIFIED, R.color.icons, true);
color = getResources().getColor(R.color.android_orange_light);
mFab.setVisibility(View.VISIBLE);
@@ -968,27 +969,21 @@ public class ViewKeyActivity extends BaseActivity implements
}
if (mPreviousColor == 0 || mPreviousColor == color) {
- mToolbar.setBackgroundColor(color);
mStatusBar.setBackgroundColor(color);
mBigToolbar.setBackgroundColor(color);
mPreviousColor = color;
} else {
ObjectAnimator colorFade1 =
- ObjectAnimator.ofObject(mToolbar, "backgroundColor",
- new ArgbEvaluator(), mPreviousColor, color);
- ObjectAnimator colorFade2 =
ObjectAnimator.ofObject(mStatusBar, "backgroundColor",
new ArgbEvaluator(), mPreviousColor, color);
- ObjectAnimator colorFade3 =
+ ObjectAnimator colorFade2 =
ObjectAnimator.ofObject(mBigToolbar, "backgroundColor",
new ArgbEvaluator(), mPreviousColor, color);
colorFade1.setDuration(1200);
colorFade2.setDuration(1200);
- colorFade3.setDuration(1200);
colorFade1.start();
colorFade2.start();
- colorFade3.start();
mPreviousColor = color;
}
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 9d79b377c..9390e8a69 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java
@@ -43,8 +43,6 @@ import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.ExportHelper;
import org.sufficientlysecure.keychain.util.Log;
-import java.util.Date;
-
public class ViewKeyAdvActivity extends BaseActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
@@ -159,7 +157,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
KeychainContract.KeyRings.IS_REVOKED,
- KeychainContract.KeyRings.EXPIRY,
+ KeychainContract.KeyRings.IS_EXPIRED,
KeychainContract.KeyRings.VERIFIED,
KeychainContract.KeyRings.HAS_ANY_SECRET
};
@@ -167,7 +165,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_USER_ID = 2;
static final int INDEX_IS_REVOKED = 3;
- static final int INDEX_EXPIRY = 4;
+ static final int INDEX_IS_EXPIRED = 4;
static final int INDEX_VERIFIED = 5;
static final int INDEX_HAS_ANY_SECRET = 6;
@@ -212,8 +210,7 @@ public class ViewKeyAdvActivity extends BaseActivity implements
boolean isSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
- boolean isExpired = !data.isNull(INDEX_EXPIRY)
- && new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
+ boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
// Note: order is important
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 8d0a2dd1d..95a6faea9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java
@@ -260,7 +260,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
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.EXPIRY,
+ KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.IS_EXPIRED,
};
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
@@ -270,7 +270,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
static final int INDEX_UNIFIED_ALGORITHM = 5;
static final int INDEX_UNIFIED_KEY_SIZE = 6;
static final int INDEX_UNIFIED_CREATION = 7;
- static final int INDEX_UNIFIED_EXPIRY = 8;
+ static final int INDEX_UNIFIED_ID_EXPIRED = 8;
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
setContentShown(false);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
index c4e6639a8..7bfebaf62 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvUserIdsFragment.java
@@ -114,12 +114,12 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
static final String[] UNIFIED_PROJECTION = new String[]{
KeyRings._ID, KeyRings.MASTER_KEY_ID,
- KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.EXPIRY, KeyRings.HAS_ENCRYPT
+ KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.IS_EXPIRED, KeyRings.HAS_ENCRYPT
};
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
static final int INDEX_UNIFIED_IS_REVOKED = 3;
- static final int INDEX_UNIFIED_EXPIRY = 4;
+ static final int INDEX_UNIFIED_IS_EXPIRED = 4;
static final int INDEX_UNIFIED_HAS_ENCRYPT = 5;
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
index 32630b459..628970b27 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -121,7 +121,7 @@ public class ViewKeyFragment extends LoaderFragment implements
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
KeychainContract.KeyRings.IS_REVOKED,
- KeychainContract.KeyRings.EXPIRY,
+ KeychainContract.KeyRings.IS_EXPIRED,
KeychainContract.KeyRings.VERIFIED,
KeychainContract.KeyRings.HAS_ANY_SECRET,
KeychainContract.KeyRings.FINGERPRINT,
@@ -131,7 +131,7 @@ public class ViewKeyFragment extends LoaderFragment implements
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_USER_ID = 2;
static final int INDEX_IS_REVOKED = 3;
- static final int INDEX_EXPIRY = 4;
+ static final int INDEX_IS_EXPIRED = 4;
static final int INDEX_VERIFIED = 5;
static final int INDEX_HAS_ANY_SECRET = 6;
static final int INDEX_FINGERPRINT = 7;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
index 25edc7a02..d22f01a48 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java
@@ -115,12 +115,12 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
}
static final String[] TRUST_PROJECTION = new String[]{
- KeyRings._ID, KeyRings.FINGERPRINT, KeyRings.IS_REVOKED, KeyRings.EXPIRY,
+ KeyRings._ID, KeyRings.FINGERPRINT, KeyRings.IS_REVOKED, KeyRings.IS_EXPIRED,
KeyRings.HAS_ANY_SECRET, KeyRings.VERIFIED
};
static final int INDEX_TRUST_FINGERPRINT = 1;
static final int INDEX_TRUST_IS_REVOKED = 2;
- static final int INDEX_TRUST_EXPIRY = 3;
+ static final int INDEX_TRUST_IS_EXPIRED = 3;
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 4;
static final int INDEX_VERIFIED = 5;
@@ -169,8 +169,7 @@ public class ViewKeyTrustFragment extends LoaderFragment implements
nothingSpecial = false;
} else {
- Date expiryDate = new Date(data.getLong(INDEX_TRUST_EXPIRY) * 1000);
- if (!data.isNull(INDEX_TRUST_EXPIRY) && expiryDate.before(new Date())) {
+ if (data.getInt(INDEX_TRUST_IS_EXPIRED) != 0) {
// if expired, don’t trust it!
message.append(getString(R.string.key_trust_expired)).
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 6ba9e26ad..429feb075 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
@@ -37,6 +37,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import java.util.ArrayList;
import java.util.HashMap;
@@ -175,9 +176,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
}
if (entry.isRevoked()) {
- KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.REVOKED, R.color.bg_gray);
} else if (entry.isExpired()) {
- KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.EXPIRED, R.color.bg_gray);
}
if (entry.isRevoked() || entry.isExpired()) {
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 a836b35df..226fda20b 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
@@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
/**
@@ -133,11 +134,11 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
boolean enabled;
if (cursor.getInt(mIndexIsRevoked) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.REVOKED, R.color.bg_gray);
enabled = false;
} else if (cursor.getInt(mIndexIsExpiry) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.EXPIRED, R.color.bg_gray);
enabled = false;
} else {
h.statusIcon.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index ff5fbb49a..096dea51f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -272,12 +272,12 @@ public class SubkeysAdapter extends CursorAdapter {
PorterDuff.Mode.SRC_IN);
if (isRevoked) {
- vStatus.setImageResource(R.drawable.status_signature_revoked_cutout_24px);
+ vStatus.setImageResource(R.drawable.status_signature_revoked_cutout_24dp);
vStatus.setColorFilter(
mContext.getResources().getColor(R.color.bg_gray),
PorterDuff.Mode.SRC_IN);
} else if (isExpired) {
- vStatus.setImageResource(R.drawable.status_signature_expired_cutout_24px);
+ vStatus.setImageResource(R.drawable.status_signature_expired_cutout_24dp);
vStatus.setColorFilter(
mContext.getResources().getColor(R.color.bg_gray),
PorterDuff.Mode.SRC_IN);
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 6a4f61f4b..3486f1516 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
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
public class UserIdsAdapter extends UserAttributesAdapter {
protected LayoutInflater mInflater;
@@ -127,7 +128,7 @@ public class UserIdsAdapter extends UserAttributesAdapter {
if (isRevoked) {
// set revocation icon (can this even be primary?)
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.REVOKED, R.color.bg_gray);
// disable revoked user ids
vName.setEnabled(false);
@@ -149,13 +150,13 @@ public class UserIdsAdapter extends UserAttributesAdapter {
int isVerified = cursor.getInt(INDEX_VERIFIED);
switch (isVerified) {
case Certs.VERIFIED_SECRET:
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.VERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
break;
case Certs.VERIFIED_SELF:
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.UNVERIFIED, KeyFormattingUtils.DEFAULT_COLOR);
break;
default:
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, KeyFormattingUtils.STATE_INVALID, KeyFormattingUtils.DEFAULT_COLOR);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.INVALID, KeyFormattingUtils.DEFAULT_COLOR);
break;
}
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
index d5376cbdc..0b1d39fc1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddSubkeyDialogFragment.java
@@ -137,12 +137,10 @@ public class AddSubkeyDialogFragment extends DialogFragment {
}
});
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
- // date picker works based on default time zone
- Calendar minDateCal = Calendar.getInstance(TimeZone.getDefault());
- minDateCal.add(Calendar.DAY_OF_YEAR, 1); // at least one day after creation (today)
- mExpiryDatePicker.setMinDate(minDateCal.getTime().getTime());
- }
+ // date picker works based on default time zone
+ Calendar minDateCal = Calendar.getInstance(TimeZone.getDefault());
+ minDateCal.add(Calendar.DAY_OF_YEAR, 1); // at least one day after creation (today)
+ mExpiryDatePicker.setMinDate(minDateCal.getTime().getTime());
{
ArrayList<Choice<Algorithm>> choices = new ArrayList<>();
@@ -283,7 +281,7 @@ public class AddSubkeyDialogFragment extends DialogFragment {
// For EC keys, add a curve
if (algorithm == Algorithm.ECDH || algorithm == Algorithm.ECDSA) {
curve = ((Choice<Curve>) mCurveSpinner.getSelectedItem()).getId();
- // Otherwise, get a keysize
+ // Otherwise, get a keysize
} else {
keySize = getProperKeyLength(algorithm, getSelectedKeyLength());
}
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/CustomAlertDialogBuilder.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
index d405b1dda..794af5b15 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/CustomAlertDialogBuilder.java
@@ -1,3 +1,20 @@
+/*
+ * 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.dialog;
import android.app.AlertDialog;
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
index 879e3f6da..07462b4ff 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteFileDialogFragment.java
@@ -62,12 +62,9 @@ public class DeleteFileDialogFragment extends DialogFragment {
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
-
- alert.setIcon(R.drawable.ic_dialog_alert_holo_light);
- alert.setTitle(R.string.warning);
alert.setMessage(this.getString(R.string.file_delete_confirmation, deleteFilename));
- alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ alert.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
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 802f0c11b..32789d53b 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
@@ -83,8 +83,6 @@ public class DeleteKeyDialogFragment extends DialogFragment {
mMainMessage = (TextView) mInflateView.findViewById(R.id.mainMessage);
- builder.setTitle(R.string.warning);
-
final boolean hasSecret;
// If only a single key has been selected
@@ -110,12 +108,14 @@ public class DeleteKeyDialogFragment extends DialogFragment {
}
hasSecret = ((Long) data.get(KeyRings.HAS_ANY_SECRET)) == 1;
- // Set message depending on which key it is.
- mMainMessage.setText(getString(
- hasSecret ? R.string.secret_key_deletion_confirmation
- : R.string.public_key_deletetion_confirmation,
- name
- ));
+ if (hasSecret) {
+ // show title only for secret key deletions,
+ // see http://www.google.com/design/spec/components/dialogs.html#dialogs-behavior
+ builder.setTitle(getString(R.string.title_delete_secret_key, name));
+ mMainMessage.setText(getString(R.string.secret_key_deletion_confirmation, name));
+ } else {
+ mMainMessage.setText(getString(R.string.public_key_deletetion_confirmation, name));
+ }
} catch (ProviderHelper.NotFoundException e) {
dismiss();
return null;
@@ -125,7 +125,6 @@ public class DeleteKeyDialogFragment extends DialogFragment {
hasSecret = false;
}
- builder.setIcon(R.drawable.ic_dialog_alert_holo_light);
builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java
index fc618c9eb..37e05a61d 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditSubkeyExpiryDialogFragment.java
@@ -25,11 +25,14 @@ import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.DialogFragment;
+import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -97,61 +100,64 @@ public class EditSubkeyExpiryDialogFragment extends DialogFragment {
final CheckBox noExpiry = (CheckBox) view.findViewById(R.id.edit_subkey_expiry_no_expiry);
final DatePicker datePicker = (DatePicker) view.findViewById(R.id.edit_subkey_expiry_date_picker);
+ final TextView currentExpiry = (TextView) view.findViewById(R.id.edit_subkey_expiry_current_expiry);
+ final LinearLayout expiryLayout = (LinearLayout) view.findViewById(R.id.edit_subkey_expiry_layout);
noExpiry.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
- datePicker.setVisibility(View.GONE);
+ expiryLayout.setVisibility(View.GONE);
} else {
- datePicker.setVisibility(View.VISIBLE);
+ expiryLayout.setVisibility(View.VISIBLE);
}
}
});
- // init date picker with default selected date
if (expiry == 0L) {
noExpiry.setChecked(true);
- datePicker.setVisibility(View.GONE);
-
- Calendar todayCal = Calendar.getInstance(TimeZone.getDefault());
- if (creationCal.after(todayCal)) {
- // Note: This is just for the rare cases where creation is _after_ today
-
- // set it to creation date +1 day (don't set it to creationCal, it would break crash
- // datePicker.setMinDate() execution with IllegalArgumentException
- Calendar creationCalPlusOne = (Calendar) creationCal.clone();
- creationCalPlusOne.add(Calendar.DAY_OF_YEAR, 1);
- datePicker.init(
- creationCalPlusOne.get(Calendar.YEAR),
- creationCalPlusOne.get(Calendar.MONTH),
- creationCalPlusOne.get(Calendar.DAY_OF_MONTH),
- null
- );
-
- } else {
- // normally, just init with today
- datePicker.init(
- todayCal.get(Calendar.YEAR),
- todayCal.get(Calendar.MONTH),
- todayCal.get(Calendar.DAY_OF_MONTH),
- null
- );
- }
+ expiryLayout.setVisibility(View.GONE);
+
+ currentExpiry.setText(R.string.btn_no_date);
} else {
noExpiry.setChecked(false);
- datePicker.setVisibility(View.VISIBLE);
+ expiryLayout.setVisibility(View.VISIBLE);
+
+ // convert from UTC to time zone of device
+ Calendar expiryCalTimeZone = (Calendar) expiryCal.clone();
+ expiryCalTimeZone.setTimeZone(TimeZone.getDefault());
+ currentExpiry.setText(DateFormat.getDateFormat(
+ getActivity()).format(expiryCalTimeZone.getTime()));
+ }
+
+ // date picker works based on default time zone
+ Calendar todayCal = Calendar.getInstance(TimeZone.getDefault());
+ if (creationCal.after(todayCal)) {
+ // NOTE: This is just for the rare cases where creation is _after_ today
+ // Min Date: Creation date + 1 day
- // set date picker to current expiry
+ Calendar creationCalPlusOne = (Calendar) creationCal.clone();
+ creationCalPlusOne.add(Calendar.DAY_OF_YEAR, 1);
+ datePicker.setMinDate(creationCalPlusOne.getTime().getTime());
datePicker.init(
- expiryCal.get(Calendar.YEAR),
- expiryCal.get(Calendar.MONTH),
- expiryCal.get(Calendar.DAY_OF_MONTH),
+ creationCalPlusOne.get(Calendar.YEAR),
+ creationCalPlusOne.get(Calendar.MONTH),
+ creationCalPlusOne.get(Calendar.DAY_OF_MONTH),
null
);
- }
+ } else {
+ // Min Date: today + 1 day
- datePicker.setMinDate(creationCal.getTime().getTime());
+ // at least one day after creation (today)
+ todayCal.add(Calendar.DAY_OF_YEAR, 1);
+ datePicker.setMinDate(todayCal.getTime().getTime());
+ datePicker.init(
+ todayCal.get(Calendar.YEAR),
+ todayCal.get(Calendar.MONTH),
+ todayCal.get(Calendar.DAY_OF_MONTH),
+ null
+ );
+ }
alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
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 a05719072..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
@@ -92,15 +95,17 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity);
alert.setTitle(title);
- alert.setMessage(R.string.enter_passphrase_twice);
LayoutInflater inflater = activity.getLayoutInflater();
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/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
index 38ed88b9c..c5403e054 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java
@@ -379,27 +379,29 @@ public class KeyFormattingUtils {
public static final int DEFAULT_COLOR = -1;
- public static final int STATE_REVOKED = 1;
- public static final int STATE_EXPIRED = 2;
- public static final int STATE_VERIFIED = 3;
- public static final int STATE_UNAVAILABLE = 4;
- public static final int STATE_ENCRYPTED = 5;
- public static final int STATE_NOT_ENCRYPTED = 6;
- public static final int STATE_UNVERIFIED = 7;
- public static final int STATE_UNKNOWN_KEY = 8;
- public static final int STATE_INVALID = 9;
- public static final int STATE_NOT_SIGNED = 10;
-
- public static void setStatusImage(Context context, ImageView statusIcon, int state) {
+ public static enum State {
+ REVOKED,
+ EXPIRED,
+ VERIFIED,
+ UNAVAILABLE,
+ ENCRYPTED,
+ NOT_ENCRYPTED,
+ UNVERIFIED,
+ UNKNOWN_KEY,
+ INVALID,
+ NOT_SIGNED
+ }
+
+ public static void setStatusImage(Context context, ImageView statusIcon, State state) {
setStatusImage(context, statusIcon, null, state);
}
- public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText, int state) {
+ public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText, State state) {
setStatusImage(context, statusIcon, statusText, state, KeyFormattingUtils.DEFAULT_COLOR, false);
}
public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText,
- int state, int color) {
+ State state, int color) {
setStatusImage(context, statusIcon, statusText, state, color, false);
}
@@ -407,16 +409,16 @@ public class KeyFormattingUtils {
* Sets status image based on constant
*/
public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText,
- int state, int color, boolean big) {
+ State state, int color, boolean big) {
switch (state) {
/** GREEN: everything is good **/
- case STATE_VERIFIED: {
+ case VERIFIED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_verified_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_green_light;
@@ -428,9 +430,9 @@ public class KeyFormattingUtils {
}
break;
}
- case STATE_ENCRYPTED: {
+ case ENCRYPTED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_lock_closed_24px));
+ context.getResources().getDrawable(R.drawable.status_lock_closed_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_green_light;
}
@@ -442,13 +444,13 @@ public class KeyFormattingUtils {
break;
}
/** ORANGE: mostly bad... **/
- case STATE_UNVERIFIED: {
+ case UNVERIFIED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_orange_light;
@@ -460,9 +462,9 @@ public class KeyFormattingUtils {
}
break;
}
- case STATE_UNKNOWN_KEY: {
+ case UNKNOWN_KEY: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_orange_light;
}
@@ -474,13 +476,13 @@ public class KeyFormattingUtils {
break;
}
/** RED: really bad... **/
- case STATE_REVOKED: {
+ case REVOKED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
@@ -492,13 +494,13 @@ public class KeyFormattingUtils {
}
break;
}
- case STATE_EXPIRED: {
+ case EXPIRED: {
if (big) {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_96px));
+ context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_96dp));
} else {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_expired_cutout_24dp));
}
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
@@ -510,9 +512,9 @@ public class KeyFormattingUtils {
}
break;
}
- case STATE_NOT_ENCRYPTED: {
+ case NOT_ENCRYPTED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_lock_open_24px));
+ context.getResources().getDrawable(R.drawable.status_lock_open_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
}
@@ -523,9 +525,9 @@ public class KeyFormattingUtils {
}
break;
}
- case STATE_NOT_SIGNED: {
+ case NOT_SIGNED: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
}
@@ -536,9 +538,9 @@ public class KeyFormattingUtils {
}
break;
}
- case STATE_INVALID: {
+ case INVALID: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.android_red_light;
}
@@ -550,9 +552,9 @@ public class KeyFormattingUtils {
break;
}
/** special **/
- case STATE_UNAVAILABLE: {
+ case UNAVAILABLE: {
statusIcon.setImageDrawable(
- context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24px));
+ context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout_24dp));
if (color == KeyFormattingUtils.DEFAULT_COLOR) {
color = R.color.bg_gray;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
index 6d0e6556f..fc912fccb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
@@ -31,6 +31,7 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
public class CertifyKeySpinner extends KeySpinner {
private long mHiddenMasterKeyId = Constants.key.none;
@@ -103,16 +104,16 @@ public class CertifyKeySpinner extends KeySpinner {
@Override
boolean setStatus(Context context, Cursor cursor, ImageView statusView) {
if (cursor.getInt(mIndexIsRevoked) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.REVOKED, R.color.bg_gray);
return false;
}
if (cursor.getInt(mIndexIsExpired) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.EXPIRED, R.color.bg_gray);
return false;
}
// don't invalidate the "None" entry, which is also null!
if (cursor.getPosition() != 0 && cursor.isNull(mIndexHasCertify)) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_UNAVAILABLE, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.UNAVAILABLE, R.color.bg_gray);
return false;
}
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/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
index f05f5f96b..d20e2bc99 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
@@ -90,7 +90,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView {
}
private void setImageByKey(ImageView view, EncryptionKey key) {
- Bitmap photo = ContactHelper.photoFromFingerprint(getContext().getContentResolver(), key.getFingerprint());
+ Bitmap photo = ContactHelper.getCachedPhotoByMasterKeyId(getContext().getContentResolver(), key.getKeyId());
if (photo != null) {
view.setImageBitmap(photo);
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/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java
index fe91e306e..10327a6a4 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java
@@ -29,6 +29,7 @@ import android.widget.ImageView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
+import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
public class SignKeySpinner extends KeySpinner {
public SignKeySpinner(Context context) {
@@ -84,15 +85,15 @@ public class SignKeySpinner extends KeySpinner {
@Override
boolean setStatus(Context context, Cursor cursor, ImageView statusView) {
if (cursor.getInt(mIndexIsRevoked) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.REVOKED, R.color.bg_gray);
return false;
}
if (cursor.getInt(mIndexIsExpired) != 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.EXPIRED, R.color.bg_gray);
return false;
}
if (cursor.getInt(mIndexHasSign) == 0) {
- KeyFormattingUtils.setStatusImage(getContext(), statusView, null, KeyFormattingUtils.STATE_UNAVAILABLE, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), statusView, null, State.UNAVAILABLE, R.color.bg_gray);
return false;
}
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;
+ }
+}