diff options
author | Vincent Breitmoser <valodim@mugenguild.com> | 2015-05-11 17:28:34 +0200 |
---|---|---|
committer | Vincent Breitmoser <valodim@mugenguild.com> | 2015-05-11 17:28:34 +0200 |
commit | 20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f (patch) | |
tree | 258667acf6ea0c995b47195492d453c7459b31ca /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui | |
parent | 92ac2ded10548756922a4c22ebae0a19b8862426 (diff) | |
parent | 5c44f8400970de5943fd6c5e804dfa394f3deb01 (diff) | |
download | open-keychain-20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f.tar.gz open-keychain-20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f.tar.bz2 open-keychain-20a6c5ce8a0484cc0ef8f4c5ca1405f60e646e1f.zip |
Merge tag 'v3.2.1' into linked-identities
Version 3.2.1
Conflicts:
OpenKeychain/build.gradle
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java
OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
OpenKeychain/src/main/res/values/strings.xml
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
26 files changed, 367 insertions, 290 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 0b203614b..e0b728bd4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -20,7 +20,6 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import org.sufficientlysecure.keychain.R; @@ -84,7 +83,7 @@ public class CreateKeyActivity extends BaseNfcActivity { String nfcUserId = intent.getStringExtra(EXTRA_NFC_USER_ID); byte[] nfcAid = intent.getByteArrayExtra(EXTRA_NFC_AID); - Fragment frag2 = CreateKeyYubiImportFragment.createInstance( + Fragment frag2 = CreateKeyYubiKeyImportFragment.createInstance( nfcFingerprints, nfcAid, nfcUserId); loadFragment(frag2, FragAction.START); @@ -99,7 +98,7 @@ public class CreateKeyActivity extends BaseNfcActivity { if (mFirstTime) { setTitle(R.string.app_name); - setActionBarIcon(R.drawable.ic_launcher); + mToolbar.setNavigationIcon(null); mToolbar.setNavigationOnClickListener(null); } else { setTitle(R.string.title_manage_my_keys); @@ -131,7 +130,7 @@ public class CreateKeyActivity extends BaseNfcActivity { finish(); } catch (PgpKeyNotFoundException e) { - Fragment frag = CreateKeyYubiImportFragment.createInstance( + Fragment frag = CreateKeyYubiKeyImportFragment.createInstance( scannedFingerprints, nfcAid, userId); loadFragment(frag, FragAction.TO_RIGHT); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 85e2f8e9d..597f04d6b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -18,7 +18,6 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -44,18 +43,17 @@ import org.sufficientlysecure.keychain.ui.widget.EmailEditText; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; public class CreateKeyEmailFragment extends Fragment { + private CreateKeyActivity mCreateKeyActivity; + private EmailEditText mEmailEdit; + private ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels = new ArrayList<>(); + private EmailAdapter mEmailAdapter; - CreateKeyActivity mCreateKeyActivity; - EmailEditText mEmailEdit; - RecyclerView mEmailsRecyclerView; - View mBackButton; - View mNextButton; - - ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels; - - EmailAdapter mEmailAdapter; + // NOTE: Do not use more complicated pattern like defined in android.util.Patterns.EMAIL_ADDRESS + // EMAIL_ADDRESS fails for mails with umlauts for example + private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\S]+@[\\S]+\\.[a-z]+$"); /** * Creates new instance of this fragment @@ -73,14 +71,13 @@ public class CreateKeyEmailFragment extends Fragment { * 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) { + private boolean isMainEmailValid(EditText editText) { boolean output = true; - if (editText.getText().length() == 0) { - editText.setError(context.getString(R.string.create_key_empty)); + if (!checkEmail(editText.getText().toString(), false)) { + editText.setError(getString(R.string.create_key_empty)); editText.requestFocus(); output = false; } else { @@ -95,9 +92,9 @@ public class CreateKeyEmailFragment extends Fragment { 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); - mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails); + View backButton = view.findViewById(R.id.create_key_back_button); + View nextButton = view.findViewById(R.id.create_key_next_button); + RecyclerView emailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails); // initial values mEmailEdit.setText(mCreateKeyActivity.mEmail); @@ -106,29 +103,21 @@ public class CreateKeyEmailFragment extends Fragment { if (mCreateKeyActivity.mEmail == null) { mEmailEdit.requestFocus(); } - mBackButton.setOnClickListener(new View.OnClickListener() { + backButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT); } }); - mNextButton.setOnClickListener(new View.OnClickListener() { + nextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { nextClicked(); } }); - mEmailsRecyclerView.setHasFixedSize(true); - mEmailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - mEmailsRecyclerView.setItemAnimator(new DefaultItemAnimator()); - - // initial values - if (mAdditionalEmailModels == null) { - mAdditionalEmailModels = new ArrayList<>(); - if (mCreateKeyActivity.mAdditionalEmails != null) { - mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); - } - } + emailsRecyclerView.setHasFixedSize(true); + emailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + emailsRecyclerView.setItemAnimator(new DefaultItemAnimator()); if (mEmailAdapter == null) { mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() { @@ -137,13 +126,77 @@ public class CreateKeyEmailFragment extends Fragment { addEmail(); } }); + + if (mCreateKeyActivity.mAdditionalEmails != null) { + mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); + } } - mEmailsRecyclerView.setAdapter(mEmailAdapter); + emailsRecyclerView.setAdapter(mEmailAdapter); return view; } + /** + * Checks if a given email is valid + * + * @param email + * @param additionalEmail + * @return + */ + private boolean checkEmail(String email, boolean additionalEmail) { + // check for email format or if the user did any input + if (!isEmailFormatValid(email)) { + Notify.create(getActivity(), + getString(R.string.create_key_email_invalid_email), + Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this); + return false; + } + + // check for duplicated emails + if (!additionalEmail && isEmailDuplicatedInsideAdapter(email) || additionalEmail && + mEmailEdit.getText().length() > 0 && email.equals(mEmailEdit.getText().toString())) { + Notify.create(getActivity(), + getString(R.string.create_key_email_already_exists_text), + Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this); + return false; + } + + return true; + } + + /** + * Checks the email format + * Uses the default Android Email Pattern + * + * @param email + * @return + */ + private boolean isEmailFormatValid(String email) { + // check for email format or if the user did any input + return !(email.length() == 0 || !EMAIL_PATTERN.matcher(email).matches()); + } + + /** + * Checks for duplicated emails inside the additional email adapter. + * + * @param email + * @return + */ + private boolean isEmailDuplicatedInsideAdapter(String email) { + //check for duplicated emails inside the adapter + for (EmailAdapter.ViewModel model : mAdditionalEmailModels) { + if (email.equals(model.email)) { + return true; + } + } + + return false; + } + + /** + * Displays a dialog fragment for the user to input a valid email. + */ private void addEmail() { Handler returnHandler = new Handler() { @Override @@ -153,34 +206,17 @@ public class CreateKeyEmailFragment extends Fragment { String email = data.getString(AddEmailDialogFragment.MESSAGE_DATA_EMAIL); - if (email.length() > 0 && mEmailEdit.getText().length() > 0 && - email.equals(mEmailEdit.getText().toString())) { - Notify.create(getActivity(), - getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); - return; - } - //check for duplicated emails inside the adapter - for (EmailAdapter.ViewModel model : mAdditionalEmailModels) { - if (email.equals(model.email)) { - Notify.create(getActivity(), - getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); - return; - } + if (checkEmail(email, true)) { + // add new user id + mEmailAdapter.add(email); } - - // add new user id - mEmailAdapter.add(email); } } }; - // Create a new Messenger for the communication back Messenger messenger = new Messenger(returnHandler); AddEmailDialogFragment addEmailDialog = AddEmailDialogFragment.newInstance(messenger); - addEmailDialog.show(getActivity().getSupportFragmentManager(), "addEmailDialog"); } @@ -191,7 +227,7 @@ public class CreateKeyEmailFragment extends Fragment { } private void nextClicked() { - if (isEditTextNotEmpty(getActivity(), mEmailEdit)) { + if (isMainEmailValid(mEmailEdit)) { // save state mCreateKeyActivity.mEmail = mEmailEdit.getText().toString(); mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java index 32173edf7..3379e0a6d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java @@ -21,7 +21,6 @@ import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.text.Editable; import android.text.method.HideReturnsTransformationMethod; import android.text.method.PasswordTransformationMethod; import android.view.LayoutInflater; @@ -37,9 +36,6 @@ import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText; import org.sufficientlysecure.keychain.util.Passphrase; -import java.util.ArrayList; -import java.util.Arrays; - public class CreateKeyPassphraseFragment extends Fragment { // view @@ -111,8 +107,8 @@ public class CreateKeyPassphraseFragment extends Fragment { // initial values // TODO: using String here is unsafe... if (mCreateKeyActivity.mPassphrase != null) { - mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); - mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); + mPassphraseEdit.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); + mPassphraseEditAgain.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); } mPassphraseEdit.requestFocus(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java index 3f56949f5..1a844e6e4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2014-2015 Dominik Schürmann <dominik@dominikschuermann.de> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,37 +18,20 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; import android.support.v4.app.Fragment; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageButton; import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; -import org.sufficientlysecure.keychain.ui.dialog.AddEmailDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; -import org.sufficientlysecure.keychain.ui.widget.EmailEditText; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; -import java.util.ArrayList; -import java.util.List; - public class CreateKeyStartFragment extends Fragment { CreateKeyActivity mCreateKeyActivity; @@ -56,8 +39,8 @@ public class CreateKeyStartFragment extends Fragment { View mCreateKey; View mImportKey; View mYubiKey; - TextView mCancel; - public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012; + TextView mSkipOrCancel; + public static final int REQUEST_CODE_IMPORT_KEY = 0x00007012; /** * Creates new instance of this fragment @@ -79,12 +62,12 @@ public class CreateKeyStartFragment extends Fragment { mCreateKey = view.findViewById(R.id.create_key_create_key_button); mImportKey = view.findViewById(R.id.create_key_import_button); mYubiKey = view.findViewById(R.id.create_key_yubikey_button); - mCancel = (TextView) view.findViewById(R.id.create_key_cancel); + mSkipOrCancel = (TextView) view.findViewById(R.id.create_key_cancel); if (mCreateKeyActivity.mFirstTime) { - mCancel.setText(R.string.first_time_skip); + mSkipOrCancel.setText(R.string.first_time_skip); } else { - mCancel.setText(R.string.btn_do_not_save); + mSkipOrCancel.setText(R.string.btn_do_not_save); } mCreateKey.setOnClickListener(new View.OnClickListener() { @@ -98,7 +81,7 @@ public class CreateKeyStartFragment extends Fragment { mYubiKey.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - CreateKeyYubiWaitFragment frag = new CreateKeyYubiWaitFragment(); + CreateKeyYubiKeyWaitFragment frag = new CreateKeyYubiKeyWaitFragment(); mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT); } }); @@ -108,48 +91,48 @@ public class CreateKeyStartFragment extends Fragment { public void onClick(View v) { Intent intent = new Intent(mCreateKeyActivity, ImportKeysActivity.class); intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); - startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); + startActivityForResult(intent, REQUEST_CODE_IMPORT_KEY); } }); - mCancel.setOnClickListener(new View.OnClickListener() { + mSkipOrCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - finishSetup(null); + if (mCreateKeyActivity.mFirstTime) { + Preferences prefs = Preferences.getPreferences(mCreateKeyActivity); + prefs.setFirstTime(false); + Intent intent = new Intent(mCreateKeyActivity, MainActivity.class); + startActivity(intent); + mCreateKeyActivity.finish(); + } else { + // just finish activity and return data + mCreateKeyActivity.setResult(Activity.RESULT_CANCELED); + mCreateKeyActivity.finish(); + } } }); return view; } - - private void finishSetup(Intent srcData) { - if (mCreateKeyActivity.mFirstTime) { - Preferences prefs = Preferences.getPreferences(mCreateKeyActivity); - prefs.setFirstTime(false); - } - Intent intent = new Intent(mCreateKeyActivity, MainActivity.class); - // give intent through to display notify - if (srcData != null) { - intent.putExtras(srcData); - } - startActivity(intent); - mCreateKeyActivity.finish(); - } - - // workaround for https://code.google.com/p/android/issues/detail?id=61394 -// @Override -// public boolean onKeyDown(int keyCode, KeyEvent event) { -// return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event); -// } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) { + if (requestCode == REQUEST_CODE_IMPORT_KEY) { if (resultCode == Activity.RESULT_OK) { - finishSetup(data); + if (mCreateKeyActivity.mFirstTime) { + Preferences prefs = Preferences.getPreferences(mCreateKeyActivity); + prefs.setFirstTime(false); + Intent intent = new Intent(mCreateKeyActivity, MainActivity.class); + intent.putExtras(data); + startActivity(intent); + mCreateKeyActivity.finish(); + } else { + // just finish activity and return data + mCreateKeyActivity.setResult(Activity.RESULT_OK, data); + mCreateKeyActivity.finish(); + } } } else { Log.e(Constants.TAG, "No valid request code!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java index db62d53c5..4c7d1dfbd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiImportFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyImportFragment.java @@ -48,7 +48,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.Preferences; -public class CreateKeyYubiImportFragment extends Fragment implements NfcListenerFragment { +public class CreateKeyYubiKeyImportFragment extends Fragment implements NfcListenerFragment { private static final String ARG_FINGERPRINT = "fingerprint"; public static final String ARG_AID = "aid"; @@ -67,7 +67,7 @@ public class CreateKeyYubiImportFragment extends Fragment implements NfcListener public static Fragment createInstance(byte[] scannedFingerprints, byte[] nfcAid, String userId) { - CreateKeyYubiImportFragment frag = new CreateKeyYubiImportFragment(); + CreateKeyYubiKeyImportFragment frag = new CreateKeyYubiKeyImportFragment(); Bundle args = new Bundle(); args.putByteArray(ARG_FINGERPRINT, scannedFingerprints); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java index 579dddf79..0b8586c0a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java @@ -28,7 +28,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; -public class CreateKeyYubiWaitFragment extends Fragment { +public class CreateKeyYubiKeyWaitFragment extends Fragment { CreateKeyActivity mCreateKeyActivity; View mBackButton; 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 dce2386b5..c9a590c5b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesActivity.java @@ -25,7 +25,7 @@ import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.api.OpenKeychainIntents; +import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.ui.base.BaseActivity; import org.sufficientlysecure.keychain.util.Log; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index 6c1902af1..234362edc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -86,12 +86,12 @@ public class DecryptFilesFragment extends DecryptFragment { */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.decrypt_file_fragment, container, false); + View view = inflater.inflate(R.layout.decrypt_files_fragment, container, false); - mFilename = (TextView) view.findViewById(R.id.decrypt_file_filename); - mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_file_delete_after_decryption); - mDecryptButton = view.findViewById(R.id.decrypt_file_action_decrypt); - view.findViewById(R.id.decrypt_file_browse).setOnClickListener(new View.OnClickListener() { + mFilename = (TextView) view.findViewById(R.id.decrypt_files_filename); + mDeleteAfter = (CheckBox) view.findViewById(R.id.decrypt_files_delete_after_decryption); + mDecryptButton = view.findViewById(R.id.decrypt_files_action_decrypt); + view.findViewById(R.id.decrypt_files_browse).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { FileHelper.openDocument(DecryptFilesFragment.this, "*/*", REQUEST_CODE_INPUT); @@ -232,7 +232,6 @@ public class DecryptFilesFragment extends DecryptFragment { returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT); if (pgpResult.success()) { - switch (mCurrentCryptoOperation) { case KeychainIntentService.ACTION_DECRYPT_METADATA: { askForOutputFilename(pgpResult.getDecryptMetadata().getFilename()); @@ -264,9 +263,8 @@ public class DecryptFilesFragment extends DecryptFragment { break; } } - } else { - pgpResult.createNotify(getActivity()).show(); } + pgpResult.createNotify(getActivity()).show(DecryptFilesFragment.this); } } @@ -309,7 +307,7 @@ public class DecryptFilesFragment extends DecryptFragment { } @Override - protected void onVerifyLoaded(boolean verified) { + protected void onVerifyLoaded(boolean hideErrorOverlay) { } } 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 9c51893ce..e9bc42a4d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -30,6 +30,7 @@ import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; import android.view.View; +import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -55,24 +56,24 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.util.Preferences; - public abstract class DecryptFragment extends CryptoOperationFragment implements LoaderManager.LoaderCallbacks<Cursor> { public static final int LOADER_ID_UNIFIED = 0; protected LinearLayout mResultLayout; - protected ImageView mEncryptionIcon; protected TextView mEncryptionText; protected ImageView mSignatureIcon; protected TextView mSignatureText; - protected View mSignatureLayout; protected TextView mSignatureName; protected TextView mSignatureEmail; protected TextView mSignatureAction; + private LinearLayout mContentLayout; + private LinearLayout mErrorOverlayLayout; + private OpenPgpSignatureResult mSignatureResult; @Override @@ -82,7 +83,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements // NOTE: These views are inside the activity! mResultLayout = (LinearLayout) getActivity().findViewById(R.id.result_main_layout); mResultLayout.setVisibility(View.GONE); - mEncryptionIcon = (ImageView) getActivity().findViewById(R.id.result_encryption_icon); mEncryptionText = (TextView) getActivity().findViewById(R.id.result_encryption_text); mSignatureIcon = (ImageView) getActivity().findViewById(R.id.result_signature_icon); @@ -92,6 +92,17 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements mSignatureEmail = (TextView) getActivity().findViewById(R.id.result_signature_email); mSignatureAction = (TextView) getActivity().findViewById(R.id.result_signature_action); + // Overlay + mContentLayout = (LinearLayout) view.findViewById(R.id.decrypt_content); + mErrorOverlayLayout = (LinearLayout) view.findViewById(R.id.decrypt_error_overlay); + Button vErrorOverlayButton = (Button) view.findViewById(R.id.decrypt_error_overlay_button); + vErrorOverlayButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + } + }); } private void lookupUnknownKey(long unknownKeyId) { @@ -113,12 +124,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements final ImportKeyResult result = returnData.getParcelable(OperationResult.EXTRA_RESULT); - // if (!result.success()) { - result.createNotify(getActivity()).show(); - // } + result.createNotify(getActivity()).show(); getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, DecryptFragment.this); - } } }; @@ -153,7 +161,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); getActivity().startService(intent); - } private void showKey(long keyId) { @@ -191,6 +198,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements getLoaderManager().destroyLoader(LOADER_ID_UNIFIED); + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + onVerifyLoaded(true); return; @@ -205,7 +215,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this); - } private void setSignatureLayoutVisibility(int visibility) { @@ -228,8 +237,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements KeychainContract.KeyRings._ID, KeychainContract.KeyRings.MASTER_KEY_ID, KeychainContract.KeyRings.USER_ID, - KeychainContract.KeyRings.IS_REVOKED, - KeychainContract.KeyRings.IS_EXPIRED, KeychainContract.KeyRings.VERIFIED, KeychainContract.KeyRings.HAS_ANY_SECRET, }; @@ -237,10 +244,8 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements @SuppressWarnings("unused") 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_IS_EXPIRED = 4; - static final int INDEX_VERIFIED = 5; - static final int INDEX_HAS_ANY_SECRET = 6; + static final int INDEX_VERIFIED = 3; + static final int INDEX_HAS_ANY_SECRET = 4; @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { @@ -282,8 +287,10 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements getActivity(), mSignatureResult.getKeyId())); } - boolean isRevoked = data.getInt(INDEX_IS_REVOKED) != 0; - boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0; + // NOTE: Don't use revoked and expired fields from database, they don't show + // revoked/expired subkeys + boolean isRevoked = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED; + boolean isExpired = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0; @@ -294,6 +301,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements setSignatureLayoutVisibility(View.VISIBLE); setShowAction(signatureKeyId); + mErrorOverlayLayout.setVisibility(View.VISIBLE); + mContentLayout.setVisibility(View.GONE); + onVerifyLoaded(false); } else if (isExpired) { @@ -303,6 +313,22 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements setSignatureLayoutVisibility(View.VISIBLE); setShowAction(signatureKeyId); + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + + onVerifyLoaded(true); + + } else if (isYours) { + + mSignatureText.setText(R.string.decrypt_result_signature_secret); + KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED); + + setSignatureLayoutVisibility(View.VISIBLE); + setShowAction(signatureKeyId); + + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + onVerifyLoaded(true); } else if (isYours) { @@ -322,6 +348,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements setSignatureLayoutVisibility(View.VISIBLE); setShowAction(signatureKeyId); + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + onVerifyLoaded(true); } else { @@ -331,6 +360,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements setSignatureLayoutVisibility(View.VISIBLE); setShowAction(signatureKeyId); + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + onVerifyLoaded(true); } @@ -344,7 +376,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } setSignatureLayoutVisibility(View.GONE); - } private void showUnknownKeyStatus() { @@ -388,6 +419,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } }); + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); + onVerifyLoaded(true); break; @@ -399,6 +433,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements setSignatureLayoutVisibility(View.GONE); + mErrorOverlayLayout.setVisibility(View.VISIBLE); + mContentLayout.setVisibility(View.GONE); + onVerifyLoaded(false); break; } @@ -407,6 +444,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } - protected abstract void onVerifyLoaded(boolean verified); + protected abstract void onVerifyLoaded(boolean hideErrorOverlay); } 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 728e3ba41..e2eba3947 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de> + * Copyright (C) 2012-2015 Dominik Schürmann <dominik@dominikschuermann.de> * Copyright (C) 2010-2014 Thialfihar <thi@thialfihar.org> * * This program is free software: you can redistribute it and/or modify @@ -23,16 +23,16 @@ import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.view.View; +import android.widget.Toast; 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.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.SingletonResult; import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.ui.base.BaseActivity; -import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import java.util.regex.Matcher; @@ -138,8 +138,6 @@ public class DecryptTextActivity extends BaseActivity { /** * Handles all actions with this intent - * - * @param intent */ private void handleActions(Bundle savedInstanceState, Intent intent) { String action = intent.getAction(); @@ -162,10 +160,14 @@ public class DecryptTextActivity extends BaseActivity { if (sharedText != null) { loadFragment(savedInstanceState, sharedText); } else { - Notify.create(this, R.string.error_invalid_data, Notify.Style.ERROR).show(); + Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!"); + Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show(); + finish(); } } else { Log.e(Constants.TAG, "ACTION_SEND received non-plaintext, this should not happen in this activity!"); + Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show(); + finish(); } } else if (ACTION_DECRYPT_TEXT.equals(action)) { Log.d(Constants.TAG, "ACTION_DECRYPT_TEXT"); @@ -176,7 +178,9 @@ public class DecryptTextActivity extends BaseActivity { if (extraText != null) { loadFragment(savedInstanceState, extraText); } else { - Notify.create(this, R.string.error_invalid_data, Notify.Style.ERROR).show(); + Log.e(Constants.TAG, "EXTRA_TEXT does not contain PGP content!"); + Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show(); + finish(); } } else if (ACTION_DECRYPT_FROM_CLIPBOARD.equals(action)) { Log.d(Constants.TAG, "ACTION_DECRYPT_FROM_CLIPBOARD"); @@ -191,6 +195,7 @@ public class DecryptTextActivity extends BaseActivity { } } else if (ACTION_DECRYPT_TEXT.equals(action)) { Log.e(Constants.TAG, "Include the extra 'text' in your Intent!"); + Toast.makeText(this, R.string.error_invalid_data, Toast.LENGTH_LONG).show(); finish(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index 6f576a112..381da6f0d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -50,8 +50,6 @@ public class DecryptTextFragment extends DecryptFragment { public static final String ARG_CIPHERTEXT = "ciphertext"; // view - private LinearLayout mValidLayout; - private LinearLayout mInvalidLayout; private TextView mText; // model @@ -78,19 +76,8 @@ public class DecryptTextFragment extends DecryptFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false); - mValidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_valid); - mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid); mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); - Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button); - vInvalidButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mInvalidLayout.setVisibility(View.GONE); - mValidLayout.setVisibility(View.VISIBLE); - } - }); - return view; } @@ -203,7 +190,6 @@ public class DecryptTextFragment extends DecryptFragment { returnData.getParcelable(DecryptVerifyResult.EXTRA_RESULT); if (pgpResult.success()) { - byte[] decryptedMessage = returnData .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); String displayMessage; @@ -219,15 +205,12 @@ public class DecryptTextFragment extends DecryptFragment { } mText.setText(displayMessage); - pgpResult.createNotify(getActivity()).show(); - // display signature result in activity loadVerifyResult(pgpResult); - } else { - pgpResult.createNotify(getActivity()).show(); // TODO: show also invalid layout with different text? } + pgpResult.createNotify(getActivity()).show(DecryptTextFragment.this); } } }; @@ -244,18 +227,8 @@ public class DecryptTextFragment extends DecryptFragment { } @Override - protected void onVerifyLoaded(boolean verified) { - - mShowMenuOptions = verified; + protected void onVerifyLoaded(boolean hideErrorOverlay) { + mShowMenuOptions = hideErrorOverlay; getActivity().supportInvalidateOptionsMenu(); - - if (verified) { - mInvalidLayout.setVisibility(View.GONE); - mValidLayout.setVisibility(View.VISIBLE); - } else { - mInvalidLayout.setVisibility(View.VISIBLE); - mValidLayout.setVisibility(View.GONE); - } - } } 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 64e908b1a..b3ec60890 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -28,7 +28,7 @@ import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.api.OpenKeychainIntents; +import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.ui.base.BaseActivity; import org.sufficientlysecure.keychain.util.Passphrase; 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 dd6dd6594..52d098adc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptTextActivity.java @@ -26,7 +26,7 @@ import android.view.View; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.api.OpenKeychainIntents; +import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.ui.base.BaseActivity; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index 5d9950db6..4cba62d5b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -30,16 +30,16 @@ import android.view.ViewGroup; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.api.OpenKeychainIntents; +import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity; import org.sufficientlysecure.keychain.service.CloudImportService; import org.sufficientlysecure.keychain.service.ServiceProgressHandler; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; -import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; @@ -346,60 +346,66 @@ public class ImportKeysActivity extends BaseNfcActivity { mListFragment.loadNew(loaderState); } + private void handleMessage(Message message) { + if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) { + // get returned data bundle + Bundle returnData = message.getData(); + if (returnData == null) { + return; + } + final ImportKeyResult result = + returnData.getParcelable(OperationResult.EXTRA_RESULT); + if (result == null) { + Log.e(Constants.TAG, "result == null"); + return; + } + + if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction()) + || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { + Intent intent = new Intent(); + intent.putExtra(ImportKeyResult.EXTRA_RESULT, result); + ImportKeysActivity.this.setResult(RESULT_OK, intent); + ImportKeysActivity.this.finish(); + return; + } + if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) { + ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData); + ImportKeysActivity.this.finish(); + return; + } + + result.createNotify(ImportKeysActivity.this) + .show((ViewGroup) findViewById(R.id.import_snackbar)); + } + } + /** * Import keys with mImportData */ public void importKeys() { - // Message is received after importing is done in CloudImportService - ServiceProgressHandler saveHandler = new ServiceProgressHandler( - this, - getString(R.string.progress_importing), - ProgressDialog.STYLE_HORIZONTAL, - true, - ProgressDialogFragment.ServiceType.CLOUD_IMPORT) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == MessageStatus.OKAY.ordinal()) { - // get returned data bundle - Bundle returnData = message.getData(); - if (returnData == null) { - return; - } - final ImportKeyResult result = - returnData.getParcelable(OperationResult.EXTRA_RESULT); - if (result == null) { - Log.e(Constants.TAG, "result == null"); - return; - } - - if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction()) - || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) { - Intent intent = new Intent(); - intent.putExtra(ImportKeyResult.EXTRA_RESULT, result); - ImportKeysActivity.this.setResult(RESULT_OK, intent); - ImportKeysActivity.this.finish(); - return; - } - if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) { - ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData); - ImportKeysActivity.this.finish(); - return; - } - - result.createNotify(ImportKeysActivity.this) - .show((ViewGroup) findViewById(R.id.import_snackbar)); - } - } - }; - ImportKeysListFragment.LoaderState ls = mListFragment.getLoaderState(); if (ls instanceof ImportKeysListFragment.BytesLoaderState) { Log.d(Constants.TAG, "importKeys started"); + ServiceProgressHandler serviceHandler = new ServiceProgressHandler( + this, + getString(R.string.progress_importing), + ProgressDialog.STYLE_HORIZONTAL, + true, + ProgressDialogFragment.ServiceType.KEYCHAIN_INTENT) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + ImportKeysActivity.this.handleMessage(message); + } + }; + + // TODO: Currently not using CloudImport here due to https://github.com/open-keychain/open-keychain/issues/1221 // Send all information needed to service to import key in other thread - Intent intent = new Intent(this, CloudImportService.class); + Intent intent = new Intent(this, KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING); // fill values for this action Bundle data = new Bundle(); @@ -417,14 +423,14 @@ public class ImportKeysActivity extends BaseNfcActivity { new ParcelableFileCache<>(this, "key_import.pcl"); cache.writeCache(selectedEntries); - intent.putExtra(CloudImportService.EXTRA_DATA, data); + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(CloudImportService.EXTRA_MESSENGER, messenger); + Messenger messenger = new Messenger(serviceHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); // show progress dialog - saveHandler.showProgressDialog(this); + serviceHandler.showProgressDialog(this); // start service with intent startService(intent); @@ -436,6 +442,20 @@ public class ImportKeysActivity extends BaseNfcActivity { } else if (ls instanceof ImportKeysListFragment.CloudLoaderState) { ImportKeysListFragment.CloudLoaderState sls = (ImportKeysListFragment.CloudLoaderState) ls; + ServiceProgressHandler serviceHandler = new ServiceProgressHandler( + this, + getString(R.string.progress_importing), + ProgressDialog.STYLE_HORIZONTAL, + true, + ProgressDialogFragment.ServiceType.CLOUD_IMPORT) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + ImportKeysActivity.this.handleMessage(message); + } + }; + // Send all information needed to service to query keys in other thread Intent intent = new Intent(this, CloudImportService.class); @@ -460,11 +480,11 @@ public class ImportKeysActivity extends BaseNfcActivity { intent.putExtra(CloudImportService.EXTRA_DATA, data); // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); + Messenger messenger = new Messenger(serviceHandler); intent.putExtra(CloudImportService.EXTRA_MESSENGER, messenger); // show progress dialog - saveHandler.showProgressDialog(this); + serviceHandler.showProgressDialog(this); // start service with intent startService(intent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java index 29f2511a0..dc8752d1a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysProxyActivity.java @@ -37,7 +37,7 @@ import com.google.zxing.integration.android.IntentResult; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.api.OpenKeychainIntents; +import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; 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 8c4ea1884..d8c3e0350 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -70,7 +70,6 @@ import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter; import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.service.ServiceProgressHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.Notify; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java index 05cf64092..f571ba1e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -64,7 +64,7 @@ public class MainActivity extends AppCompatActivity implements FabContainer { transaction.replace(R.id.main_fragment_container, mainFragment); transaction.commit(); - mToolbar = (Toolbar) findViewById(R.id.activity_main_toolbar); + mToolbar = (Toolbar) findViewById(R.id.toolbar); mToolbar.setTitle(R.string.app_name); setSupportActionBar(mToolbar); 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 6bd3a9303..fde0f62fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyAdvShareFragment.java @@ -26,6 +26,7 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; +import android.os.ParcelFileDescriptor; import android.support.v4.app.ActivityCompat; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; @@ -42,19 +43,24 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; +import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.QrCodeUtils; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.NfcHelper; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; import java.io.IOException; +import java.io.FileNotFoundException; public class ViewKeyAdvShareFragment extends LoaderFragment implements @@ -175,11 +181,11 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements boolean toClipboard) { try { String content; + byte[] fingerprintData = (byte[]) providerHelper.getGenericData( + KeyRings.buildUnifiedKeyRingUri(dataUri), + Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); if (fingerprintOnly) { - byte[] data = (byte[]) providerHelper.getGenericData( - KeyRings.buildUnifiedKeyRingUri(dataUri), - Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); - String fingerprint = KeyFormattingUtils.convertFingerprintToHex(data); + String fingerprint = KeyFormattingUtils.convertFingerprintToHex(fingerprintData); if (!toClipboard) { content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; } else { @@ -213,13 +219,48 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements Intent sendIntent = new Intent(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, content); sendIntent.setType("text/plain"); + String title; if (fingerprintOnly) { title = getResources().getString(R.string.title_share_fingerprint_with); } else { title = getResources().getString(R.string.title_share_key); } - startActivity(Intent.createChooser(sendIntent, title)); + Intent shareChooser = Intent.createChooser(sendIntent, title); + + // Bluetooth Share will convert text/plain sent via EXTRA_TEXT to HTML + // Add replacement extra to send a text/plain file instead. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + try { + String primaryUserId = UncachedKeyRing.decodeFromData(content.getBytes()). + getPublicKey().getPrimaryUserIdWithFallback(); + + TemporaryStorageProvider shareFileProv = new TemporaryStorageProvider(); + Uri contentUri = TemporaryStorageProvider.createFile(getActivity(), + primaryUserId + Constants.FILE_EXTENSION_ASC); + + BufferedWriter contentWriter = new BufferedWriter(new OutputStreamWriter( + new ParcelFileDescriptor.AutoCloseOutputStream( + shareFileProv.openFile(contentUri, "w")))); + contentWriter.write(content); + contentWriter.close(); + + // create replacement extras inside try{}: + // if file creation fails, just don't add the replacements + Bundle replacements = new Bundle(); + shareChooser.putExtra(Intent.EXTRA_REPLACEMENT_EXTRAS, replacements); + + Bundle bluetoothExtra = new Bundle(sendIntent.getExtras()); + replacements.putBundle("com.android.bluetooth", bluetoothExtra); + + bluetoothExtra.putParcelable(Intent.EXTRA_STREAM, contentUri); + } catch (FileNotFoundException e) { + Log.e(Constants.TAG, "error creating temporary Bluetooth key share file!", e); + Notify.create(getActivity(), R.string.error_bluetooth_file, Notify.Style.ERROR).show(); + } + } + + startActivity(shareChooser); } } catch (PgpGeneralException | IOException e) { Log.e(Constants.TAG, "error processing key!", e); @@ -379,4 +420,4 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements } -}
\ No newline at end of file +} 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 d9b1fa279..c01a94286 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -202,6 +202,8 @@ public class ViewKeyFragment extends LoaderFragment implements * In the case of a secret key, "me" (own profile) contact details are loaded. */ private void loadLinkedSystemContact(final long contactId) { + // contact doesn't exist, stop + if(contactId == -1) return; final Context context = mSystemContactName.getContext(); final ContentResolver resolver = context.getContentResolver(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java index f09dc1a4f..3dbae09b6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java @@ -18,15 +18,12 @@ package org.sufficientlysecure.keychain.ui.adapter; -import java.util.Calendar; import java.util.Date; -import java.util.TimeZone; import android.content.Context; import android.database.Cursor; import android.graphics.PorterDuff; import android.support.v4.widget.CursorAdapter; -import android.text.format.DateFormat; import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; @@ -176,9 +173,8 @@ public class KeyAdapter extends CursorAdapter { | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH); - - mCreationDate.setText(context.getString(R.string.label_creation, - dateTime)); + mCreationDate.setText(context.getString(R.string.label_key_created, + dateTime)); mCreationDate.setVisibility(View.VISIBLE); } else { mCreationDate.setVisibility(View.GONE); @@ -281,20 +277,6 @@ public class KeyAdapter extends CursorAdapter { } } - public boolean hasDuplicate() { - return mHasDuplicate; - } - - public String getCreationDate(Context context) { - Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(mCreation); - // convert from UTC to time zone of device - creationCal.setTimeZone(TimeZone.getDefault()); - - return context.getString(R.string.label_creation) + ": " - + DateFormat.getDateFormat(context).format(creationCal.getTime()); - } - } } 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 1ccb910d0..6bbf41a88 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 @@ -140,8 +140,7 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter { | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH); - - h.creation.setText(context.getString(R.string.label_creation, dateTime)); + h.creation.setText(context.getString(R.string.label_key_created, dateTime)); h.creation.setVisibility(View.VISIBLE); } else { h.creation.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java index 5d5ca533e..5b91b9d37 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java @@ -112,9 +112,11 @@ public class AddEmailDialogFragment extends DialogFragment implements OnEditorAc mEmail.post(new Runnable() { @Override public void run() { - InputMethodManager imm = (InputMethodManager) getActivity() - .getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(mEmail, InputMethodManager.SHOW_IMPLICIT); + if(getActivity() != null) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mEmail, InputMethodManager.SHOW_IMPLICIT); + } } }); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java index b58f584c8..af9d175ff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ProgressDialogFragment.java @@ -94,12 +94,12 @@ public class ProgressDialogFragment extends DialogFragment { /** Updates progress of dialog */ public void setProgress(String message, int progress, int max) { - if (mIsCancelled) { + ProgressDialog dialog = (ProgressDialog) getDialog(); + + if (mIsCancelled || dialog == null) { return; } - ProgressDialog dialog = (ProgressDialog) getDialog(); - dialog.setMessage(message); dialog.setProgress(progress); dialog.setMax(max); 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 ac7e7a487..3d98034d2 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 @@ -216,7 +216,16 @@ public class KeyFormattingUtils { * @return */ public static String convertFingerprintToHex(byte[] fingerprint) { - return Hex.toHexString(fingerprint, 0, 20).toLowerCase(Locale.ENGLISH); + // NOTE: Even though v3 keys are not imported we need to support both fingerprints for + // display/comparison before import + // Also better cut of unneeded parts, e.g., for fingerprints returned from YubiKeys + if (fingerprint.length < 20) { + // v3 key fingerprint with 128 bit (MD5) + return Hex.toHexString(fingerprint, 0, 16).toLowerCase(Locale.ENGLISH); + } else { + // v4 key fingerprint with 160 bit (SHA1) + return Hex.toHexString(fingerprint, 0, 20).toLowerCase(Locale.ENGLISH); + } } public static long getKeyIdFromFingerprint(byte[] fingerprint) { 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 525bc26ca..63a1aade9 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 @@ -136,7 +136,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView where += " AND " + KeyRings.USER_ID + " LIKE ?"; return new CursorLoader(getContext(), baseUri, KeyAdapter.PROJECTION, where, - new String[] { "%" + query + "%" }, null); + new String[]{"%" + query + "%"}, null); } mAdapter.setSearchQuery(null); @@ -156,7 +156,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView @Override public void showDropDown() { - if (mAdapter.getCursor().isClosed()) { + if (mAdapter == null || mAdapter.getCursor() == null || mAdapter.getCursor().isClosed()) { return; } super.showDropDown(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index 8cf15a75a..61b7c718b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -26,7 +26,7 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.support.v4.widget.CursorAdapter; import android.support.v7.widget.AppCompatSpinner; -import android.text.format.DateFormat; +import android.text.format.DateUtils; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; @@ -42,10 +42,6 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.util.Log; -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - /** * Use AppCompatSpinner from AppCompat lib instead of Spinner. Fixes white dropdown icon. * Related: http://stackoverflow.com/a/27713090 @@ -164,14 +160,14 @@ public abstract class KeySpinner extends AppCompatSpinner implements LoaderManag boolean duplicate = cursor.getLong(mIndexDuplicate) > 0; if (duplicate) { - Date creationDate = new Date(cursor.getLong(mIndexCreationDate) * 1000); - Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(creationDate); - // convert from UTC to time zone of device - creationCal.setTimeZone(TimeZone.getDefault()); - - vDuplicate.setText(context.getString(R.string.label_creation) + ": " - + DateFormat.getDateFormat(context).format(creationCal.getTime())); + String dateTime = DateUtils.formatDateTime(context, + cursor.getLong(mIndexCreationDate) * 1000, + DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_TIME + | DateUtils.FORMAT_SHOW_YEAR + | DateUtils.FORMAT_ABBREV_MONTH); + + vDuplicate.setText(context.getString(R.string.label_key_created, dateTime)); vDuplicate.setVisibility(View.VISIBLE); } else { vDuplicate.setVisibility(View.GONE); |