diff options
author | Vincent Breitmoser <valodim@mugenguild.com> | 2015-03-10 00:57:23 +0100 |
---|---|---|
committer | Vincent Breitmoser <valodim@mugenguild.com> | 2015-03-10 00:57:23 +0100 |
commit | 4db86fdabe80cffba13b5e18e1576b5d8de39e8d (patch) | |
tree | 80ca70fdd019824c65fc3b73740b1311cecc257e /OpenKeychain/src/main/java/org | |
parent | f76f84dfb2e406dd613be04dabd9432ffd0f9c4b (diff) | |
parent | e3547b497932a1c0219c11d586858754c82d19da (diff) | |
download | open-keychain-4db86fdabe80cffba13b5e18e1576b5d8de39e8d.tar.gz open-keychain-4db86fdabe80cffba13b5e18e1576b5d8de39e8d.tar.bz2 open-keychain-4db86fdabe80cffba13b5e18e1576b5d8de39e8d.zip |
Merge remote-tracking branch 'development' into linked-identities
Diffstat (limited to 'OpenKeychain/src/main/java/org')
24 files changed, 786 insertions, 432 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 03fa41984..390e85ef8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -38,8 +38,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEnt import org.sufficientlysecure.keychain.operations.results.PgpSignEncryptResult; import org.sufficientlysecure.keychain.pgp.PgpConstants; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; -import org.sufficientlysecure.keychain.pgp.PgpHelper; -import org.sufficientlysecure.keychain.pgp.PgpKeyOperation; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptInput; import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; @@ -55,7 +53,6 @@ import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.Preferences; import java.io.IOException; import java.io.InputStream; @@ -83,7 +80,7 @@ public class OpenPgpService extends RemoteService { * @param encryptionUserIds * @return */ - private Intent getKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { + private Intent returnKeyIdsFromEmails(Intent data, String[] encryptionUserIds) { boolean noUserIdsCheck = (encryptionUserIds == null || encryptionUserIds.length == 0); boolean missingUserIdsCheck = false; boolean duplicateUserIdsCheck = false; @@ -164,7 +161,24 @@ public class OpenPgpService extends RemoteService { } } - private Intent getNfcSignIntent(Intent data, long keyId, String pin, byte[] hashToSign, int hashAlgo) { + private Intent returnPassphraseIntent(Intent data, long keyId) { + // build PendingIntent for passphrase input + Intent intent = new Intent(getBaseContext(), PassphraseDialogActivity.class); + intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, keyId); + // pass params through to activity that it can be returned again later to repeat pgp operation + intent.putExtra(PassphraseDialogActivity.EXTRA_DATA, data); + PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, + intent, + PendingIntent.FLAG_CANCEL_CURRENT); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; + } + + private PendingIntent getNfcSignPendingIntent(Intent data, long keyId, String pin, byte[] hashToSign, int hashAlgo) { // build PendingIntent for Yubikey NFC operations Intent intent = new Intent(getBaseContext(), NfcActivity.class); intent.setAction(NfcActivity.ACTION_SIGN_HASH); @@ -175,18 +189,12 @@ public class OpenPgpService extends RemoteService { intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign); intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo); - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, + return PendingIntent.getActivity(getBaseContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; } - private Intent getNfcDecryptIntent(Intent data, long subKeyId, String pin, byte[] encryptedSessionKey) { + private PendingIntent getNfcDecryptPendingIntent(Intent data, long subKeyId, String pin, byte[] encryptedSessionKey) { // build PendingIntent for Yubikey NFC operations Intent intent = new Intent(getBaseContext(), NfcActivity.class); intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY); @@ -196,32 +204,31 @@ public class OpenPgpService extends RemoteService { intent.putExtra(NfcActivity.EXTRA_KEY_ID, subKeyId); intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey); - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, + return PendingIntent.getActivity(getBaseContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); - - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; } - private Intent getPassphraseIntent(Intent data, long keyId) { - // build PendingIntent for passphrase input - Intent intent = new Intent(getBaseContext(), PassphraseDialogActivity.class); - intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, keyId); - // pass params through to activity that it can be returned again later to repeat pgp operation - intent.putExtra(PassphraseDialogActivity.EXTRA_DATA, data); - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, + private PendingIntent getKeyserverPendingIntent(Intent data, long masterKeyId) { + // If signature is unknown we return an _additional_ PendingIntent + // to retrieve the missing key + Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE); + intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, masterKeyId); + intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data); + + return PendingIntent.getActivity(getBaseContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + } - // return PendingIntent to be executed by client - Intent result = new Intent(); - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); - result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); - return result; + private PendingIntent getShowKeyPendingIntent(long masterKeyId) { + Intent intent = new Intent(getBaseContext(), ViewKeyActivity.class); + intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); + + return PendingIntent.getActivity(getBaseContext(), 0, + intent, + PendingIntent.FLAG_CANCEL_CURRENT); } private Intent signImpl(Intent data, ParcelFileDescriptor input, @@ -274,21 +281,27 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { - return getPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); + return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == PgpSignEncryptResult.RESULT_PENDING_NFC) { // return PendingIntent to execute NFC activity // pass through the signature creation timestamp to be used again on second execution // of PgpSignEncrypt when we have the signed hash! data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, pgpResult.getNfcTimestamp().getTime()); - return getNfcSignIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo()); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, + getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo())); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; } else { throw new PgpGeneralException( "Encountered unhandled type of pending action not supported by API!"); } } else if (pgpResult.success()) { Intent result = new Intent(); - if (!cleartextSign) { + if (pgpResult.getDetachedSignature() != null && !cleartextSign) { result.putExtra(OpenPgpApi.RESULT_DETACHED_SIGNATURE, pgpResult.getDetachedSignature()); } result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); @@ -340,7 +353,7 @@ public class OpenPgpService extends RemoteService { // get key ids based on given user ids String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); // give params through to activity... - Intent result = getKeyIdsFromEmails(data, userIds); + Intent result = returnKeyIdsFromEmails(data, userIds); if (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0) == OpenPgpApi.RESULT_CODE_SUCCESS) { keyIds = result.getLongArrayExtra(OpenPgpApi.RESULT_KEY_IDS); @@ -391,14 +404,19 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) == PgpSignEncryptResult.RESULT_PENDING_PASSPHRASE) { - return getPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); + return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); } else if ((pgpResult.getResult() & PgpSignEncryptResult.RESULT_PENDING_NFC) == PgpSignEncryptResult.RESULT_PENDING_NFC) { // return PendingIntent to execute NFC activity // pass through the signature creation timestamp to be used again on second execution // of PgpSignEncrypt when we have the signed hash! data.putExtra(OpenPgpApi.EXTRA_NFC_SIG_CREATION_TIMESTAMP, pgpResult.getNfcTimestamp().getTime()); - return getNfcSignIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo()); + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, + getNfcSignPendingIntent(data, pgpResult.getNfcKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcHash(), pgpResult.getNfcAlgo())); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; } else { throw new PgpGeneralException( "Encountered unhandled type of pending action not supported by API!"); @@ -478,15 +496,20 @@ public class OpenPgpService extends RemoteService { if (pgpResult.isPending()) { if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { - return getPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); + return returnPassphraseIntent(data, pgpResult.getKeyIdPassphraseNeeded()); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) == DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { throw new PgpGeneralException( "Decryption of symmetric content not supported by API!"); } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) == DecryptVerifyResult.RESULT_PENDING_NFC) { - return getNfcDecryptIntent( - data, pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey()); + + // return PendingIntent to be executed by client + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, + getNfcDecryptPendingIntent(data, pgpResult.getNfcSubKeyId(), pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey())); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; } else { throw new PgpGeneralException( "Encountered unhandled type of pending action not supported by API!"); @@ -509,16 +532,10 @@ public class OpenPgpService extends RemoteService { if (signatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) { // If signature is unknown we return an _additional_ PendingIntent // to retrieve the missing key - Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class); - intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE); - intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, signatureResult.getKeyId()); - intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data); - - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + result.putExtra(OpenPgpApi.RESULT_INTENT, getKeyserverPendingIntent(data, signatureResult.getKeyId())); + } else { + // If signature key is known, return PendingIntent to show key + result.putExtra(OpenPgpApi.RESULT_INTENT, getShowKeyPendingIntent(signatureResult.getKeyId())); } } @@ -576,33 +593,15 @@ public class OpenPgpService extends RemoteService { Intent result = new Intent(); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS); - // also return PendingIntent that opens the key view activity - Intent intent = new Intent(getBaseContext(), ViewKeyActivity.class); - intent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId)); - - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + result.putExtra(OpenPgpApi.RESULT_INTENT, getShowKeyPendingIntent(masterKeyId)); return result; } catch (ProviderHelper.NotFoundException e) { - Intent result = new Intent(); - // If keys are not in db we return an additional PendingIntent // to retrieve the missing key - Intent intent = new Intent(getBaseContext(), ImportKeysActivity.class); - intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE); - intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, masterKeyId); - intent.putExtra(ImportKeysActivity.EXTRA_PENDING_INTENT_DATA, data); - - PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, - intent, - PendingIntent.FLAG_CANCEL_CURRENT); - - result.putExtra(OpenPgpApi.RESULT_INTENT, pi); + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, getKeyserverPendingIntent(data, masterKeyId)); result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); return result; } @@ -629,7 +628,7 @@ public class OpenPgpService extends RemoteService { } else { // get key ids based on given user ids String[] userIds = data.getStringArrayExtra(OpenPgpApi.EXTRA_USER_IDS); - return getKeyIdsFromEmails(data, userIds); + return returnKeyIdsFromEmails(data, userIds); } } @@ -669,7 +668,7 @@ public class OpenPgpService extends RemoteService { return result; } - // check if caller is allowed to access openpgp keychain + // check if caller is allowed to access OpenKeychain Intent result = isAllowed(data); if (result != null) { return result; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java index e6c2542a2..41fa50705 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BaseActivity.java @@ -88,12 +88,20 @@ public abstract class BaseActivity extends ActionBarActivity { /** * Close button only */ - protected void setFullScreenDialogClose(View.OnClickListener cancelOnClickListener) { - setActionBarIcon(R.drawable.ic_close_white_24dp); + protected void setFullScreenDialogClose(View.OnClickListener cancelOnClickListener, boolean white) { + if (white) { + setActionBarIcon(R.drawable.ic_close_white_24dp); + } else { + setActionBarIcon(R.drawable.ic_close_black_24dp); + } getSupportActionBar().setDisplayShowTitleEnabled(true); mToolbar.setNavigationOnClickListener(cancelOnClickListener); } + protected void setFullScreenDialogClose(View.OnClickListener cancelOnClickListener) { + setFullScreenDialogClose(cancelOnClickListener, true); + } + /** * Inflate custom design with two buttons using drawables. * This does not conform to the Material Design Guidelines, but we deviate here as this is used 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 60cc404b6..2da5511b8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -39,8 +39,8 @@ public class CreateKeyActivity extends BaseActivity { super.onCreate(savedInstanceState); // pass extras into fragment - CreateKeyInputFragment frag = - CreateKeyInputFragment.newInstance( + CreateKeyNameFragment frag = + CreateKeyNameFragment.newInstance( getIntent().getStringExtra(EXTRA_NAME), getIntent().getStringExtra(EXTRA_EMAIL) ); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java new file mode 100644 index 000000000..d9f391149 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; +import org.sufficientlysecure.keychain.ui.widget.EmailEditText; + +public class CreateKeyEmailFragment extends Fragment { + + public static final String ARG_NAME = "name"; + public static final String ARG_EMAIL = "email"; + + CreateKeyActivity mCreateKeyActivity; + EmailEditText mEmailEdit; + View mBackButton; + View mNextButton; + + String mName; + + /** + * Creates new instance of this fragment + */ + public static CreateKeyEmailFragment newInstance(String name, String email) { + CreateKeyEmailFragment frag = new CreateKeyEmailFragment(); + + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putString(ARG_EMAIL, email); + + frag.setArguments(args); + + return frag; + } + + /** + * Checks if text of given EditText is not empty. If it is empty an error is + * set and the EditText gets the focus. + * + * @param context + * @param editText + * @return true if EditText is not empty + */ + private static boolean isEditTextNotEmpty(Context context, EditText editText) { + boolean output = true; + if (editText.getText().toString().length() == 0) { + editText.setError(context.getString(R.string.create_key_empty)); + editText.requestFocus(); + output = false; + } else { + editText.setError(null); + } + + return output; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.create_key_email_fragment, container, false); + + mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email); + mBackButton = view.findViewById(R.id.create_key_back_button); + mNextButton = view.findViewById(R.id.create_key_next_button); + + // initial values + mName = getArguments().getString(ARG_NAME); + String email = getArguments().getString(ARG_EMAIL); + mEmailEdit.setText(email); + + // focus empty edit fields + if (email == null) { + mEmailEdit.requestFocus(); + } + mBackButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT); + } + }); + mNextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createKeyCheck(); + } + }); + + return view; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mCreateKeyActivity = (CreateKeyActivity) getActivity(); + } + + private void createKeyCheck() { + if (isEditTextNotEmpty(getActivity(), mEmailEdit)) { + + CreateKeyPassphraseFragment frag = + CreateKeyPassphraseFragment.newInstance( + mName, + mEmailEdit.getText().toString() + ); + + mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT); + } + } + +} 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 920488e3e..dc9f3d4ad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -95,7 +95,7 @@ public class CreateKeyFinalFragment extends Fragment { mEmailEdit = (TextView) view.findViewById(R.id.email); mUploadCheckbox = (CheckBox) view.findViewById(R.id.create_key_upload); mBackButton = view.findViewById(R.id.create_key_back_button); - mCreateButton = view.findViewById(R.id.create_key_create_button); + mCreateButton = view.findViewById(R.id.create_key_next_button); mEditText = (TextView) view.findViewById(R.id.create_key_edit_text); mEditButton = view.findViewById(R.id.create_key_edit_button); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java new file mode 100644 index 000000000..50a3bd655 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyNameFragment.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; +import org.sufficientlysecure.keychain.ui.widget.EmailEditText; +import org.sufficientlysecure.keychain.ui.widget.NameEditText; + +public class CreateKeyNameFragment extends Fragment { + + public static final String ARG_NAME = "name"; + public static final String ARG_EMAIL = "email"; + + CreateKeyActivity mCreateKeyActivity; + NameEditText mNameEdit; + View mNextButton; + + String mEmail; + + /** + * Creates new instance of this fragment + */ + public static CreateKeyNameFragment newInstance(String name, String email) { + CreateKeyNameFragment frag = new CreateKeyNameFragment(); + + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putString(ARG_EMAIL, email); + + frag.setArguments(args); + + return frag; + } + + /** + * Checks if text of given EditText is not empty. If it is empty an error is + * set and the EditText gets the focus. + * + * @param context + * @param editText + * @return true if EditText is not empty + */ + private static boolean isEditTextNotEmpty(Context context, EditText editText) { + boolean output = true; + if (editText.getText().toString().length() == 0) { + editText.setError(context.getString(R.string.create_key_empty)); + editText.requestFocus(); + output = false; + } else { + editText.setError(null); + } + + return output; + } + + private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) { + boolean output = true; + if (!editText1.getText().toString().equals(editText2.getText().toString())) { + editText2.setError(context.getString(R.string.create_key_passphrases_not_equal)); + editText2.requestFocus(); + output = false; + } else { + editText2.setError(null); + } + + return output; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.create_key_name_fragment, container, false); + + mNameEdit = (NameEditText) view.findViewById(R.id.create_key_name); + mNextButton = view.findViewById(R.id.create_key_next_button); + + // initial values + String name = getArguments().getString(ARG_NAME); + mEmail = getArguments().getString(ARG_EMAIL); + mNameEdit.setText(name); + + // focus empty edit fields + if (name == null) { + mNameEdit.requestFocus(); + } + mNextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createKeyCheck(); + } + }); + + return view; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mCreateKeyActivity = (CreateKeyActivity) getActivity(); + } + + private void createKeyCheck() { + if (isEditTextNotEmpty(getActivity(), mNameEdit)) { + + CreateKeyEmailFragment frag = + CreateKeyEmailFragment.newInstance( + mNameEdit.getText().toString(), + mEmail + ); + + mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT); + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java index b496d40fd..00ac00ff4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java @@ -17,43 +17,46 @@ package org.sufficientlysecure.keychain.ui; +import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; +import android.widget.CheckBox; +import android.widget.CompoundButton; 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 org.sufficientlysecure.keychain.ui.widget.PassphraseEditText; -public class CreateKeyInputFragment extends Fragment { - - CreateKeyActivity mCreateKeyActivity; - - PasswordStrengthView mPassphraseStrengthView; - AutoCompleteTextView mNameEdit; - EmailEditText mEmailEdit; - PasswordEditText mPassphraseEdit; - EditText mPassphraseEditAgain; - View mCreateButton; +public class CreateKeyPassphraseFragment extends Fragment { public static final String ARG_NAME = "name"; public static final String ARG_EMAIL = "email"; + // model + String mName; + String mEmail; + + // view + CreateKeyActivity mCreateKeyActivity; + PassphraseEditText mPassphraseEdit; + EditText mPassphraseEditAgain; + CheckBox mShowPassphrase; + View mBackButton; + View mNextButton; + /** * Creates new instance of this fragment */ - public static CreateKeyInputFragment newInstance(String name, String email) { - CreateKeyInputFragment frag = new CreateKeyInputFragment(); + public static CreateKeyPassphraseFragment newInstance(String name, String email) { + CreateKeyPassphraseFragment frag = new CreateKeyPassphraseFragment(); Bundle args = new Bundle(); args.putString(ARG_NAME, name); @@ -64,84 +67,102 @@ public class CreateKeyInputFragment extends Fragment { return frag; } + /** + * Checks if text of given EditText is not empty. If it is empty an error is + * set and the EditText gets the focus. + * + * @param context + * @param editText + * @return true if EditText is not empty + */ + private static boolean isEditTextNotEmpty(Context context, EditText editText) { + boolean output = true; + if (editText.getText().toString().length() == 0) { + editText.setError(context.getString(R.string.create_key_empty)); + editText.requestFocus(); + output = false; + } else { + editText.setError(null); + } + + return output; + } + + private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) { + boolean output = true; + if (!editText1.getText().toString().equals(editText2.getText().toString())) { + editText2.setError(context.getString(R.string.create_key_passphrases_not_equal)); + editText2.requestFocus(); + output = false; + } else { + editText2.setError(null); + } + + return output; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.create_key_input_fragment, container, false); + View view = inflater.inflate(R.layout.create_key_passphrase_fragment, container, false); - mPassphraseStrengthView = (PasswordStrengthView) view.findViewById(R.id - .create_key_passphrase_strength); - mNameEdit = (AutoCompleteTextView) view.findViewById(R.id.create_key_name); - mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email); - mPassphraseEdit = (PasswordEditText) view.findViewById(R.id.create_key_passphrase); + mPassphraseEdit = (PassphraseEditText) 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); + mShowPassphrase = (CheckBox) view.findViewById(R.id.create_key_show_passphrase); + mBackButton = view.findViewById(R.id.create_key_back_button); + mNextButton = view.findViewById(R.id.create_key_next_button); // initial values - String name = getArguments().getString(ARG_NAME); - String email = getArguments().getString(ARG_EMAIL); - mNameEdit.setText(name); - mEmailEdit.setText(email); - - // focus non-empty edit fields - if (name != null && email != null) { - mPassphraseEdit.requestFocus(); - } else if (name != null) { - mEmailEdit.requestFocus(); - } - - mEmailEdit.setThreshold(1); // Start working from first character - mEmailEdit.setAdapter( - new ArrayAdapter<> - (getActivity(), android.R.layout.simple_spinner_dropdown_item, - ContactHelper.getPossibleUserEmails(getActivity()) - ) - ); - - - mNameEdit.setThreshold(1); // Start working from first character - mNameEdit.setAdapter( - new ArrayAdapter<> - (getActivity(), android.R.layout.simple_spinner_dropdown_item, - ContactHelper.getPossibleUserNames(getActivity()) - ) - ); - - // 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() { + mName = getArguments().getString(ARG_NAME); + mEmail = getArguments().getString(ARG_EMAIL); + mPassphraseEdit.requestFocus(); + mBackButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + back(); + } + }); + mNextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { createKeyCheck(); } }); + mShowPassphrase.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + mPassphraseEdit.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + mPassphraseEditAgain.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + } else { + mPassphraseEdit.setTransformationMethod(PasswordTransformationMethod.getInstance()); + mPassphraseEditAgain.setTransformationMethod(PasswordTransformationMethod.getInstance()); + } + } + }); + return view; } @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - + public void onAttach(Activity activity) { + super.onAttach(activity); mCreateKeyActivity = (CreateKeyActivity) getActivity(); } + private void back() { + hideKeyboard(); + mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT); + } + private void createKeyCheck() { - if (isEditTextNotEmpty(getActivity(), mNameEdit) - && isEditTextNotEmpty(getActivity(), mEmailEdit) - && isEditTextNotEmpty(getActivity(), mPassphraseEdit) + if (isEditTextNotEmpty(getActivity(), mPassphraseEdit) && areEditTextsEqual(getActivity(), mPassphraseEdit, mPassphraseEditAgain)) { CreateKeyFinalFragment frag = CreateKeyFinalFragment.newInstance( - mNameEdit.getText().toString(), - mEmailEdit.getText().toString(), + mName, + mEmail, mPassphraseEdit.getText().toString() ); @@ -165,38 +186,4 @@ public class CreateKeyInputFragment extends Fragment { inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); } - /** - * Checks if text of given EditText is not empty. If it is empty an error is - * set and the EditText gets the focus. - * - * @param context - * @param editText - * @return true if EditText is not empty - */ - private static boolean isEditTextNotEmpty(Context context, EditText editText) { - boolean output = true; - if (editText.getText().toString().length() == 0) { - editText.setError(context.getString(R.string.create_key_empty)); - editText.requestFocus(); - output = false; - } else { - editText.setError(null); - } - - return output; - } - - private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) { - boolean output = true; - if (!editText1.getText().toString().equals(editText2.getText().toString())) { - editText2.setError(context.getString(R.string.create_key_passphrases_not_equal)); - editText2.requestFocus(); - output = false; - } else { - editText2.setError(null); - } - - return output; - } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java index 89dd4970b..162b10eca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java @@ -17,9 +17,12 @@ package org.sufficientlysecure.keychain.ui; +import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.os.PersistableBundle; +import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -40,6 +43,14 @@ public class DecryptFilesActivity extends BaseActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setFullScreenDialogClose(new View.OnClickListener() { + @Override + public void onClick(View v) { + setResult(Activity.RESULT_CANCELED); + finish(); + } + }, false); + // Handle intent actions handleActions(savedInstanceState, getIntent()); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java index 81a8a2ac4..1e9e7bcb1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java @@ -18,9 +18,11 @@ package org.sufficientlysecure.keychain.ui; +import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; +import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -49,6 +51,14 @@ public class DecryptTextActivity extends BaseActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setFullScreenDialogClose(new View.OnClickListener() { + @Override + public void onClick(View v) { + setResult(Activity.RESULT_CANCELED); + finish(); + } + }, false); + // Handle intent actions handleActions(savedInstanceState, getIntent()); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 0d7e6056e..ed5920cde 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -1,10 +1,29 @@ +/* + * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + package org.sufficientlysecure.keychain.ui; +import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.os.Message; import android.os.Messenger; +import android.view.View; import org.openintents.openpgp.util.OpenPgpApi; import org.sufficientlysecure.keychain.R; @@ -26,6 +45,19 @@ public abstract class EncryptActivity extends BaseActivity { protected Date mNfcTimestamp = null; protected byte[] mNfcHash = null; + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setFullScreenDialogClose(new View.OnClickListener() { + @Override + public void onClick(View v) { + setResult(Activity.RESULT_CANCELED); + finish(); + } + }, false); + } + protected void startPassphraseDialog(long subkeyId) { Intent intent = new Intent(this, PassphraseDialogActivity.class); intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId); 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 11b596c24..d95b5cda3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -67,8 +67,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi private String mEncryptionUserIds[] = null; private long mSigningKeyId = Constants.key.none; private String mPassphrase = ""; - private boolean mUseArmor; - private boolean mUseCompression; + private boolean mUseArmor = false; + private boolean mUseCompression = true; private boolean mDeleteAfterEncrypt = false; private boolean mShareAfterEncrypt = false; private ArrayList<Uri> mInputUris; @@ -209,6 +209,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi } else { data.setCompressionId(CompressionAlgorithmTags.UNCOMPRESSED); } + data.setEnableAsciiArmorOutput(mUseArmor); data.setSymmetricEncryptionAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); data.setSignatureHashAlgorithm(PgpConstants.OpenKeychainSymmetricKeyAlgorithmTags.USE_PREFERRED); @@ -314,15 +315,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // if called with an intent action, do not init drawer navigation - if (ACTION_ENCRYPT_DATA.equals(getIntent().getAction())) { - // lock drawer -// deactivateDrawerNavigation(); - // TODO: back button to key? - } else { -// activateDrawerNavigation(savedInstanceState); - } - // Handle intent actions handleActions(getIntent()); updateModeFragment(); @@ -339,17 +331,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi return super.onCreateOptionsMenu(menu); } - private void updateModeFragment() { - getSupportFragmentManager().beginTransaction() - .replace(R.id.encrypt_pager_mode, - mCurrentMode == MODE_SYMMETRIC - ? new EncryptSymmetricFragment() - : new EncryptAsymmetricFragment() - ) - .commitAllowingStateLoss(); - getSupportFragmentManager().executePendingTransactions(); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.isCheckable()) { @@ -384,6 +365,17 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi return true; } + private void updateModeFragment() { + getSupportFragmentManager().beginTransaction() + .replace(R.id.encrypt_pager_mode, + mCurrentMode == MODE_SYMMETRIC + ? new EncryptSymmetricFragment() + : new EncryptAsymmetricFragment() + ) + .commitAllowingStateLoss(); + getSupportFragmentManager().executePendingTransactions(); + } + /** * Handles all actions with this intent * @@ -418,9 +410,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM); } - if (extras.containsKey(EXTRA_ASCII_ARMOR)) { - mUseArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, true); - } + mUseArmor = extras.getBoolean(EXTRA_ASCII_ARMOR, false); // preselect keys given by intent mSigningKeyId = extras.getLong(EXTRA_SIGNATURE_KEY_ID); @@ -428,7 +418,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi // Save uris mInputUris = uris; - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index 860bd8502..ace58b165 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -27,6 +27,7 @@ import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; @@ -56,7 +57,6 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt // view private View mAddView; - private View mShareFile; private ListView mSelectedFiles; private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); private final Map<Uri, Bitmap> thumbnailCache = new HashMap<>(); @@ -78,21 +78,6 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_files_fragment, container, false); - View vEncryptFile = view.findViewById(R.id.action_encrypt_file); - vEncryptFile.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - encryptClicked(false); - } - }); - mShareFile = view.findViewById(R.id.action_encrypt_share); - mShareFile.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - encryptClicked(true); - } - }); - mAddView = inflater.inflate(R.layout.file_list_entry_add, null); mAddView.setOnClickListener(new View.OnClickListener() { @Override @@ -108,8 +93,10 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt } @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setHasOptionsMenu(true); } private void addInputUri() { @@ -192,6 +179,24 @@ public class EncryptFilesFragment extends Fragment implements EncryptActivityInt } @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.encrypt_save: { + encryptClicked(false); + break; + } + case R.id.encrypt_share: { + encryptClicked(true); + break; + } + default: { + return super.onOptionsItemSelected(item); + } + } + return true; + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CODE_INPUT: { 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 08ff5b962..ee15cf7b5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -72,7 +72,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv private ArrayList<Uri> mInputUris; private ArrayList<Uri> mOutputUris; private String mMessage = ""; - private boolean mUseCompression; + private boolean mUseCompression = true; public boolean isModeSymmetric() { return MODE_SYMMETRIC == mCurrentMode; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java index b13cb7837..5d9994c5c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextFragment.java @@ -23,6 +23,7 @@ import android.support.v4.app.Fragment; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; @@ -33,8 +34,6 @@ public class EncryptTextFragment extends Fragment { public static final String ARG_TEXT = "text"; private TextView mText; - private View mEncryptShare; - private View mEncryptClipboard; private EncryptActivityInterface mEncryptInterface; @@ -72,24 +71,16 @@ public class EncryptTextFragment extends Fragment { mEncryptInterface.setMessage(s.toString()); } }); - mEncryptClipboard = view.findViewById(R.id.action_encrypt_clipboard); - mEncryptShare = view.findViewById(R.id.action_encrypt_share); - mEncryptClipboard.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mEncryptInterface.startEncrypt(false); - } - }); - mEncryptShare.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mEncryptInterface.startEncrypt(true); - } - }); return view; } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setHasOptionsMenu(true); + } @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -100,4 +91,22 @@ public class EncryptTextFragment extends Fragment { mText.setText(text); } } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.encrypt_copy: { + mEncryptInterface.startEncrypt(false); + break; + } + case R.id.encrypt_share: { + mEncryptInterface.startEncrypt(true); + break; + } + default: { + return super.onOptionsItemSelected(item); + } + } + return true; + } } 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 9390e8a69..0654f0c9a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvActivity.java @@ -76,8 +76,8 @@ public class ViewKeyAdvActivity extends BaseActivity implements mExportHelper = new ExportHelper(this); mProviderHelper = new ProviderHelper(this); - mViewPager = (ViewPager) findViewById(R.id.view_key_pager); - mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.view_key_sliding_tab_layout); + mViewPager = (ViewPager) findViewById(R.id.pager); + mSlidingTabLayout = (PagerSlidingTabStrip) findViewById(R.id.sliding_tab_layout); int switchToTab = TAB_MAIN; Intent intent = getIntent(); 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 ee4af8cbe..5dd675fd3 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 @@ -33,8 +33,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; @@ -44,7 +42,7 @@ 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.ui.widget.NameEditText; import org.sufficientlysecure.keychain.util.Log; public class AddUserIdDialogFragment extends DialogFragment implements OnEditorActionListener { @@ -57,7 +55,7 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA public static final String MESSAGE_DATA_USER_ID = "user_id"; private Messenger mMessenger; - private AutoCompleteTextView mName; + private NameEditText mName; private EmailEditText mEmail; private EditText mComment; @@ -81,11 +79,6 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA mMessenger = getArguments().getParcelable(ARG_MESSENGER); String predefinedName = getArguments().getString(ARG_NAME); - ArrayAdapter<String> autoCompleteEmailAdapter = new ArrayAdapter<> - (getActivity(), android.R.layout.simple_spinner_dropdown_item, - ContactHelper.getPossibleUserEmails(getActivity()) - ); - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); alert.setTitle(R.string.edit_key_action_add_identity); @@ -94,16 +87,12 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA View view = inflater.inflate(R.layout.add_user_id_dialog, null); alert.setView(view); - mName = (AutoCompleteTextView) view.findViewById(R.id.add_user_id_name); + mName = (NameEditText) view.findViewById(R.id.add_user_id_name); mEmail = (EmailEditText) view.findViewById(R.id.add_user_id_address); mComment = (EditText) view.findViewById(R.id.add_user_id_comment); mName.setText(predefinedName); - - mEmail.setThreshold(1); // Start working from first character - mEmail.setAdapter(autoCompleteEmailAdapter); - alert.setPositiveButton(android.R.string.ok, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { @@ -118,14 +107,6 @@ public class AddUserIdDialogFragment extends DialogFragment implements OnEditorA } }); - mName.setThreshold(1); // Start working from first character - mName.setAdapter( - new ArrayAdapter<> - (getActivity(), android.R.layout.simple_spinner_dropdown_item, - ContactHelper.getPossibleUserNames(getActivity()) - ) - ); - alert.setNegativeButton(android.R.string.cancel, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { 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 07462b4ff..c4b437593 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 @@ -28,8 +28,10 @@ import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; import android.widget.Toast; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.FileHelper; +import org.sufficientlysecure.keychain.util.Log; import java.io.File; @@ -69,41 +71,44 @@ public class DeleteFileDialogFragment extends DialogFragment { @Override public void onClick(DialogInterface dialog, int id) { dismiss(); - String scheme = deleteUri.getScheme(); - if(scheme.equals(ContentResolver.SCHEME_FILE)) { - if(new File(deleteUri.getPath()).delete()) { - Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); - return; - } - } - else if(scheme.equals(ContentResolver.SCHEME_CONTENT)) { - // We can not securely delete Uris, so just use usual delete on them - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + // NOTE: Use Toasts, not Snackbars. When sharing to another application snackbars + // would not show up! + + // Use DocumentsContract on Android >= 4.4 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + try { if (DocumentsContract.deleteDocument(getActivity().getContentResolver(), deleteUri)) { - Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), getActivity().getString(R.string.file_delete_successful, + deleteFilename), Toast.LENGTH_LONG).show(); return; } + } catch (UnsupportedOperationException e) { + Log.d(Constants.TAG, "Catched UnsupportedOperationException, can happen when delete is not supported!", e); } + } + try { if (getActivity().getContentResolver().delete(deleteUri, null, null) > 0) { - Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); - return; - } - - // some Uri's a ContentResolver fails to delete is handled by the java.io.File's delete - // via the path of the Uri - if(new File(deleteUri.getPath()).delete()) { - Toast.makeText(getActivity(), R.string.file_delete_successful, Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), getActivity().getString(R.string.file_delete_successful, + deleteFilename), Toast.LENGTH_LONG).show(); return; } + } catch (UnsupportedOperationException e) { + Log.d(Constants.TAG, "Catched UnsupportedOperationException, can happen when delete is not supported!", e); } - Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, - deleteFilename), Toast.LENGTH_SHORT).show(); + // some Uri's a ContentResolver fails to delete is handled by the java.io.File's delete + // via the path of the Uri + if (new File(deleteUri.getPath()).delete()) { + Toast.makeText(getActivity(), getActivity().getString(R.string.file_delete_successful, + deleteFilename), Toast.LENGTH_LONG).show(); + return; + } // Note: We can't delete every file... - // If possible we should find out if deletion is possible before even showing the option to do so. + Toast.makeText(getActivity(), getActivity().getString(R.string.error_file_delete_failed, + deleteFilename), Toast.LENGTH_LONG).show(); } }); alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 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 9e1f21f60..b34dc2edc 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,8 +43,7 @@ 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.ui.widget.PassphraseEditText; import org.sufficientlysecure.keychain.util.Log; public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener { @@ -57,10 +56,9 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi public static final String MESSAGE_NEW_PASSPHRASE = "new_passphrase"; private Messenger mMessenger; - private PasswordEditText mPassphraseEditText; + private PassphraseEditText mPassphraseEditText; private EditText mPassphraseAgainEditText; private CheckBox mNoPassphraseCheckBox; - private PasswordStrengthView mPassphraseStrengthView; /** * Creates new instance of this dialog fragment @@ -100,11 +98,9 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi View view = inflater.inflate(R.layout.passphrase_repeat_dialog, null); alert.setView(view); - mPassphraseEditText = (PasswordEditText) view.findViewById(R.id.passphrase_passphrase); + mPassphraseEditText = (PassphraseEditText) 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)) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java index 697f5a61e..1bdec7b84 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EmailEditText.java @@ -25,6 +25,7 @@ import android.text.InputType; import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Patterns; +import android.view.inputmethod.EditorInfo; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; @@ -34,35 +35,33 @@ 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); + init(); } 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); + init(); } 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); + init(); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public EmailEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - emailEditText = this; + init(); + } + + private void init() { this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); this.addTextChangedListener(textWatcher); + removeFlag(); + initAdapter(); } TextWatcher textWatcher = new TextWatcher() { @@ -82,16 +81,32 @@ public class EmailEditText extends AutoCompleteTextView { if (email.length() > 0) { Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); if (emailMatcher.matches()) { - emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, + EmailEditText.this.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.uid_mail_ok, 0); } else { - emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, + EmailEditText.this.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.uid_mail_bad, 0); } } else { // remove drawable if email is empty - emailEditText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + EmailEditText.this.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); } } }; + + private void initAdapter() { + setThreshold(1); // Start working from first character + setAdapter(new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, + ContactHelper.getPossibleUserEmails(getContext()))); + } + + /** + * Hack to re-enable keyboard auto correction in AutoCompleteTextView. + * From http://stackoverflow.com/a/22512858 + */ + private void removeFlag() { + int inputType = getInputType(); + inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE; + setRawInputType(inputType); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/AutoCorrectAutoCompleteTextView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java index ed373a938..f086c5696 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/AutoCorrectAutoCompleteTextView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/NameEditText.java @@ -17,32 +17,54 @@ package org.sufficientlysecure.keychain.ui.widget; +import android.annotation.TargetApi; import android.content.Context; +import android.os.Build; import android.util.AttributeSet; import android.view.inputmethod.EditorInfo; +import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; -/** - * Hack to re-enable keyboard auto correction in AutoCompleteTextView. - * From http://stackoverflow.com/a/22512858 - */ -public class AutoCorrectAutoCompleteTextView extends AutoCompleteTextView { +import org.sufficientlysecure.keychain.util.ContactHelper; - public AutoCorrectAutoCompleteTextView(Context context) { +public class NameEditText extends AutoCompleteTextView { + public NameEditText(Context context) { super(context); - removeFlag(); + init(); } - public AutoCorrectAutoCompleteTextView(Context context, AttributeSet attrs) { + public NameEditText(Context context, AttributeSet attrs) { super(context, attrs); - removeFlag(); + init(); + } + + public NameEditText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); } - public AutoCorrectAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public NameEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { removeFlag(); + initAdapter(); + } + + private void initAdapter() { + setThreshold(1); // Start working from first character + setAdapter(new ArrayAdapter<>( + getContext(), android.R.layout.simple_spinner_dropdown_item, + ContactHelper.getPossibleUserNames(getContext()))); } + /** + * Hack to re-enable keyboard auto correction in AutoCompleteTextView. + * From http://stackoverflow.com/a/22512858 + */ private void removeFlag() { int inputType = getInputType(); inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java new file mode 100644 index 000000000..377f701d1 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PassphraseEditText.java @@ -0,0 +1,88 @@ +/* + * 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.content.Context; +import android.graphics.Canvas; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.widget.EditText; + +import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthBarView; + +public class PassphraseEditText extends EditText { + + PasswordStrengthBarView mPasswordStrengthBarView; + int mPasswordBarWidth; + int mPasswordBarHeight; + float barGap; + + public PassphraseEditText(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + mPasswordBarHeight = (int) (8 * getResources().getDisplayMetrics().density); + mPasswordBarWidth = (int) (50 * getResources().getDisplayMetrics().density); + + barGap = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, + getContext().getResources().getDisplayMetrics()); + + this.setPadding(getPaddingLeft(), getPaddingTop(), + getPaddingRight() + (int) barGap + mPasswordBarWidth, getPaddingBottom()); + + mPasswordStrengthBarView = new PasswordStrengthBarView(context, attrs); + mPasswordStrengthBarView.setShowGuides(false); + + this.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) { + mPasswordStrengthBarView.setPassword(s.toString()); + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + mPasswordStrengthBarView.layout(0, 0, mPasswordBarWidth, mPasswordBarHeight); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + float translateX = getScrollX() + canvas.getWidth() - mPasswordBarWidth; + float translateY = (canvas.getHeight() - mPasswordBarHeight) / 2; + canvas.translate(translateX, translateY); + mPasswordStrengthBarView.draw(canvas); + canvas.translate(-translateX, -translateY); + } +}
\ No newline at end of file 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 deleted file mode 100644 index 04c48922b..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PasswordEditText.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.ui.widget; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import android.text.Editable; -import android.text.InputType; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.widget.EditText; - -import org.sufficientlysecure.keychain.ui.widget.passwordstrengthindicator.PasswordStrengthView; - -/** - * Developer: chipset - * Package : org.sufficientlysecure.keychain.layouts - * Project : open-keychain - * Date : 6/3/15 - */ -public class PasswordEditText extends EditText { - - PasswordEditText passwordEditText; - PasswordStrengthView passwordStrengthView; - - public PasswordEditText(Context context) { - super(context); - passwordEditText = this; - this.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_PASSWORD); - this.addTextChangedListener(textWatcher); - } - - public PasswordEditText(Context context, AttributeSet attrs) { - super(context, attrs); - passwordEditText = this; - this.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_PASSWORD); - this.addTextChangedListener(textWatcher); - } - - public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - passwordEditText = this; - this.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_PASSWORD); - this.addTextChangedListener(textWatcher); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - passwordEditText = this; - this.setInputType(InputType.TYPE_CLASS_TEXT | - InputType.TYPE_TEXT_VARIATION_PASSWORD); - this.addTextChangedListener(textWatcher); - } - - - TextWatcher textWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable editable) { - String passphrase = editable.toString(); - passwordStrengthView.setPassword(passphrase); - } - }; - -// public PasswordStrengthView getPasswordStrengthView() { -// return passwordStrengthView; -// } - - public void setPasswordStrengthView(PasswordStrengthView mPasswordStrengthView) { - this.passwordStrengthView = mPasswordStrengthView; - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/passwordstrengthindicator/PasswordStrengthView.java index d7270ff58..bc5018497 100644 --- 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 @@ -56,9 +56,6 @@ import org.sufficientlysecure.keychain.R; */ 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; @@ -100,6 +97,11 @@ public class PasswordStrengthView extends View { public PasswordStrengthView(Context context, AttributeSet attrs) { super(context, attrs); + + int COLOR_FAIL = context.getResources().getColor(R.color.android_red_light); + int COLOR_WEAK = context.getResources().getColor(R.color.android_orange_light); + int COLOR_STRONG = context.getResources().getColor(R.color.android_green_light); + TypedArray style = context.getTheme().obtainStyledAttributes( attrs, R.styleable.PasswordStrengthView, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java index c66dc04d0..08c7c02fb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java @@ -43,9 +43,11 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; public class ContactHelper { @@ -54,6 +56,17 @@ public class ContactHelper { public static List<String> getPossibleUserEmails(Context context) { Set<String> accountMails = getAccountEmails(context); accountMails.addAll(getMainProfileContactEmails(context)); + + // remove items that are not an email + Iterator<String> it = accountMails.iterator(); + while (it.hasNext()) { + String email = it.next(); + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); + if (!emailMatcher.matches()) { + it.remove(); + } + } + // now return the Set (without duplicates) as a List return new ArrayList<>(accountMails); } @@ -62,6 +75,17 @@ public class ContactHelper { Set<String> accountMails = getAccountEmails(context); Set<String> names = getContactNamesFromEmails(context, accountMails); names.addAll(getMainProfileContactName(context)); + + // remove items that are an email + Iterator<String> it = names.iterator(); + while (it.hasNext()) { + String email = it.next(); + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); + if (emailMatcher.matches()) { + it.remove(); + } + } + return new ArrayList<>(names); } @@ -75,9 +99,7 @@ public class ContactHelper { final Account[] accounts = AccountManager.get(context).getAccounts(); final Set<String> emailSet = new HashSet<>(); for (Account account : accounts) { - if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { - emailSet.add(account.name); - } + emailSet.add(account.name); } return emailSet; } @@ -256,7 +278,7 @@ public class ContactHelper { } public static Bitmap loadPhotoByMasterKeyId(ContentResolver contentResolver, long masterKeyId, - boolean highRes) { + boolean highRes) { if (masterKeyId == -1) { return null; } |