diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui')
30 files changed, 1226 insertions, 1421 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java index 7ac229b91..467e0c14a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyActivity.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui; import android.app.ProgressDialog; import android.content.Intent; import android.database.Cursor; +import android.graphics.PorterDuff; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -37,12 +38,11 @@ import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.ImageView; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; @@ -52,10 +52,12 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.util.ArrayList; @@ -64,7 +66,8 @@ import java.util.ArrayList; */ public class CertifyKeyActivity extends ActionBarActivity implements SelectSecretKeyLayoutFragment.SelectSecretKeyCallback, LoaderManager.LoaderCallbacks<Cursor> { - private View mSignButton; + private View mCertifyButton; + private ImageView mActionCertifyImage; private CheckBox mUploadKeyCheckbox; private Spinner mSelectKeyserverSpinner; @@ -88,10 +91,19 @@ public class CertifyKeyActivity extends ActionBarActivity implements mSelectKeyFragment = (SelectSecretKeyLayoutFragment) getSupportFragmentManager() .findFragmentById(R.id.sign_key_select_key_fragment); + mSelectKeyserverSpinner = (Spinner) findViewById(R.id.upload_key_keyserver); + mUploadKeyCheckbox = (CheckBox) findViewById(R.id.sign_key_upload_checkbox); + mCertifyButton = findViewById(R.id.certify_key_certify_button); + mActionCertifyImage = (ImageView) findViewById(R.id.certify_key_action_certify_image); + mUserIds = (ListView) findViewById(R.id.view_key_user_ids); + + // make certify image gray, like action icons + mActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light), + PorterDuff.Mode.SRC_IN); + mSelectKeyFragment.setCallback(this); mSelectKeyFragment.setFilterCertify(true); - mSelectKeyserverSpinner = (Spinner) findViewById(R.id.upload_key_keyserver); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, Preferences.getPreferences(this) .getKeyServers() @@ -99,7 +111,6 @@ public class CertifyKeyActivity extends ActionBarActivity implements adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mSelectKeyserverSpinner.setAdapter(adapter); - mUploadKeyCheckbox = (CheckBox) findViewById(R.id.sign_key_upload_checkbox); if (!mUploadKeyCheckbox.isChecked()) { mSelectKeyserverSpinner.setEnabled(false); } else { @@ -118,16 +129,17 @@ public class CertifyKeyActivity extends ActionBarActivity implements } }); - mSignButton = findViewById(R.id.sign_key_sign_button); - mSignButton.setOnClickListener(new OnClickListener() { + mCertifyButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mPubKeyId != 0) { if (mMasterKeyId == 0) { mSelectKeyFragment.setError(getString(R.string.select_key_to_certify)); + Notify.showNotify(CertifyKeyActivity.this, getString(R.string.select_key_to_certify), + Notify.Style.ERROR); } else { - initiateSigning(); + initiateCertifying(); } } } @@ -141,7 +153,6 @@ public class CertifyKeyActivity extends ActionBarActivity implements } Log.e(Constants.TAG, "uri: " + mDataUri); - mUserIds = (ListView) findViewById(R.id.view_key_user_ids); mUserIdsAdapter = new UserIdsAdapter(this, null, 0, true); mUserIds.setAdapter(mUserIdsAdapter); @@ -218,7 +229,7 @@ public class CertifyKeyActivity extends ActionBarActivity implements /** * handles the UI bits of the signing process on the UI thread */ - private void initiateSigning() { + private void initiateCertifying() { // get the user's passphrase for this key (if required) String passphrase = PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId); if (passphrase == null) { @@ -227,27 +238,27 @@ public class CertifyKeyActivity extends ActionBarActivity implements @Override public void handleMessage(Message message) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - startSigning(); + startCertifying(); } } - }); + } + ); // bail out; need to wait until the user has entered the passphrase before trying again return; } else { - startSigning(); + startCertifying(); } } /** * kicks off the actual signing process on a background thread */ - private void startSigning() { - + private void startCertifying() { // Bail out if there is not at least one user id selected ArrayList<String> userIds = mUserIdsAdapter.getSelectedUserIds(); if (userIds.isEmpty()) { - AppMsg.makeText(CertifyKeyActivity.this, "No User IDs to sign selected!", - AppMsg.STYLE_ALERT).show(); + Notify.showNotify(CertifyKeyActivity.this, "No identities selected!", + Notify.Style.ERROR); return; } @@ -267,15 +278,15 @@ public class CertifyKeyActivity extends ActionBarActivity implements // Message is received after signing is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - getString(R.string.progress_signing), ProgressDialog.STYLE_SPINNER) { + getString(R.string.progress_certifying), ProgressDialog.STYLE_SPINNER) { public void handleMessage(Message message) { // handle messages by standard KeychainIntentServiceHandler first super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - AppMsg.makeText(CertifyKeyActivity.this, R.string.key_certify_success, - AppMsg.STYLE_INFO).show(); + Notify.showNotify(CertifyKeyActivity.this, R.string.key_certify_success, + Notify.Style.INFO); // check if we need to send the key to the server or not if (mUploadKeyCheckbox.isChecked()) { @@ -321,14 +332,16 @@ public class CertifyKeyActivity extends ActionBarActivity implements // Message is received after uploading is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) { + getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) { public void handleMessage(Message message) { // handle messages by standard KeychainIntentServiceHandler first super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - AppMsg.makeText(CertifyKeyActivity.this, R.string.key_send_success, - AppMsg.STYLE_INFO).show(); + Intent intent = new Intent(); + intent.putExtra(OperationResultParcel.EXTRA_RESULT, message.getData()); + Notify.showNotify(CertifyKeyActivity.this, R.string.key_send_success, + Notify.Style.INFO); setResult(RESULT_OK); finish(); 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 d2073d9a7..534ac5811 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -17,171 +17,69 @@ package org.sufficientlysecure.keychain.ui; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; import android.support.v7.app.ActionBarActivity; -import android.text.Editable; -import android.text.TextWatcher; -import android.util.Patterns; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.AutoCompleteTextView; -import android.widget.Button; -import android.widget.EditText; -import org.spongycastle.bcpg.sig.KeyFlags; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ContactHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel; - -import java.util.regex.Matcher; public class CreateKeyActivity extends ActionBarActivity { - AutoCompleteTextView nameEdit; - AutoCompleteTextView emailEdit; - EditText passphraseEdit; - Button createButton; + public static final String EXTRA_NAME = "name"; + public static final String EXTRA_EMAIL = "email"; + + public static final int FRAG_ACTION_START = 0; + public static final int FRAG_ACTION_TO_RIGHT = 1; + public static final int FRAG_ACTION_TO_LEFT = 2; @Override - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.create_key_activity); - nameEdit = (AutoCompleteTextView) findViewById(R.id.name); - emailEdit = (AutoCompleteTextView) findViewById(R.id.email); - passphraseEdit = (EditText) findViewById(R.id.passphrase); - createButton = (Button) findViewById(R.id.create_key_button); - - emailEdit.setThreshold(1); // Start working from first character - emailEdit.setAdapter( - new ArrayAdapter<String> - (this, android.R.layout.simple_spinner_dropdown_item, - ContactHelper.getPossibleUserEmails(this) - ) - ); - emailEdit.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - } - - @Override - public void afterTextChanged(Editable editable) { - String email = editable.toString(); - if (email.length() > 0) { - Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); - if (emailMatcher.matches()) { - emailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_ok, 0); - } else { - emailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, - R.drawable.uid_mail_bad, 0); - } - } else { - // remove drawable if email is empty - emailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - } - }); - nameEdit.setThreshold(1); // Start working from first character - nameEdit.setAdapter( - new ArrayAdapter<String> - (this, android.R.layout.simple_spinner_dropdown_item, - ContactHelper.getPossibleUserNames(this) - ) - ); - - createButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - createKeyCheck(); - } - }); - + // pass extras into fragment + CreateKeyInputFragment frag = + CreateKeyInputFragment.newInstance( + getIntent().getStringExtra(EXTRA_NAME), + getIntent().getStringExtra(EXTRA_EMAIL) + ); + loadFragment(null, frag, FRAG_ACTION_START); } - private void createKeyCheck() { - if (isEditTextNotEmpty(this, nameEdit) - && isEditTextNotEmpty(this, emailEdit) - && isEditTextNotEmpty(this, passphraseEdit)) { - createKey(); + public void loadFragment(Bundle savedInstanceState, Fragment fragment, int action) { + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; } - } - - private void createKey() { - Intent intent = new Intent(this, KeychainIntentService.class); - intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); - - // Message is received after importing is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( - this, - getString(R.string.progress_importing), - ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - CreateKeyActivity.this.finish(); - } - } - }; + // Add the fragment to the 'fragment_container' FrameLayout + // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + switch (action) { + case FRAG_ACTION_START: + transaction.setCustomAnimations(0, 0); + transaction.replace(R.id.create_key_fragment_container, fragment) + .commitAllowingStateLoss(); + break; + case FRAG_ACTION_TO_LEFT: + getSupportFragmentManager().popBackStackImmediate(); + break; + case FRAG_ACTION_TO_RIGHT: + transaction.setCustomAnimations(R.anim.frag_slide_in_from_right, R.anim.frag_slide_out_to_left, + R.anim.frag_slide_in_from_left, R.anim.frag_slide_out_to_right); + transaction.addToBackStack(null); + transaction.replace(R.id.create_key_fragment_container, fragment) + .commitAllowingStateLoss(); + break; - // fill values for this action - Bundle data = new Bundle(); - - SaveKeyringParcel parcel = new SaveKeyringParcel(); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.CERTIFY_OTHER, null)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); - parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null)); - String userId = nameEdit.getText().toString() + " <" + emailEdit.getText().toString() + ">"; - parcel.mAddUserIds.add(userId); - parcel.mNewPassphrase = passphraseEdit.getText().toString(); - - // get selected key entries - data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, parcel); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - saveHandler.showProgressDialog(this); - - startService(intent); - } - - /** - * 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("empty!"); - editText.requestFocus(); - output = false; - } else { - editText.setError(null); } - - return output; + // do it immediately! + getSupportFragmentManager().executePendingTransactions(); } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java new file mode 100644 index 000000000..f9ed16cba --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyFinalFragment.java @@ -0,0 +1,249 @@ +/* + * 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.net.Uri; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.TextView; + +import org.spongycastle.bcpg.sig.KeyFlags; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.OperationResultParcel; +import org.sufficientlysecure.keychain.service.OperationResults; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.util.Notify; + +public class CreateKeyFinalFragment extends Fragment { + + CreateKeyActivity mCreateKeyActivity; + + TextView mNameEdit; + TextView mEmailEdit; + CheckBox mUploadCheckbox; + View mBackButton; + View mCreateButton; + + public static final String ARG_NAME = "name"; + public static final String ARG_EMAIL = "email"; + public static final String ARG_PASSPHRASE = "passphrase"; + + String mName; + String mEmail; + String mPassphrase; + + /** + * Creates new instance of this fragment + */ + public static CreateKeyFinalFragment newInstance(String name, String email, String passphrase) { + CreateKeyFinalFragment frag = new CreateKeyFinalFragment(); + + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putString(ARG_EMAIL, email); + args.putString(ARG_PASSPHRASE, passphrase); + + frag.setArguments(args); + + return frag; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.create_key_final_fragment, container, false); + + mNameEdit = (TextView) view.findViewById(R.id.name); + 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); + + // get args + mName = getArguments().getString(ARG_NAME); + mEmail = getArguments().getString(ARG_EMAIL); + mPassphrase = getArguments().getString(ARG_PASSPHRASE); + + // set values + mNameEdit.setText(mName); + mEmailEdit.setText(mEmail); + + mCreateButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createKey(); + } + }); + + mBackButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mCreateKeyActivity.loadFragment(null, null, CreateKeyActivity.FRAG_ACTION_TO_LEFT); + } + }); + + return view; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mCreateKeyActivity = (CreateKeyActivity) getActivity(); + } + + private void createKey() { + Intent intent = new Intent(getActivity(), KeychainIntentService.class); + intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); + + // Message is received after importing is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( + getActivity(), + getString(R.string.progress_importing), + ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // get returned data bundle + Bundle returnData = message.getData(); + if (returnData == null) { + return; + } + final OperationResults.EditKeyResult result = + returnData.getParcelable(OperationResultParcel.EXTRA_RESULT); + if (result == null) { + return; + } + + if (result.getResult() == OperationResultParcel.RESULT_OK) { + if (mUploadCheckbox.isChecked()) { + // result will be displayed after upload + uploadKey(result); + } else { + // TODO: return result + result.createNotify(getActivity()); + + getActivity().setResult(Activity.RESULT_OK); + getActivity().finish(); + } + } else { + // display result on error without finishing activity + result.createNotify(getActivity()); + } + } + } + }; + + // fill values for this action + Bundle data = new Bundle(); + + SaveKeyringParcel parcel = new SaveKeyringParcel(); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.CERTIFY_OTHER, null)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); + parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null)); + String userId = mName + " <" + mEmail + ">"; + parcel.mAddUserIds.add(userId); + parcel.mNewPassphrase = mPassphrase; + + // get selected key entries + data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, parcel); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + saveHandler.showProgressDialog(getActivity()); + + getActivity().startService(intent); + } + + private void uploadKey(final OperationResults.EditKeyResult editKeyResult) { + // Send all information needed to service to upload key in other thread + final Intent intent = new Intent(getActivity(), KeychainIntentService.class); + + intent.setAction(KeychainIntentService.ACTION_UPLOAD_KEYRING); + + // set data uri as path to keyring + Uri blobUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri( + editKeyResult.mRingMasterKeyId); + intent.setData(blobUri); + + // fill values for this action + Bundle data = new Bundle(); + + // upload to favorite keyserver + String keyserver = Preferences.getPreferences(getActivity()).getKeyServers()[0]; + data.putString(KeychainIntentService.UPLOAD_KEY_SERVER, keyserver); + + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + + // Message is received after uploading is done in KeychainIntentService + KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), + getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + // TODO: not supported by upload? +// if (result.getResult() == OperationResultParcel.RESULT_OK) { + // TODO: return result + editKeyResult.createNotify(getActivity()); + + Notify.showNotify(getActivity(), R.string.key_send_success, + Notify.Style.INFO); + + getActivity().setResult(Activity.RESULT_OK); + getActivity().finish(); +// } else { +// // display result on error without finishing activity +// editKeyResult.createNotify(getActivity()); +// } + } + } + }; + + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + saveHandler.showProgressDialog(getActivity()); + + // start service with intent + getActivity().startService(intent); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java new file mode 100644 index 000000000..ef5a3b145 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyInputFragment.java @@ -0,0 +1,214 @@ +/* + * 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.content.Context; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; + +import java.util.regex.Matcher; + +public class CreateKeyInputFragment extends Fragment { + + CreateKeyActivity mCreateKeyActivity; + + AutoCompleteTextView mNameEdit; + AutoCompleteTextView mEmailEdit; + EditText mPassphraseEdit; + EditText mPassphraseEditAgain; + View mCreateButton; + + public static final String ARG_NAME = "name"; + public static final String ARG_EMAIL = "email"; + + /** + * Creates new instance of this fragment + */ + public static CreateKeyInputFragment newInstance(String name, String email) { + CreateKeyInputFragment frag = new CreateKeyInputFragment(); + + Bundle args = new Bundle(); + args.putString(ARG_NAME, name); + args.putString(ARG_EMAIL, email); + + frag.setArguments(args); + + return frag; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.create_key_input_fragment, container, false); + + mNameEdit = (AutoCompleteTextView) view.findViewById(R.id.name); + mEmailEdit = (AutoCompleteTextView) view.findViewById(R.id.email); + mPassphraseEdit = (EditText) view.findViewById(R.id.passphrase); + mPassphraseEditAgain = (EditText) view.findViewById(R.id.passphrase_again); + mCreateButton = view.findViewById(R.id.create_key_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<String> + (getActivity(), android.R.layout.simple_spinner_dropdown_item, + ContactHelper.getPossibleUserEmails(getActivity()) + ) + ); + mEmailEdit.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + } + + @Override + public void afterTextChanged(Editable editable) { + String email = editable.toString(); + if (email.length() > 0) { + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email); + if (emailMatcher.matches()) { + mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_ok, 0); + } else { + mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_bad, 0); + } + } else { + // remove drawable if email is empty + mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + }); + + mNameEdit.setThreshold(1); // Start working from first character + mNameEdit.setAdapter( + new ArrayAdapter<String> + (getActivity(), android.R.layout.simple_spinner_dropdown_item, + ContactHelper.getPossibleUserNames(getActivity()) + ) + ); + + mCreateButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createKeyCheck(); + } + }); + + return view; + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mCreateKeyActivity = (CreateKeyActivity) getActivity(); + } + + private void createKeyCheck() { + if (isEditTextNotEmpty(getActivity(), mNameEdit) + && isEditTextNotEmpty(getActivity(), mEmailEdit) + && isEditTextNotEmpty(getActivity(), mPassphraseEdit) + && areEditTextsEqual(getActivity(), mPassphraseEdit, mPassphraseEditAgain)) { + + CreateKeyFinalFragment frag = + CreateKeyFinalFragment.newInstance( + mNameEdit.getText().toString(), + mEmailEdit.getText().toString(), + mPassphraseEdit.getText().toString() + ); + + hideKeyboard(); + mCreateKeyActivity.loadFragment(null, frag, CreateKeyActivity.FRAG_ACTION_TO_RIGHT); + } + } + + private void hideKeyboard() { + InputMethodManager inputManager = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + + //check if no view has focus: + View v = getActivity().getCurrentFocus(); + if (v == null) + return; + + 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/DecryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index c12b5b7be..56dfdbd95 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -34,8 +34,6 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.ImageButton; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -129,7 +127,6 @@ public class DecryptFileFragment extends DecryptFragment { } if (mInputFilename.equals("")) { - //AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR); return; } @@ -137,11 +134,8 @@ public class DecryptFileFragment extends DecryptFragment { if (mInputUri == null && mInputFilename.startsWith("file")) { File file = new File(mInputFilename); if (!file.exists() || !file.isFile()) { - AppMsg.makeText( - getActivity(), - getString(R.string.error_message, - getString(R.string.error_file_not_found)), AppMsg.STYLE_ALERT) - .show(); + Notify.showNotify(getActivity(), getString(R.string.error_message, + getString(R.string.error_file_not_found)), Notify.Style.ERROR); return; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 6b8358538..d4235b82b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -132,7 +132,7 @@ public class DecryptFragment extends Fragment { mResultText.setText(R.string.decrypt_result_decrypted_and_signature_certified); } - mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_green)); + mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_green_light)); mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); mSignatureLayout.setVisibility(View.VISIBLE); mLookupKey.setVisibility(View.GONE); @@ -146,7 +146,7 @@ public class DecryptFragment extends Fragment { mResultText.setText(R.string.decrypt_result_decrypted_and_signature_uncertified); } - mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_orange)); + mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_orange_light)); mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); mSignatureLayout.setVisibility(View.VISIBLE); mLookupKey.setVisibility(View.GONE); @@ -160,7 +160,7 @@ public class DecryptFragment extends Fragment { mResultText.setText(R.string.decrypt_result_decrypted_unknown_pub_key); } - mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_orange)); + mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_orange_light)); mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureLayout.setVisibility(View.VISIBLE); mLookupKey.setVisibility(View.VISIBLE); @@ -170,7 +170,7 @@ public class DecryptFragment extends Fragment { case OpenPgpSignatureResult.SIGNATURE_ERROR: { mResultText.setText(R.string.decrypt_result_invalid_signature); - mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_red)); + mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_red_light)); mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureLayout.setVisibility(View.GONE); mLookupKey.setVisibility(View.GONE); @@ -180,7 +180,7 @@ public class DecryptFragment extends Fragment { default: { mResultText.setText(R.string.error); - mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_red)); + mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_red_light)); mSignatureStatusImage.setImageResource(R.drawable.overlay_error); mSignatureLayout.setVisibility(View.GONE); mLookupKey.setVisibility(View.GONE); @@ -192,7 +192,7 @@ public class DecryptFragment extends Fragment { mLookupKey.setVisibility(View.GONE); // successful decryption-only - mResultLayout.setBackgroundColor(getResources().getColor(R.color.result_purple)); + mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_purple_light)); mResultText.setText(R.string.decrypt_result_decrypted); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 46462f924..cf7a0b4b8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -28,8 +28,6 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.EditText; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -38,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.util.regex.Matcher; @@ -107,12 +106,10 @@ public class DecryptMessageFragment extends DecryptFragment { mCiphertext = matcher.group(1); decryptStart(null); } else { - AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_ALERT) - .show(); + Notify.showNotify(getActivity(), R.string.error_invalid_data, Notify.Style.ERROR); } } else { - AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_ALERT) - .show(); + Notify.showNotify(getActivity(), R.string.error_invalid_data, Notify.Style.ERROR); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index d80425c3c..6ddaec17f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -33,7 +33,7 @@ public class EditKeyActivity extends ActionBarActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.edit_key_activity_new); + setContentView(R.layout.edit_key_activity); Uri dataUri = getIntent().getData(); if (dataUri == null) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java deleted file mode 100644 index 70ccb8800..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (C) 2012-2014 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 - * 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.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; -import android.support.v4.app.ActivityCompat; -import android.support.v7.app.ActionBarActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.LinearLayout; -import android.widget.Toast; - -import com.devspark.appmsg.AppMsg; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.helper.ExportHelper; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.pgp.UncachedSecretKey; -import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; -import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; -import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; -import org.sufficientlysecure.keychain.ui.widget.Editor; -import org.sufficientlysecure.keychain.ui.widget.Editor.EditorListener; -import org.sufficientlysecure.keychain.ui.widget.KeyEditor; -import org.sufficientlysecure.keychain.ui.widget.SectionView; -import org.sufficientlysecure.keychain.ui.widget.UserIdEditor; -import org.sufficientlysecure.keychain.util.Log; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Vector; - -public class EditKeyActivityOld extends ActionBarActivity implements EditorListener { - - // Actions for internal use only: - public static final String ACTION_CREATE_KEY = Constants.INTENT_PREFIX + "CREATE_KEY"; - public static final String ACTION_EDIT_KEY = Constants.INTENT_PREFIX + "EDIT_KEY"; - - // possible extra keys - public static final String EXTRA_USER_IDS = "user_ids"; - public static final String EXTRA_NO_PASSPHRASE = "no_passphrase"; - public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generate_default_keys"; - - // EDIT - private Uri mDataUri; - - private SectionView mUserIdsView; - private SectionView mKeysView; - - private String mCurrentPassphrase = null; - private String mNewPassphrase = null; - private String mSavedNewPassphrase = null; - private boolean mIsPassphraseSet; - private boolean mNeedsSaving; - private boolean mIsBrandNewKeyring = false; - - private Button mChangePassphrase; - - private CheckBox mNoPassphrase; - - Vector<String> mUserIds; - Vector<UncachedSecretKey> mKeys; - Vector<Integer> mKeysUsages; - boolean mMasterCanSign = true; - - ExportHelper mExportHelper; - - public boolean needsSaving() { - mNeedsSaving = (mUserIdsView == null) ? false : mUserIdsView.needsSaving(); - mNeedsSaving |= (mKeysView == null) ? false : mKeysView.needsSaving(); - mNeedsSaving |= hasPassphraseChanged(); - mNeedsSaving |= mIsBrandNewKeyring; - return mNeedsSaving; - } - - - public void somethingChanged() { - ActivityCompat.invalidateOptionsMenu(this); - } - - public void onDeleted(Editor e, boolean wasNewItem) { - somethingChanged(); - } - - public void onEdited() { - somethingChanged(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mExportHelper = new ExportHelper(this); - - // Inflate a "Done"/"Cancel" custom action bar view - ActionBarHelper.setTwoButtonView(getSupportActionBar(), - R.string.btn_save, R.drawable.ic_action_save, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Save - saveClicked(); - } - }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel, - new View.OnClickListener() { - @Override - public void onClick(View v) { - // Cancel - cancelClicked(); - } - } - ); - - mUserIds = new Vector<String>(); - mKeys = new Vector<UncachedSecretKey>(); - mKeysUsages = new Vector<Integer>(); - - // Catch Intents opened from other apps - Intent intent = getIntent(); - String action = intent.getAction(); - if (ACTION_CREATE_KEY.equals(action)) { - handleActionCreateKey(intent); - } else if (ACTION_EDIT_KEY.equals(action)) { - handleActionEditKey(intent); - } - } - - /** - * Handle intent action to create new key - * - * @param intent - */ - private void handleActionCreateKey(Intent intent) { - Bundle extras = intent.getExtras(); - - mCurrentPassphrase = ""; - mIsBrandNewKeyring = true; - - if (extras != null) { - // if userId is given, prefill the fields - if (extras.containsKey(EXTRA_USER_IDS)) { - Log.d(Constants.TAG, "UserIds are given!"); - mUserIds.add(extras.getString(EXTRA_USER_IDS)); - } - - // if no passphrase is given - if (extras.containsKey(EXTRA_NO_PASSPHRASE)) { - boolean noPassphrase = extras.getBoolean(EXTRA_NO_PASSPHRASE); - if (noPassphrase) { - // check "no passphrase" checkbox and remove button - mNoPassphrase.setChecked(true); - mChangePassphrase.setVisibility(View.GONE); - } - } - - // generate key - if (extras.containsKey(EXTRA_GENERATE_DEFAULT_KEYS)) { - /* - boolean generateDefaultKeys = extras.getBoolean(EXTRA_GENERATE_DEFAULT_KEYS); - if (generateDefaultKeys) { - - // fill values for this action - Bundle data = new Bundle(); - data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, - mCurrentPassphrase); - - serviceIntent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after generating is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( - this, getResources().getQuantityString(R.plurals.progress_generating, 1), - ProgressDialog.STYLE_HORIZONTAL, true, - - new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - // Stop key generation on cancel - stopService(serviceIntent); - EditKeyActivity.this.setResult(Activity.RESULT_CANCELED); - EditKeyActivity.this.finish(); - } - }) { - - @Override - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get new key from data bundle returned from service - Bundle data = message.getDataAsStringList(); - - ArrayList<UncachedSecretKey> newKeys = - PgpConversionHelper.BytesToPGPSecretKeyList(data - .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); - - ArrayList<Integer> keyUsageFlags = data.getIntegerArrayList( - KeychainIntentService.RESULT_KEY_USAGES); - - if (newKeys.size() == keyUsageFlags.size()) { - for (int i = 0; i < newKeys.size(); ++i) { - mKeys.add(newKeys.get(i)); - mKeysUsages.add(keyUsageFlags.get(i)); - } - } - - buildLayout(true); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - serviceIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - saveHandler.showProgressDialog(this); - - // start service with intent - startService(serviceIntent); - } - */ - } - } else { - buildLayout(false); - } - } - - /** - * Handle intent action to edit existing key - * - * @param intent - */ - private void handleActionEditKey(Intent intent) { - mDataUri = intent.getData(); - if (mDataUri == null) { - Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!"); - finish(); - } else { - Log.d(Constants.TAG, "uri: " + mDataUri); - - try { - Uri secretUri = KeyRings.buildUnifiedKeyRingUri(mDataUri); - WrappedSecretKeyRing keyRing = new ProviderHelper(this).getWrappedSecretKeyRing(secretUri); - - mMasterCanSign = keyRing.getSecretKey().canCertify(); - for (WrappedSecretKey key : keyRing.secretKeyIterator()) { - // Turn into uncached instance - mKeys.add(key.getUncached()); - mKeysUsages.add(key.getKeyUsage()); // get usage when view is created - } - - boolean isSet = false; - for (String userId : keyRing.getSecretKey().getUserIds()) { - Log.d(Constants.TAG, "Added userId " + userId); - if (!isSet) { - isSet = true; - String[] parts = KeyRing.splitUserId(userId); - if (parts[0] != null) { - setTitle(parts[0]); - } - } - mUserIds.add(userId); - } - - buildLayout(false); - - mCurrentPassphrase = ""; - mIsPassphraseSet = keyRing.hasPassphrase(); - if (!mIsPassphraseSet) { - // check "no passphrase" checkbox and remove button - mNoPassphrase.setChecked(true); - mChangePassphrase.setVisibility(View.GONE); - } - - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "Keyring not found: " + e.getMessage(), e); - Toast.makeText(this, R.string.error_no_secret_key_found, Toast.LENGTH_SHORT).show(); - finish(); - } - - } - } - - /** - * Shows the dialog to set a new passphrase - */ - private void showSetPassphraseDialog() { - // Message is received after passphrase is cached - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) { - Bundle data = message.getData(); - - // set new returned passphrase! - mNewPassphrase = data - .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE); - - updatePassphraseButtonText(); - somethingChanged(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); - - // set title based on isPassphraseSet() - int title; - if (isPassphraseSet()) { - title = R.string.title_change_passphrase; - } else { - title = R.string.title_set_passphrase; - } - - SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance( - messenger, null, title); - - setPassphraseDialog.show(getSupportFragmentManager(), "setPassphraseDialog"); - } - - /** - * Build layout based on mUserId, mKeys and mKeysUsages Vectors. It creates Views for every user - * id and key. - * - * @param newKeys - */ - private void buildLayout(boolean newKeys) { - setContentView(R.layout.edit_key_activity); - - // find views - mChangePassphrase = (Button) findViewById(R.id.edit_key_btn_change_passphrase); - mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase); - // Build layout based on given userIds and keys - - LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container); - if (mIsPassphraseSet) { - mChangePassphrase.setText(getString(R.string.btn_change_passphrase)); - } - mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false); - mUserIdsView.setType(SectionView.TYPE_USER_ID); - mUserIdsView.setCanBeEdited(mMasterCanSign); - mUserIdsView.setUserIds(mUserIds); - mUserIdsView.setEditorListener(this); - container.addView(mUserIdsView); - mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false); - mKeysView.setType(SectionView.TYPE_KEY); - mKeysView.setCanBeEdited(mMasterCanSign); - mKeysView.setKeys(mKeys, mKeysUsages, newKeys); - mKeysView.setEditorListener(this); - container.addView(mKeysView); - - updatePassphraseButtonText(); - - mChangePassphrase.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - showSetPassphraseDialog(); - } - }); - - // disable passphrase when no passphrase checkbox is checked! - mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() { - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if (isChecked) { - // remove passphrase - mSavedNewPassphrase = mNewPassphrase; - mNewPassphrase = ""; - mChangePassphrase.setVisibility(View.GONE); - } else { - mNewPassphrase = mSavedNewPassphrase; - mChangePassphrase.setVisibility(View.VISIBLE); - } - somethingChanged(); - } - }); - } - - private long getMasterKeyId() { - if (mKeysView.getEditors().getChildCount() == 0) { - return 0; - } - return ((KeyEditor) mKeysView.getEditors().getChildAt(0)).getValue().getKeyId(); - } - - public boolean isPassphraseSet() { - if (mNoPassphrase.isChecked()) { - return true; - } else if ((mIsPassphraseSet) - || (mNewPassphrase != null && !mNewPassphrase.equals(""))) { - return true; - } else { - return false; - } - } - - public boolean hasPassphraseChanged() { - if (mNoPassphrase != null) { - if (mNoPassphrase.isChecked()) { - return mIsPassphraseSet; - } else { - return (mNewPassphrase != null && !mNewPassphrase.equals("")); - } - } else { - return false; - } - } - - private void saveClicked() { - final long masterKeyId = getMasterKeyId(); - if (needsSaving()) { //make sure, as some versions don't support invalidateOptionsMenu - try { - if (!isPassphraseSet()) { - throw new PgpGeneralException(this.getString(R.string.set_a_passphrase)); - } - - String passphrase; - if (mIsPassphraseSet) { - passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId); - } else { - passphrase = ""; - } - if (passphrase == null) { - PassphraseDialogFragment.show(this, masterKeyId, - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase( - EditKeyActivityOld.this, masterKeyId); - checkEmptyIDsWanted(); - } - } - }); - } else { - mCurrentPassphrase = passphrase; - checkEmptyIDsWanted(); - } - } catch (PgpGeneralException e) { - AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()), - AppMsg.STYLE_ALERT).show(); - } - } else { - AppMsg.makeText(this, R.string.error_change_something_first, AppMsg.STYLE_ALERT).show(); - } - } - - private void checkEmptyIDsWanted() { - try { - ArrayList<String> userIDs = getUserIds(mUserIdsView); - List<Boolean> newIDs = mUserIdsView.getNewIDFlags(); - ArrayList<String> originalIDs = mUserIdsView.getOriginalIDs(); - int curID = 0; - for (String userID : userIDs) { - if (userID.equals("") && (!userID.equals(originalIDs.get(curID)) || newIDs.get(curID))) { - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder( - EditKeyActivityOld.this); - - alert.setIcon(R.drawable.ic_dialog_alert_holo_light); - alert.setTitle(R.string.warning); - alert.setMessage(EditKeyActivityOld.this.getString(R.string.ask_empty_id_ok)); - - alert.setPositiveButton(EditKeyActivityOld.this.getString(android.R.string.yes), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - finallySaveClicked(); - } - } - ); - alert.setNegativeButton(this.getString(android.R.string.no), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - } - } - ); - alert.setCancelable(false); - alert.show(); - return; - } - curID++; - } - } catch (PgpGeneralException e) { - Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage())); - AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()), AppMsg.STYLE_ALERT).show(); - } - finallySaveClicked(); - } - - private boolean[] toPrimitiveArray(final List<Boolean> booleanList) { - final boolean[] primitives = new boolean[booleanList.size()]; - int index = 0; - for (Boolean object : booleanList) { - primitives[index++] = object; - } - return primitives; - } - - private void finallySaveClicked() { - /* - try { - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(this, KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING); - - OldSaveKeyringParcel saveParams = new OldSaveKeyringParcel(); - saveParams.userIds = getUserIds(mUserIdsView); - saveParams.originalIDs = mUserIdsView.getOriginalIDs(); - saveParams.deletedIDs = mUserIdsView.getDeletedIDs(); - saveParams.newIDs = toPrimitiveArray(mUserIdsView.getNewIDFlags()); - saveParams.primaryIDChanged = mUserIdsView.primaryChanged(); - saveParams.moddedKeys = toPrimitiveArray(mKeysView.getNeedsSavingArray()); - saveParams.deletedKeys = mKeysView.getDeletedKeys(); - saveParams.keysExpiryDates = getKeysExpiryDates(mKeysView); - saveParams.keysUsages = getKeysUsages(mKeysView); - saveParams.mNewPassphrase = mNewPassphrase; - saveParams.oldPassphrase = mCurrentPassphrase; - saveParams.newKeys = toPrimitiveArray(mKeysView.getNewKeysArray()); - saveParams.keys = getKeys(mKeysView); - saveParams.originalPrimaryID = mUserIdsView.getOriginalPrimaryID(); - - // fill values for this action - Bundle data = new Bundle(); - data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, mMasterCanSign); - data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, saveParams); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after saving is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - getString(R.string.progress_saving), ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - Intent data = new Intent(); - - // return uri pointing to new created key - Uri uri = KeyRings.buildGenericKeyRingUri(getMasterKeyId()); - data.setData(uri); - - setResult(RESULT_OK, data); - finish(); - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - saveHandler.showProgressDialog(this); - - // start service with intent - startService(intent); - } catch (PgpGeneralException e) { - Log.e(Constants.TAG, getString(R.string.error_message, e.getMessage())); - AppMsg.makeText(this, getString(R.string.error_message, e.getMessage()), - AppMsg.STYLE_ALERT).show(); - } - */ - } - - private void cancelClicked() { - if (needsSaving()) { //ask if we want to save - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder( - EditKeyActivityOld.this); - - alert.setIcon(R.drawable.ic_dialog_alert_holo_light); - alert.setTitle(R.string.warning); - alert.setMessage(EditKeyActivityOld.this.getString(R.string.ask_save_changed_key)); - - alert.setPositiveButton(EditKeyActivityOld.this.getString(android.R.string.yes), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - saveClicked(); - } - }); - alert.setNegativeButton(this.getString(android.R.string.no), - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - setResult(RESULT_CANCELED); - finish(); - } - }); - alert.setCancelable(false); - alert.show(); - } else { - setResult(RESULT_CANCELED); - finish(); - } - } - - /** - * Returns user ids from the SectionView - * - * @param userIdsView - * @return - */ - private ArrayList<String> getUserIds(SectionView userIdsView) throws PgpGeneralException { - ArrayList<String> userIds = new ArrayList<String>(); - - ViewGroup userIdEditors = userIdsView.getEditors(); - - boolean gotMainUserId = false; - for (int i = 0; i < userIdEditors.getChildCount(); ++i) { - UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i); - String userId; - userId = editor.getValue(); - - if (editor.isMainUserId()) { - userIds.add(0, userId); - gotMainUserId = true; - } else { - userIds.add(userId); - } - } - - if (userIds.size() == 0) { - throw new PgpGeneralException(getString(R.string.error_key_needs_a_user_id)); - } - - if (!gotMainUserId) { - throw new PgpGeneralException(getString(R.string.error_main_user_id_must_not_be_empty)); - } - - return userIds; - } - - /** - * Returns keys from the SectionView - * - * @param keysView - * @return - */ - private ArrayList<UncachedSecretKey> getKeys(SectionView keysView) throws PgpGeneralException { - ArrayList<UncachedSecretKey> keys = new ArrayList<UncachedSecretKey>(); - - ViewGroup keyEditors = keysView.getEditors(); - - if (keyEditors.getChildCount() == 0) { - throw new PgpGeneralException(getString(R.string.error_key_needs_master_key)); - } - - for (int i = 0; i < keyEditors.getChildCount(); ++i) { - KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); - keys.add(editor.getValue()); - } - - return keys; - } - - /** - * Returns usage selections of keys from the SectionView - * - * @param keysView - * @return - */ - private ArrayList<Integer> getKeysUsages(SectionView keysView) throws PgpGeneralException { - ArrayList<Integer> keysUsages = new ArrayList<Integer>(); - - ViewGroup keyEditors = keysView.getEditors(); - - if (keyEditors.getChildCount() == 0) { - throw new PgpGeneralException(getString(R.string.error_key_needs_master_key)); - } - - for (int i = 0; i < keyEditors.getChildCount(); ++i) { - KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); - keysUsages.add(editor.getUsage()); - } - - return keysUsages; - } - - private ArrayList<Calendar> getKeysExpiryDates(SectionView keysView) throws PgpGeneralException { - ArrayList<Calendar> keysExpiryDates = new ArrayList<Calendar>(); - - ViewGroup keyEditors = keysView.getEditors(); - - if (keyEditors.getChildCount() == 0) { - throw new PgpGeneralException(getString(R.string.error_key_needs_master_key)); - } - - for (int i = 0; i < keyEditors.getChildCount(); ++i) { - KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i); - keysExpiryDates.add(editor.getExpiryDate()); - } - - return keysExpiryDates; - } - - private void updatePassphraseButtonText() { - mChangePassphrase.setText(isPassphraseSet() ? getString(R.string.btn_change_passphrase) - : getString(R.string.btn_set_passphrase)); - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index b41871a39..9083d1567 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -42,12 +42,13 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.helper.ActionBarHelper; -import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.OperationResults; +import org.sufficientlysecure.keychain.service.OperationResults.EditKeyResult; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; @@ -167,8 +168,8 @@ public class EditKeyFragment extends LoaderFragment implements try { Uri secretUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); - WrappedSecretKeyRing keyRing = - new ProviderHelper(getActivity()).getWrappedSecretKeyRing(secretUri); + CanonicalizedSecretKeyRing keyRing = + new ProviderHelper(getActivity()).getCanonicalizedSecretKeyRing(secretUri); mSaveKeyringParcel = new SaveKeyringParcel(keyRing.getMasterKeyId(), keyRing.getUncachedKeyRing().getFingerprint()); @@ -466,26 +467,30 @@ public class EditKeyFragment extends LoaderFragment implements super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - getActivity().finish(); - // TODO below // get returned data bundle Bundle returnData = message.getData(); if (returnData == null) { return; } - final OperationResults.SaveKeyringResult result = - returnData.getParcelable(KeychainIntentService.RESULT); + final OperationResults.EditKeyResult result = + returnData.getParcelable(EditKeyResult.EXTRA_RESULT); if (result == null) { return; } - // if good -> finish, return result to showkey and display there! // if bad -> display here! + if (!result.success()) { + result.createNotify(getActivity()).show(); + return; + } -// result.displayNotify(ImportKeysActivity.this); + // if good -> finish, return result to showkey and display there! + Intent intent = new Intent(); + intent.putExtra(EditKeyResult.EXTRA_RESULT, result); + getActivity().setResult(EditKeyActivity.RESULT_OK, intent); + getActivity().finish(); -// getActivity().finish(); } } }; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index dc0510189..eb807792b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -31,11 +31,14 @@ import android.widget.Button; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.util.Vector; @@ -195,22 +198,23 @@ public class EncryptAsymmetricFragment extends Fragment { mMainUserIdRest.setText(""); } else { // See if we can get a user_id from a unified query - String[] userId; try { - userId = mProviderHelper.getCachedPublicKeyRing( + String[] userIdSplit = mProviderHelper.getCachedPublicKeyRing( KeyRings.buildUnifiedKeyRingUri(mSecretKeyId)).getSplitPrimaryUserIdWithFallback(); + + if (userIdSplit[0] != null) { + mMainUserId.setText(userIdSplit[0]); + } else { + mMainUserId.setText(R.string.user_id_no_name); + } + if (userIdSplit[1] != null) { + mMainUserIdRest.setText(userIdSplit[1]); + } else { + mMainUserIdRest.setText(getString(R.string.label_key_id) + ": " + + PgpKeyHelper.convertKeyIdToHex(mSecretKeyId)); + } } catch (PgpGeneralException e) { - userId = null; - } - if (userId != null && userId[0] != null) { - mMainUserId.setText(String.format("%#16x", Long.parseLong(userId[0]))); - } else { - mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); - } - if (userId != null && userId[1] != null) { - mMainUserIdRest.setText(userId[1]); - } else { - mMainUserIdRest.setText(""); + Notify.showNotify(getActivity(), "Key not found! This is a bug!", Notify.Style.ERROR); } mSign.setChecked(true); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index f5d89d186..345e38a0e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -37,8 +37,6 @@ import android.widget.EditText; import android.widget.ImageButton; import android.widget.Spinner; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.FileHelper; @@ -51,6 +49,7 @@ import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.io.File; @@ -58,7 +57,7 @@ public class EncryptFileFragment extends Fragment { public static final String ARG_FILENAME = "filename"; public static final String ARG_ASCII_ARMOR = "ascii_armor"; - private static final int RESULT_CODE_FILE = 0x00007003; + private static final int REQUEST_CODE_FILE = 0x00007003; private EncryptActivityInterface mEncryptInterface; @@ -109,10 +108,10 @@ public class EncryptFileFragment extends Fragment { mBrowse.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (Constants.KITKAT) { - FileHelper.openDocument(EncryptFileFragment.this, mInputUri, "*/*", RESULT_CODE_FILE); + FileHelper.openDocument(EncryptFileFragment.this, mInputUri, "*/*", REQUEST_CODE_FILE); } else { FileHelper.openFile(EncryptFileFragment.this, mFilename.getText().toString(), "*/*", - RESULT_CODE_FILE); + REQUEST_CODE_FILE); } } }); @@ -218,18 +217,18 @@ public class EncryptFileFragment extends Fragment { } if (mInputFilename.equals("")) { - AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.no_file_selected, Notify.Style.ERROR); return; } if (mInputUri == null && !mInputFilename.startsWith("content")) { File file = new File(mInputFilename); if (!file.exists() || !file.isFile()) { - AppMsg.makeText( + Notify.showNotify( getActivity(), getString(R.string.error_message, - getString(R.string.error_file_not_found)), AppMsg.STYLE_ALERT) - .show(); + getString(R.string.error_file_not_found)), Notify.Style.ERROR + ); return; } } @@ -240,13 +239,13 @@ public class EncryptFileFragment extends Fragment { boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null && mEncryptInterface.getPassphrase().length() != 0); if (!gotPassphrase) { - AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT) - .show(); + Notify.showNotify(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR) + ; return; } if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) { - AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR); return; } } else { @@ -256,13 +255,13 @@ public class EncryptFileFragment extends Fragment { && mEncryptInterface.getEncryptionKeys().length > 0); if (!gotEncryptionKeys) { - AppMsg.makeText(getActivity(), R.string.select_encryption_key, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.select_encryption_key, Notify.Style.ERROR); return; } if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) { - AppMsg.makeText(getActivity(), R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.select_encryption_or_signature_key, + Notify.Style.ERROR); return; } @@ -345,8 +344,8 @@ public class EncryptFileFragment extends Fragment { super.handleMessage(message); if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - AppMsg.makeText(getActivity(), R.string.encrypt_sign_successful, - AppMsg.STYLE_INFO).show(); + Notify.showNotify(getActivity(), R.string.encrypt_sign_successful, + Notify.Style.INFO); if (mDeleteAfter.isChecked()) { // Create and show dialog to delete original file @@ -390,7 +389,7 @@ public class EncryptFileFragment extends Fragment { @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { - case RESULT_CODE_FILE: { + case REQUEST_CODE_FILE: { if (resultCode == Activity.RESULT_OK && data != null) { if (Constants.KITKAT) { mInputUri = data.getData(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java index 8a6103b16..e1760b4ed 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java @@ -30,8 +30,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -41,6 +39,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; public class EncryptMessageFragment extends Fragment { public static final String ARG_TEXT = "text"; @@ -126,13 +125,12 @@ public class EncryptMessageFragment extends Fragment { boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null && mEncryptInterface.getPassphrase().length() != 0); if (!gotPassphrase) { - AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT) - .show(); + Notify.showNotify(getActivity(), R.string.passphrase_must_not_be_empty, Notify.Style.ERROR); return; } if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) { - AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.passphrases_do_not_match, Notify.Style.ERROR); return; } @@ -143,8 +141,8 @@ public class EncryptMessageFragment extends Fragment { && mEncryptInterface.getEncryptionKeys().length > 0); if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) { - AppMsg.makeText(getActivity(), R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.select_encryption_or_signature_key, + Notify.Style.ERROR); return; } @@ -226,9 +224,8 @@ public class EncryptMessageFragment extends Fragment { if (toClipboard) { ClipboardReflection.copyToClipboard(getActivity(), output); - AppMsg.makeText(getActivity(), - R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO) - .show(); + Notify.showNotify(getActivity(), + R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); } else { Intent sendIntent = new Intent(Intent.ACTION_SEND); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java index aa4120d2c..5f3f170a1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/FirstTimeActivity.java @@ -22,15 +22,19 @@ import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.view.Window; -import android.widget.Button; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.util.Log; public class FirstTimeActivity extends ActionBarActivity { - Button mCreateKey; - Button mImportKey; - Button mSkipSetup; + View mCreateKey; + View mImportKey; + View mSkipSetup; + + public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012; @Override protected void onCreate(Bundle savedInstanceState) { @@ -40,16 +44,14 @@ public class FirstTimeActivity extends ActionBarActivity { setContentView(R.layout.first_time_activity); - mCreateKey = (Button) findViewById(R.id.first_time_create_key); - mImportKey = (Button) findViewById(R.id.first_time_import_key); - mSkipSetup = (Button) findViewById(R.id.first_time_cancel); + mCreateKey = findViewById(R.id.first_time_create_key); + mImportKey = findViewById(R.id.first_time_import_key); + mSkipSetup = findViewById(R.id.first_time_cancel); mSkipSetup.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(FirstTimeActivity.this, KeyListActivity.class); - startActivity(intent); - finish(); + finishSetup(); } }); @@ -58,8 +60,7 @@ public class FirstTimeActivity extends ActionBarActivity { public void onClick(View v) { Intent intent = new Intent(FirstTimeActivity.this, ImportKeysActivity.class); intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); - startActivity(intent); - finish(); + startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); } }); @@ -67,11 +68,30 @@ public class FirstTimeActivity extends ActionBarActivity { @Override public void onClick(View v) { Intent intent = new Intent(FirstTimeActivity.this, CreateKeyActivity.class); - startActivity(intent); - finish(); + startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); } }); } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) { + if (resultCode == RESULT_OK) { + finishSetup(); + } + } else { + Log.e(Constants.TAG, "No valid request code!"); + } + } + + private void finishSetup() { + Preferences prefs = Preferences.getPreferences(this); + prefs.setFirstTime(false); + Intent intent = new Intent(FirstTimeActivity.this, KeyListActivity.class); + startActivity(intent); + finish(); + } } 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 3ff3b56bf..dbc557f9a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -40,17 +40,19 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.keyimport.FileImportCache; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.OperationResults.ImportResult; +import org.sufficientlysecure.keychain.service.OperationResults.ImportKeyResult; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Notify; +import java.io.IOException; import java.util.ArrayList; import java.util.Locale; @@ -98,6 +100,7 @@ public class ImportKeysActivity extends ActionBarActivity { public static final int VIEW_PAGER_HEIGHT = 64; // dp + private static final int ALL_TABS = -1; private static final int TAB_KEYSERVER = 0; private static final int TAB_QR_CODE = 1; private static final int TAB_FILE = 2; @@ -150,7 +153,7 @@ public class ImportKeysActivity extends ActionBarActivity { } Bundle serverBundle = null; - boolean serverOnly = false; + int showTabOnly = ALL_TABS; if (ACTION_IMPORT_KEY.equals(action)) { /* Keychain's own Actions */ @@ -214,7 +217,7 @@ public class ImportKeysActivity extends ActionBarActivity { serverBundle.putString(ImportKeysServerFragment.ARG_QUERY, query); serverBundle.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true); // display server tab only - serverOnly = true; + showTabOnly = TAB_KEYSERVER; mSwitchToTab = TAB_KEYSERVER; // action: search immediately @@ -227,13 +230,20 @@ public class ImportKeysActivity extends ActionBarActivity { ); return; } - } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action) - || ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { + } else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) { // NOTE: this only displays the appropriate fragment, no actions are taken mSwitchToTab = TAB_FILE; // no immediate actions! startListFragment(savedInstanceState, null, null, null); + } else if (ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(action)) { + // NOTE: this only displays the appropriate fragment, no actions are taken + mSwitchToTab = TAB_FILE; + // display file tab only + showTabOnly = TAB_FILE; + + // no immediate actions! + startListFragment(savedInstanceState, null, null, null); } else if (ACTION_IMPORT_KEY_FROM_QR_CODE.equals(action)) { // also exposed in AndroidManifest @@ -259,10 +269,10 @@ public class ImportKeysActivity extends ActionBarActivity { startListFragment(savedInstanceState, null, null, null); } - initTabs(serverBundle, serverOnly); + initTabs(serverBundle, showTabOnly); } - private void initTabs(Bundle serverBundle, boolean serverOnly) { + private void initTabs(Bundle serverBundle, int showTabOnly) { mTabsAdapter = new PagerTabStripAdapter(this); mViewPager.setAdapter(mTabsAdapter); mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @@ -285,15 +295,34 @@ public class ImportKeysActivity extends ActionBarActivity { } }); - mTabsAdapter.addTab(ImportKeysServerFragment.class, - serverBundle, getString(R.string.import_tab_keyserver)); - if (!serverOnly) { - mTabsAdapter.addTab(ImportKeysQrCodeFragment.class, - null, getString(R.string.import_tab_qr_code)); - mTabsAdapter.addTab(ImportKeysFileFragment.class, - null, getString(R.string.import_tab_direct)); - mTabsAdapter.addTab(ImportKeysKeybaseFragment.class, - null, getString(R.string.import_tab_keybase)); + switch (showTabOnly) { + case ALL_TABS: + // show all tabs + mTabsAdapter.addTab(ImportKeysServerFragment.class, + serverBundle, getString(R.string.import_tab_keyserver)); + mTabsAdapter.addTab(ImportKeysQrCodeFragment.class, + null, getString(R.string.import_tab_qr_code)); + mTabsAdapter.addTab(ImportKeysFileFragment.class, + null, getString(R.string.import_tab_direct)); + mTabsAdapter.addTab(ImportKeysKeybaseFragment.class, + null, getString(R.string.import_tab_keybase)); + break; + case TAB_KEYSERVER: + mTabsAdapter.addTab(ImportKeysServerFragment.class, + serverBundle, getString(R.string.import_tab_keyserver)); + break; + case TAB_QR_CODE: + mTabsAdapter.addTab(ImportKeysQrCodeFragment.class, + null, getString(R.string.import_tab_qr_code)); + break; + case TAB_FILE: + mTabsAdapter.addTab(ImportKeysFileFragment.class, + null, getString(R.string.import_tab_direct)); + break; + case TAB_KEYBASE: + mTabsAdapter.addTab(ImportKeysKeybaseFragment.class, + null, getString(R.string.import_tab_keybase)); + break; } // update layout after operations @@ -354,9 +383,8 @@ public class ImportKeysActivity extends ActionBarActivity { ImportKeysServerFragment f = (ImportKeysServerFragment) getActiveFragment(mViewPager, TAB_KEYSERVER); - // TODO: Currently it simply uses keyserver nr 0 - String keyserver = Preferences.getPreferences(ImportKeysActivity.this) - .getKeyServers()[0]; + // ask favorite keyserver + String keyserver = Preferences.getPreferences(ImportKeysActivity.this).getKeyServers()[0]; // set fields of ImportKeysServerFragment f.setQueryAndKeyserver(query, keyserver); @@ -427,15 +455,15 @@ public class ImportKeysActivity extends ActionBarActivity { if (returnData == null) { return; } - final ImportResult result = - returnData.getParcelable(KeychainIntentService.RESULT); + final ImportKeyResult result = + returnData.getParcelable(KeychainIntentService.RESULT_IMPORT); if (result == null) { return; } if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())) { Intent intent = new Intent(); - intent.putExtra(EXTRA_RESULT, result); + intent.putExtra(ImportKeyResult.EXTRA_RESULT, result); ImportKeysActivity.this.setResult(RESULT_OK, intent); ImportKeysActivity.this.finish(); return; @@ -451,7 +479,7 @@ public class ImportKeysActivity extends ActionBarActivity { return; } - result.displayNotify(ImportKeysActivity.this); + result.createNotify(ImportKeysActivity.this).show(); } } }; @@ -470,19 +498,29 @@ public class ImportKeysActivity extends ActionBarActivity { // get DATA from selected key entries ArrayList<ParcelableKeyRing> selectedEntries = mListFragment.getSelectedData(); - data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries); - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + // instead of given the entries by Intent extra, cache them into a file + // to prevent Java Binder problems on heavy imports + // read FileImportCache for more info. + try { + FileImportCache cache = new FileImportCache(this); + cache.writeCache(selectedEntries); - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - // show progress dialog - saveHandler.showProgressDialog(this); + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(saveHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - // start service with intent - startService(intent); + // show progress dialog + saveHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } catch (IOException e) { + Log.e(Constants.TAG, "Problem writing cache file", e); + Notify.showNotify(this, "Problem writing cache file!", Notify.Style.ERROR); + } } else if (ls instanceof ImportKeysListFragment.KeyserverLoaderState) { ImportKeysListFragment.KeyserverLoaderState sls = (ImportKeysListFragment.KeyserverLoaderState) ls; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 9a39b6cc3..fde0f5f23 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -35,7 +35,6 @@ import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.Keyserver; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListKeybaseLoader; @@ -288,13 +287,13 @@ public class ImportKeysListFragment extends ListFragment implements if (error == null) { // No error mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings(); - } else if (error instanceof ImportKeysListLoader.FileHasNoContent) { - Notify.showNotify(getActivity(), R.string.error_import_file_no_content, Notify.Style.ERROR); - } else if (error instanceof ImportKeysListLoader.NonPgpPart) { + } else if (error instanceof ImportKeysListLoader.NoValidKeysException) { + Notify.showNotify(getActivity(), R.string.error_import_no_valid_keys, Notify.Style.ERROR); + } else if (error instanceof ImportKeysListLoader.NonPgpPartException) { Notify.showNotify(getActivity(), - ((ImportKeysListLoader.NonPgpPart) error).getCount() + " " + getResources(). + ((ImportKeysListLoader.NonPgpPartException) error).getCount() + " " + getResources(). getQuantityString(R.plurals.error_import_non_pgp_part, - ((ImportKeysListLoader.NonPgpPart) error).getCount()), + ((ImportKeysListLoader.NonPgpPartException) error).getCount()), Notify.Style.OK ); } else { @@ -308,9 +307,11 @@ public class ImportKeysListFragment extends ListFragment implements if (error == null) { // No error } else if (error instanceof Keyserver.QueryTooShortException) { - Notify.showNotify(getActivity(), R.string.error_keyserver_insufficient_query, Notify.Style.ERROR); + Notify.showNotify(getActivity(), R.string.error_query_too_short, Notify.Style.ERROR); } else if (error instanceof Keyserver.TooManyResponsesException) { - Notify.showNotify(getActivity(), R.string.error_keyserver_too_many_responses, Notify.Style.ERROR); + Notify.showNotify(getActivity(), R.string.error_too_many_responses, Notify.Style.ERROR); + } else if (error instanceof Keyserver.QueryTooShortOrTooManyResponsesException) { + Notify.showNotify(getActivity(), R.string.error_too_short_or_too_many_responses, Notify.Style.ERROR); } else if (error instanceof Keyserver.QueryFailedException) { Log.d(Constants.TAG, "Unrecoverable keyserver query error: " + error.getLocalizedMessage()); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java index 9cc623c83..50ff5c753 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -17,29 +17,19 @@ package org.sufficientlysecure.keychain.ui; -import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; import android.view.Menu; import android.view.MenuItem; -import com.devspark.appmsg.AppMsg; - -import org.spongycastle.bcpg.sig.KeyFlags; import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.Constants.choice.algorithm; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ExportHelper; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel; -import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.io.IOException; @@ -51,11 +41,10 @@ public class KeyListActivity extends DrawerActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // if this is the first time show first time activity Preferences prefs = Preferences.getPreferences(this); - if (prefs.getFirstTime()) { - prefs.setFirstTime(false); - Intent intent = new Intent(this, FirstTimeActivity.class); - startActivity(intent); + if (prefs.isFirstTime()) { + startActivity(new Intent(this, FirstTimeActivity.class)); finish(); return; } @@ -85,7 +74,7 @@ public class KeyListActivity extends DrawerActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.menu_key_list_import: + case R.id.menu_key_list_add: importKeys(); return true; @@ -93,6 +82,12 @@ public class KeyListActivity extends DrawerActivity { createKey(); return true; + case R.id.menu_key_list_import_existing_key: + Intent intentImportExisting = new Intent(this, ImportKeysActivity.class); + intentImportExisting.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); + startActivityForResult(intentImportExisting, 0); + return true; + case R.id.menu_key_list_export: mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true); return true; @@ -100,25 +95,27 @@ public class KeyListActivity extends DrawerActivity { case R.id.menu_key_list_debug_read: try { KeychainDatabase.debugRead(this); - AppMsg.makeText(this, "Restored from backup", AppMsg.STYLE_CONFIRM).show(); + Notify.showNotify(this, "Restored Notify.Style backup", Notify.Style.INFO); getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null); } catch (IOException e) { Log.e(Constants.TAG, "IO Error", e); - AppMsg.makeText(this, "IO Error: " + e.getMessage(), AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, "IO Notify.Style: " + e.getMessage(), Notify.Style.ERROR); } return true; case R.id.menu_key_list_debug_write: try { KeychainDatabase.debugWrite(this); - AppMsg.makeText(this, "Backup successful", AppMsg.STYLE_CONFIRM).show(); - } catch (IOException e) { + Notify.showNotify(this, "Backup Notify.Style", Notify.Style.INFO); + } catch(IOException e) { Log.e(Constants.TAG, "IO Error", e); - AppMsg.makeText(this, "IO Error: " + e.getMessage(), AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, "IO Notify.Style: " + e.getMessage(), Notify.Style.ERROR); } return true; case R.id.menu_key_list_debug_first_time: + Preferences prefs = Preferences.getPreferences(this); + prefs.setFirstTime(true); Intent intent = new Intent(this, FirstTimeActivity.class); startActivity(intent); finish(); @@ -139,4 +136,4 @@ public class KeyListActivity extends DrawerActivity { startActivity(intent); } -}
\ No newline at end of file +} 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 9d0a80406..aa17aea3d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Color; +import android.graphics.PorterDuff; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -46,14 +47,11 @@ import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import android.widget.Button; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ExportHelper; @@ -62,6 +60,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.util.Highlighter; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.util.Date; import java.util.HashMap; @@ -86,6 +85,7 @@ public class KeyListFragment extends LoaderFragment private Button mButtonEmptyCreate; private Button mButtonEmptyImport; + public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012; /** * Load custom layout with StickyListView from library @@ -104,11 +104,8 @@ public class KeyListFragment extends LoaderFragment @Override public void onClick(View v) { - Intent intent = new Intent(getActivity(), EditKeyActivityOld.class); - intent.setAction(EditKeyActivityOld.ACTION_CREATE_KEY); - intent.putExtra(EditKeyActivityOld.EXTRA_GENERATE_DEFAULT_KEYS, true); - intent.putExtra(EditKeyActivityOld.EXTRA_USER_IDS, ""); // show user id view - startActivityForResult(intent, 0); + Intent intent = new Intent(getActivity(), CreateKeyActivity.class); + startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); } }); mButtonEmptyImport = (Button) view.findViewById(R.id.key_list_empty_button_import); @@ -117,8 +114,8 @@ public class KeyListFragment extends LoaderFragment @Override public void onClick(View v) { Intent intent = new Intent(getActivity(), ImportKeysActivity.class); - intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE); - startActivityForResult(intent, 0); + intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); + startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); } }); @@ -339,8 +336,8 @@ public class KeyListFragment extends LoaderFragment public void showDeleteKeyDialog(final ActionMode mode, long[] masterKeyIds, boolean hasSecret) { // Can only work on singular secret keys if(hasSecret && masterKeyIds.length > 1) { - AppMsg.makeText(getActivity(), R.string.secret_cannot_multiple, - AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.secret_cannot_multiple, + Notify.Style.ERROR); return; } @@ -437,9 +434,7 @@ public class KeyListFragment extends LoaderFragment private class ItemViewHolder { TextView mMainUserId; TextView mMainUserIdRest; - FrameLayout mStatusLayout; - TextView mRevoked; - ImageView mVerified; + ImageView mStatus; } @Override @@ -448,9 +443,7 @@ public class KeyListFragment extends LoaderFragment ItemViewHolder holder = new ItemViewHolder(); holder.mMainUserId = (TextView) view.findViewById(R.id.mainUserId); holder.mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); - holder.mStatusLayout = (FrameLayout) view.findViewById(R.id.status_layout); - holder.mRevoked = (TextView) view.findViewById(R.id.revoked); - holder.mVerified = (ImageView) view.findViewById(R.id.verified); + holder.mStatus = (ImageView) view.findViewById(R.id.status_image); view.setTag(holder); return view; } @@ -482,30 +475,40 @@ public class KeyListFragment extends LoaderFragment } } - { // set edit button and revoked info, specific by key type - - if (cursor.getInt(KeyListFragment.INDEX_HAS_ANY_SECRET) != 0) { - // this is a secret key - h.mStatusLayout.setVisibility(View.VISIBLE); - h.mRevoked.setVisibility(View.GONE); - h.mVerified.setVisibility(View.GONE); - } else { - // this is a public key - show if it's revoked - - boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; - boolean isExpired = !cursor.isNull(INDEX_EXPIRY) - && new Date(cursor.getLong(INDEX_EXPIRY)*1000).before(new Date()); - if(isRevoked || isExpired) { - h.mStatusLayout.setVisibility(View.VISIBLE); - h.mRevoked.setVisibility(View.VISIBLE); - h.mVerified.setVisibility(View.GONE); - h.mRevoked.setText(isRevoked ? R.string.revoked : R.string.expired); + { // set edit button and status, specific by key type + + boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; + boolean isExpired = !cursor.isNull(INDEX_EXPIRY) + && new Date(cursor.getLong(INDEX_EXPIRY)*1000).before(new Date()); + boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; + + // Note: order is important! + if (isRevoked) { + h.mStatus.setImageDrawable( + getResources().getDrawable(R.drawable.status_signature_revoked_cutout)); + h.mStatus.setColorFilter(getResources().getColor(R.color.android_red_dark), + PorterDuff.Mode.SRC_ATOP); + h.mStatus.setVisibility(View.VISIBLE); + } else if (isExpired) { + h.mStatus.setImageDrawable( + getResources().getDrawable(R.drawable.status_signature_expired_cutout)); + h.mStatus.setColorFilter(getResources().getColor(R.color.android_orange_dark), + PorterDuff.Mode.SRC_ATOP); + h.mStatus.setVisibility(View.VISIBLE); + } else if (isVerified) { + if (cursor.getInt(KeyListFragment.INDEX_HAS_ANY_SECRET) != 0) { + // this is a secret key + h.mStatus.setVisibility(View.GONE); } else { - boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; - h.mStatusLayout.setVisibility(isVerified ? View.VISIBLE : View.GONE); - h.mRevoked.setVisibility(View.GONE); - h.mVerified.setVisibility(isVerified ? View.VISIBLE : View.GONE); + // this is a public key - show if it's verified + h.mStatus.setImageDrawable( + getResources().getDrawable(R.drawable.status_signature_verified_cutout)); + h.mStatus.setColorFilter(getResources().getColor(R.color.android_green_dark), + PorterDuff.Mode.SRC_ATOP); + h.mStatus.setVisibility(View.VISIBLE); } + } else { + h.mStatus.setVisibility(View.GONE); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java index 75c967c60..43de6774b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LogDisplayFragment.java @@ -178,9 +178,11 @@ public class LogDisplayFragment extends ListFragment implements OnTouchListener if (entry.mParameters != null && entry.mParameters.length > 0 && entry.mParameters[0] instanceof Integer) { ih.mText.setText(getResources().getQuantityString(entry.mType.getMsgId(), - (Integer) entry.mParameters[0], entry.mParameters)); + (Integer) entry.mParameters[0], + entry.mParameters)); } else { - ih.mText.setText(getResources().getString(entry.mType.getMsgId(), entry.mParameters)); + ih.mText.setText(getResources().getString(entry.mType.getMsgId(), + entry.mParameters)); } ih.mText.setTextColor(entry.mLevel == LogLevel.DEBUG ? Color.GRAY : Color.BLACK); convertView.setPadding((entry.mIndent) * dipFactor, 0, 0, 0); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java new file mode 100644 index 000000000..a906dfa97 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/QrCodeActivity.java @@ -0,0 +1,114 @@ +/* + * 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.net.Uri; +import android.os.Bundle; +import android.support.v7.app.ActionBarActivity; +import android.view.View; +import android.widget.ImageView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ActionBarHelper; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; +import org.sufficientlysecure.keychain.util.Notify.Style; +import org.sufficientlysecure.keychain.util.QrCodeUtils; + +public class QrCodeActivity extends ActionBarActivity { + + private ImageView mFingerprintQrCode; + + private static final int QR_CODE_SIZE = 1000; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Inflate a "Done" custom action bar + ActionBarHelper.setOneButtonView(getSupportActionBar(), + R.string.btn_okay, R.drawable.ic_action_done, + new View.OnClickListener() { + @Override + public void onClick(View v) { + // "Done" + finish(); + } + } + ); + + setContentView(R.layout.qr_code_activity); + + Uri dataUri = getIntent().getData(); + if (dataUri == null) { + Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); + finish(); + return; + } + + mFingerprintQrCode = (ImageView) findViewById(R.id.qr_code_image); + + mFingerprintQrCode.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + ProviderHelper providerHelper = new ProviderHelper(this); + try { + byte[] blob = (byte[]) providerHelper.getGenericData( + KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), + KeychainContract.KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); + if (blob == null) { + Log.e(Constants.TAG, "key not found!"); + Notify.showNotify(this, R.string.error_key_not_found, Style.ERROR); + finish(); + } + + String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); + String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; + mFingerprintQrCode.setImageBitmap(QrCodeUtils.getQRCodeBitmap(qrCodeContent, QR_CODE_SIZE)); + } catch (ProviderHelper.NotFoundException e) { + Log.e(Constants.TAG, "key not found!", e); + Notify.showNotify(this, R.string.error_key_not_found, Style.ERROR); + finish(); + } + } + + @Override + protected void onResume() { + super.onResume(); + + // custom activity transition to get zoom in effect + this.overridePendingTransition(R.anim.qr_code_zoom_enter, android.R.anim.fade_out); + } + + @Override + protected void onPause() { + super.onPause(); + + // custom activity transition to get zoom out effect + this.overridePendingTransition(0, R.anim.qr_code_zoom_exit); + } + +}
\ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java index dbd1b7507..57bfc7bd5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/UploadKeyActivity.java @@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.util.Log; @@ -92,7 +93,7 @@ public class UploadKeyActivity extends ActionBarActivity { intent.setAction(KeychainIntentService.ACTION_UPLOAD_KEYRING); // set data uri as path to keyring - Uri blobUri = KeychainContract.KeyRingData.buildPublicKeyRingUri(mDataUri); + Uri blobUri = KeyRings.buildUnifiedKeyRingUri(mDataUri); intent.setData(blobUri); // fill values for this action @@ -105,7 +106,7 @@ public class UploadKeyActivity extends ActionBarActivity { // Message is received after uploading is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, - getString(R.string.progress_exporting), ProgressDialog.STYLE_HORIZONTAL) { + getString(R.string.progress_uploading), ProgressDialog.STYLE_HORIZONTAL) { public void handleMessage(Message message) { // handle messages by standard KeychainIntentServiceHandler first super.handleMessage(message); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java index cfdea0611..5201b5df8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewCertActivity.java @@ -35,7 +35,7 @@ import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.pgp.WrappedPublicKeyRing; +import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; import org.sufficientlysecure.keychain.pgp.WrappedSignature; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; @@ -143,16 +143,16 @@ public class ViewCertActivity extends ActionBarActivity try { ProviderHelper providerHelper = new ProviderHelper(this); - WrappedPublicKeyRing signeeRing = - providerHelper.getWrappedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); - WrappedPublicKeyRing signerRing = - providerHelper.getWrappedPublicKeyRing(sig.getKeyId()); + CanonicalizedPublicKeyRing signeeRing = + providerHelper.getCanonicalizedPublicKeyRing(data.getLong(INDEX_MASTER_KEY_ID)); + CanonicalizedPublicKeyRing signerRing = + providerHelper.getCanonicalizedPublicKeyRing(sig.getKeyId()); try { sig.init(signerRing.getPublicKey()); if (sig.verifySignature(signeeRing.getPublicKey(), signeeUid)) { mStatus.setText(R.string.cert_verify_ok); - mStatus.setTextColor(getResources().getColor(R.color.result_green)); + mStatus.setTextColor(getResources().getColor(R.color.android_green_light)); } else { mStatus.setText(R.string.cert_verify_failed); mStatus.setTextColor(getResources().getColor(R.color.alert)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index a9cd0976b..44a51a75f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -19,9 +19,9 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; -import android.app.Activity; import android.content.Intent; import android.database.Cursor; +import android.graphics.PorterDuff; import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NdefRecord; @@ -43,8 +43,9 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; - -import com.devspark.appmsg.AppMsg; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; @@ -54,11 +55,12 @@ import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.OperationResults.ImportResult; +import org.sufficientlysecure.keychain.service.OperationResultParcel; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout.TabColorizer; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout; +import org.sufficientlysecure.keychain.util.Notify; import java.util.Date; import java.util.HashMap; @@ -81,11 +83,11 @@ public class ViewKeyActivity extends ActionBarActivity implements private ViewPager mViewPager; private SlidingTabLayout mSlidingTabLayout; private PagerTabStripAdapter mTabsAdapter; - private View mStatusDivider; - private View mStatusRevoked; - private View mStatusExpired; - public static final int REQUEST_CODE_LOOKUP_KEY = 0x00007006; + private LinearLayout mStatusLayout; + private TextView mStatusText; + private ImageView mStatusImage; + private View mStatusDivider; // NFC private NfcAdapter mNfcAdapter; @@ -115,9 +117,10 @@ public class ViewKeyActivity extends ActionBarActivity implements setContentView(R.layout.view_key_activity); - mStatusDivider = findViewById(R.id.status_divider); - mStatusRevoked = findViewById(R.id.view_key_revoked); - mStatusExpired = findViewById(R.id.view_key_expired); + mStatusLayout = (LinearLayout) findViewById(R.id.view_key_status_layout); + mStatusText = (TextView) findViewById(R.id.view_key_status_text); + mStatusImage = (ImageView) findViewById(R.id.view_key_status_image); + mStatusDivider = findViewById(R.id.view_key_status_divider); mViewPager = (ViewPager) findViewById(R.id.view_key_pager); mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.view_key_sliding_tab_layout); @@ -140,20 +143,27 @@ public class ViewKeyActivity extends ActionBarActivity implements switchToTab = intent.getExtras().getInt(EXTRA_SELECTED_TAB); } - Uri dataUri = getDataUri(); - if (dataUri == null) { - Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); + mDataUri = getIntent().getData(); + if (mDataUri == null) { + Log.e(Constants.TAG, "Data missing. Should be uri of key!"); finish(); return; } + if (mDataUri.getHost().equals(ContactsContract.AUTHORITY)) { + mDataUri = ContactHelper.dataUriFromContactUri(this, mDataUri); + } + + Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); - loadData(dataUri); + // Prepare the loaders. Either re-connect with an existing ones, + // or start new ones. + getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); - initNfc(dataUri); + initNfc(mDataUri); mShowAdvancedTabs = false; - initTabs(dataUri); + initTabs(mDataUri); // switch to tab selected by extra mViewPager.setCurrentItem(switchToTab); @@ -230,24 +240,6 @@ public class ViewKeyActivity extends ActionBarActivity implements mSlidingTabLayout.setViewPager(mViewPager); } - private Uri getDataUri() { - Uri dataUri = getIntent().getData(); - if (dataUri != null && dataUri.getHost().equals(ContactsContract.AUTHORITY)) { - dataUri = ContactHelper.dataUriFromContactUri(this, dataUri); - } - return dataUri; - } - - private void loadData(Uri dataUri) { - mDataUri = dataUri; - - Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); - - // Prepare the loaders. Either re-connect with an existing ones, - // or start new ones. - getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -268,14 +260,6 @@ public class ViewKeyActivity extends ActionBarActivity implements startActivity(homeIntent); return true; } - case R.id.menu_key_view_update: { - updateFromKeyserver(mDataUri, mProviderHelper); - return true; - } - case R.id.menu_key_view_export_keyserver: { - uploadToKeyserver(mDataUri); - return true; - } case R.id.menu_key_view_export_file: { exportToFile(mDataUri, mExportHelper, mProviderHelper); return true; @@ -295,7 +279,7 @@ public class ViewKeyActivity extends ActionBarActivity implements } } } catch (ProviderHelper.NotFoundException e) { - AppMsg.makeText(this, R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); Log.e(Constants.TAG, "Key not found", e); } return super.onOptionsItemSelected(item); @@ -317,26 +301,6 @@ public class ViewKeyActivity extends ActionBarActivity implements ); } - private void uploadToKeyserver(Uri dataUri) throws ProviderHelper.NotFoundException { - Intent uploadIntent = new Intent(this, UploadKeyActivity.class); - uploadIntent.setData(dataUri); - startActivityForResult(uploadIntent, 0); - } - - private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper) - throws ProviderHelper.NotFoundException { - byte[] blob = (byte[]) providerHelper.getGenericData( - KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), - KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); - String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); - - Intent queryIntent = new Intent(this, ImportKeysActivity.class); - queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); - queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); - - startActivityForResult(queryIntent, REQUEST_CODE_LOOKUP_KEY); - } - private void deleteKey(Uri dataUri, ExportHelper exportHelper) { // Message is received after key is deleted Handler returnHandler = new Handler() { @@ -352,22 +316,11 @@ public class ViewKeyActivity extends ActionBarActivity implements @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case REQUEST_CODE_LOOKUP_KEY: { - if (resultCode == Activity.RESULT_OK) { - ImportResult result = data.getParcelableExtra(ImportKeysActivity.EXTRA_RESULT); - if (result != null) { - result.displayNotify(this); - } - } - break; - } - - default: { - super.onActivityResult(requestCode, resultCode, data); - - break; - } + if (data != null && data.hasExtra(OperationResultParcel.EXTRA_RESULT)) { + OperationResultParcel result = data.getParcelableExtra(OperationResultParcel.EXTRA_RESULT); + result.createNotify(this).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); } } @@ -455,8 +408,8 @@ public class ViewKeyActivity extends ActionBarActivity implements public void handleMessage(Message msg) { switch (msg.what) { case NFC_SENT: - AppMsg.makeText(ViewKeyActivity.this, R.string.nfc_successful, - AppMsg.STYLE_INFO).show(); + Notify.showNotify( + ViewKeyActivity.this, R.string.nfc_successful, Notify.Style.INFO); break; } } @@ -515,22 +468,32 @@ public class ViewKeyActivity extends ActionBarActivity implements String keyIdStr = PgpKeyHelper.convertKeyIdToHex(masterKeyId); getSupportActionBar().setSubtitle(keyIdStr); - // If this key is revoked, it cannot be used for anything! - if (data.getInt(INDEX_UNIFIED_IS_REVOKED) != 0) { + boolean isRevoked = data.getInt(INDEX_UNIFIED_IS_REVOKED) > 0; + boolean isExpired = !data.isNull(INDEX_UNIFIED_EXPIRY) + && new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000).before(new Date()); + + // Note: order is important + if (isRevoked) { + mStatusText.setText(R.string.view_key_revoked); + mStatusText.setTextColor(getResources().getColor(R.color.android_red_dark)); + mStatusImage.setImageDrawable( + getResources().getDrawable(R.drawable.status_signature_revoked_cutout)); + mStatusImage.setColorFilter(getResources().getColor(R.color.android_red_dark), + PorterDuff.Mode.SRC_ATOP); + mStatusDivider.setVisibility(View.VISIBLE); + mStatusLayout.setVisibility(View.VISIBLE); + } else if (isExpired) { + mStatusText.setText(R.string.view_key_expired); + mStatusText.setTextColor(getResources().getColor(R.color.android_orange_dark)); + mStatusImage.setImageDrawable( + getResources().getDrawable(R.drawable.status_signature_expired_cutout)); + mStatusImage.setColorFilter(getResources().getColor(R.color.android_orange_dark), + PorterDuff.Mode.SRC_ATOP); mStatusDivider.setVisibility(View.VISIBLE); - mStatusRevoked.setVisibility(View.VISIBLE); - mStatusExpired.setVisibility(View.GONE); + mStatusLayout.setVisibility(View.VISIBLE); } else { - mStatusRevoked.setVisibility(View.GONE); - - Date expiryDate = new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000); - if (!data.isNull(INDEX_UNIFIED_EXPIRY) && expiryDate.before(new Date())) { - mStatusDivider.setVisibility(View.VISIBLE); - mStatusExpired.setVisibility(View.VISIBLE); - } else { - mStatusDivider.setVisibility(View.GONE); - mStatusExpired.setVisibility(View.GONE); - } + mStatusDivider.setVisibility(View.GONE); + mStatusLayout.setVisibility(View.GONE); } break; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java index f0636cf2c..370a7312f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.database.Cursor; +import android.graphics.PorterDuff; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.LoaderManager; @@ -27,19 +28,21 @@ import android.support.v4.content.Loader; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.ListView; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.ProviderHelper; +import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import java.util.Date; @@ -52,7 +55,9 @@ public class ViewKeyMainFragment extends LoaderFragment implements private View mActionEditDivider; private View mActionEncrypt; private View mActionCertify; - private View mActionCertifyDivider; + private View mActionCertifyText; + private ImageView mActionCertifyImage; + private View mActionUpdate; private ListView mUserIds; @@ -76,7 +81,12 @@ public class ViewKeyMainFragment extends LoaderFragment implements mActionEditDivider = view.findViewById(R.id.view_key_action_edit_divider); mActionEncrypt = view.findViewById(R.id.view_key_action_encrypt); mActionCertify = view.findViewById(R.id.view_key_action_certify); - mActionCertifyDivider = view.findViewById(R.id.view_key_action_certify_divider); + mActionCertifyText = view.findViewById(R.id.view_key_action_certify_text); + mActionCertifyImage = (ImageView) view.findViewById(R.id.view_key_action_certify_image); + // make certify image gray, like action icons + mActionCertifyImage.setColorFilter(getResources().getColor(R.color.tertiary_text_light), + PorterDuff.Mode.SRC_IN); + mActionUpdate = view.findViewById(R.id.view_key_action_update); return root; } @@ -116,6 +126,15 @@ public class ViewKeyMainFragment extends LoaderFragment implements editKey(mDataUri); } }); + mActionUpdate.setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + try { + updateFromKeyserver(mDataUri, new ProviderHelper(getActivity())); + } catch (NotFoundException e) { + Notify.showNotify(getActivity(), R.string.error_key_not_found, Notify.Style.ERROR); + } + } + }); mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); mUserIds.setAdapter(mUserIdsAdapter); @@ -182,6 +201,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements if (data.getInt(INDEX_UNIFIED_IS_REVOKED) != 0) { mActionEdit.setEnabled(false); mActionCertify.setEnabled(false); + mActionCertifyText.setEnabled(false); mActionEncrypt.setEnabled(false); } else { mActionEdit.setEnabled(true); @@ -189,9 +209,11 @@ public class ViewKeyMainFragment extends LoaderFragment implements Date expiryDate = new Date(data.getLong(INDEX_UNIFIED_EXPIRY) * 1000); if (!data.isNull(INDEX_UNIFIED_EXPIRY) && expiryDate.before(new Date())) { mActionCertify.setEnabled(false); + mActionCertifyText.setEnabled(false); mActionEncrypt.setEnabled(false); } else { mActionCertify.setEnabled(true); + mActionCertifyText.setEnabled(true); mActionEncrypt.setEnabled(true); } } @@ -225,7 +247,7 @@ public class ViewKeyMainFragment extends LoaderFragment implements private void encrypt(Uri dataUri) { // If there is no encryption key, don't bother. if (!mHasEncrypt) { - AppMsg.makeText(getActivity(), R.string.error_no_encrypt_subkey, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.error_no_encrypt_subkey, Notify.Style.ERROR); return; } try { @@ -243,18 +265,30 @@ public class ViewKeyMainFragment extends LoaderFragment implements } } + private void updateFromKeyserver(Uri dataUri, ProviderHelper providerHelper) + throws ProviderHelper.NotFoundException { + byte[] blob = (byte[]) providerHelper.getGenericData( + KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri), + KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); + String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); + + Intent queryIntent = new Intent(getActivity(), ImportKeysActivity.class); + queryIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT); + queryIntent.putExtra(ImportKeysActivity.EXTRA_FINGERPRINT, fingerprint); + + startActivityForResult(queryIntent, 0); + } + private void certify(Uri dataUri) { Intent signIntent = new Intent(getActivity(), CertifyKeyActivity.class); signIntent.setData(dataUri); - startActivity(signIntent); + startActivityForResult(signIntent, 0); } private void editKey(Uri dataUri) { Intent editIntent = new Intent(getActivity(), EditKeyActivity.class); editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri)); -// editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); -// startActivityForResult(editIntent, 0); - startActivity(editIntent); + startActivityForResult(editIntent, 0); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java index 52b573f47..54ab76464 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyShareFragment.java @@ -20,7 +20,14 @@ package org.sufficientlysecure.keychain.ui; import android.annotation.TargetApi; import android.content.Intent; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.TransitionDrawable; import android.net.Uri; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.provider.Settings; @@ -33,8 +40,6 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -44,9 +49,10 @@ 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.ProviderHelper.NotFoundException; import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.Notify; import org.sufficientlysecure.keychain.util.QrCodeUtils; import java.io.IOException; @@ -65,6 +71,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements private View mKeyClipboardButton; private View mNfcHelpButton; private View mNfcPrefsButton; + private View mKeyUploadButton; ProviderHelper mProviderHelper; @@ -89,6 +96,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard); mNfcHelpButton = view.findViewById(R.id.view_key_action_nfc_help); mNfcPrefsButton = view.findViewById(R.id.view_key_action_nfc_prefs); + mKeyUploadButton = view.findViewById(R.id.view_key_action_upload); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mNfcPrefsButton.setVisibility(View.VISIBLE); @@ -139,6 +147,12 @@ public class ViewKeyShareFragment extends LoaderFragment implements showNfcPrefs(); } }); + mKeyUploadButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + uploadToKeyserver(); + } + }); return root; } @@ -152,7 +166,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements KeyRings.buildUnifiedKeyRingUri(dataUri), Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); String fingerprint = PgpKeyHelper.convertFingerprintToHex(data); - if(!toClipboard){ + if (!toClipboard) { content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; } else { content = fingerprint; @@ -171,13 +185,13 @@ public class ViewKeyShareFragment extends LoaderFragment implements } else { message = getResources().getString(R.string.key_copied_to_clipboard); } - AppMsg.makeText(getActivity(), message, AppMsg.STYLE_INFO).show(); + Notify.showNotify(getActivity(), message, Notify.Style.OK); } else { // Android will fail with android.os.TransactionTooLargeException if key is too big // see http://www.lonestarprod.com/?p=34 if (content.length() >= 86389) { - AppMsg.makeText(getActivity(), R.string.key_too_big_for_sharing, - AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.key_too_big_for_sharing, + Notify.Style.ERROR); return; } @@ -195,19 +209,20 @@ public class ViewKeyShareFragment extends LoaderFragment implements } } catch (PgpGeneralException e) { Log.e(Constants.TAG, "error processing key!", e); - AppMsg.makeText(getActivity(), R.string.error_key_processing, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR); } catch (IOException e) { Log.e(Constants.TAG, "error processing key!", e); - AppMsg.makeText(getActivity(), R.string.error_key_processing, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.error_key_processing, Notify.Style.ERROR); } catch (ProviderHelper.NotFoundException e) { Log.e(Constants.TAG, "key not found!", e); - AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); + Notify.showNotify(getActivity(), R.string.error_key_not_found, Notify.Style.ERROR); } } private void showQrCodeDialog() { - ShareQrCodeDialogFragment dialog = ShareQrCodeDialogFragment.newInstance(mDataUri); - dialog.show(ViewKeyShareFragment.this.getActivity().getSupportFragmentManager(), "shareQrCodeDialog"); + Intent qrCodeIntent = new Intent(getActivity(), QrCodeActivity.class); + qrCodeIntent.setData(mDataUri); + startActivity(qrCodeIntent); } private void showNfcHelpDialog() { @@ -292,10 +307,7 @@ public class ViewKeyShareFragment extends LoaderFragment implements String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint)); - String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; - mFingerprintQrCode.setImageBitmap( - QrCodeUtils.getQRCodeBitmap(qrCodeContent, QR_CODE_SIZE) - ); + loadQrCode(fingerprint); break; } @@ -311,4 +323,42 @@ public class ViewKeyShareFragment extends LoaderFragment implements */ public void onLoaderReset(Loader<Cursor> loader) { } + + /** + * Load QR Code asynchronously and with a fade in animation + * + * @param fingerprint + */ + private void loadQrCode(final String fingerprint) { + AsyncTask<Void, Void, Bitmap> loadTask = + new AsyncTask<Void, Void, Bitmap>() { + protected Bitmap doInBackground(Void... unused) { + String qrCodeContent = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; + return QrCodeUtils.getQRCodeBitmap(qrCodeContent, QR_CODE_SIZE); + } + + protected void onPostExecute(Bitmap qrCode) { + mFingerprintQrCode.setImageBitmap(qrCode); + + // Transition drawable with a transparent drawable and the final bitmap + final TransitionDrawable td = + new TransitionDrawable(new Drawable[]{ + new ColorDrawable(Color.TRANSPARENT), + new BitmapDrawable(getResources(), qrCode) + }); + + mFingerprintQrCode.setImageDrawable(td); + td.startTransition(200); + } + }; + + loadTask.execute(); + } + + private void uploadToKeyserver() { + Intent uploadIntent = new Intent(getActivity(), UploadKeyActivity.class); + uploadIntent.setData(mDataUri); + startActivityForResult(uploadIntent, 0); + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index 99f959035..4971c535c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -30,20 +30,21 @@ import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.PositionAwareInputStream; import java.io.BufferedInputStream; +import java.io.IOException; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { - public static class FileHasNoContent extends Exception { - + public static class NoValidKeysException extends Exception { } - public static class NonPgpPart extends Exception { + public static class NonPgpPartException extends Exception { private int mCount; - public NonPgpPart(int count) { + public NonPgpPartException(int count) { this.mCount = count; } @@ -67,7 +68,6 @@ public class ImportKeysListLoader @Override public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() { - // This has already been loaded! nvm any further, just return if (mEntryListWrapper != null) { return mEntryListWrapper; @@ -119,9 +119,6 @@ public class ImportKeysListLoader * @return */ private void generateListOfKeyrings(InputData inputData) { - - boolean isEmpty = true; - PositionAwareInputStream progressIn = new PositionAwareInputStream( inputData.getInputStream()); @@ -130,27 +127,23 @@ public class ImportKeysListLoader // armor blocks BufferedInputStream bufferedInput = new BufferedInputStream(progressIn); try { - - // read all available blocks... (asc files can contain many blocks with BEGIN END) - while (bufferedInput.available() > 0) { - // TODO: deal with non-keyring objects? - List<UncachedKeyRing> rings = UncachedKeyRing.fromStream(bufferedInput); - for(UncachedKeyRing key : rings) { - ImportKeysListEntry item = new ImportKeysListEntry(getContext(), key); - mData.add(item); - mParcelableRings.put(item.hashCode(), new ParcelableKeyRing(key.getEncoded())); - isEmpty = false; - } + // parse all keyrings + Iterator<UncachedKeyRing> it = UncachedKeyRing.fromStream(bufferedInput); + while (it.hasNext()) { + UncachedKeyRing ring = it.next(); + ImportKeysListEntry item = new ImportKeysListEntry(getContext(), ring); + mData.add(item); + mParcelableRings.put(item.hashCode(), new ParcelableKeyRing(ring.getEncoded())); } - } catch (Exception e) { - Log.e(Constants.TAG, "Exception on parsing key file!", e); - mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, e); - } + } catch (IOException e) { + Log.e(Constants.TAG, "IOException on parsing key file! Return NoValidKeysException!", e); - if (isEmpty) { - Log.e(Constants.TAG, "File has no content!", new FileHasNoContent()); + NoValidKeysException e1 = new NoValidKeysException(); mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> - (mData, new FileHasNoContent()); + (mData, e1); + } catch (Exception e) { + Log.e(Constants.TAG, "Other Exception on parsing key file!", e); + mEntryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(mData, e); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index 18312660a..6d46f3c8f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.content.Context; import android.database.Cursor; +import android.graphics.PorterDuff; +import android.graphics.Typeface; import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; @@ -156,7 +158,10 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC if (isRevoked) { // set revocation icon (can this even be primary?) - vVerified.setImageResource(R.drawable.key_certify_revoke); + vVerified.setImageResource(R.drawable.status_signature_revoked_cutout); + vVerified.setColorFilter( + mContext.getResources().getColor(R.color.bg_gray), + PorterDuff.Mode.SRC_IN); // disable and strike through text for revoked user ids vName.setEnabled(false); @@ -170,22 +175,33 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC vAddress.setEnabled(true); vComment.setEnabled(true); - // verified: has been verified - // isPrimary: show small star icon for primary user ids - int verified = cursor.getInt(INDEX_VERIFIED); - switch (verified) { + if (isPrimary) { + vName.setTypeface(null, Typeface.BOLD); + vAddress.setTypeface(null, Typeface.BOLD); + } else { + vName.setTypeface(null, Typeface.NORMAL); + vAddress.setTypeface(null, Typeface.NORMAL); + } + + int isVerified = cursor.getInt(INDEX_VERIFIED); + switch (isVerified) { case Certs.VERIFIED_SECRET: - vVerified.setImageResource(isPrimary - ? R.drawable.key_certify_primary_ok_depth0 - : R.drawable.key_certify_ok_depth0); + vVerified.setImageResource(R.drawable.status_signature_verified_cutout); + vVerified.setColorFilter( + mContext.getResources().getColor(R.color.android_green_dark), + PorterDuff.Mode.SRC_IN); break; case Certs.VERIFIED_SELF: - vVerified.setImageResource(isPrimary - ? R.drawable.key_certify_primary_ok_self - : R.drawable.key_certify_ok_self); + vVerified.setImageResource(R.drawable.status_signature_unverified_cutout); + vVerified.setColorFilter( + mContext.getResources().getColor(R.color.bg_gray), + PorterDuff.Mode.SRC_IN); break; default: - vVerified.setImageResource(R.drawable.key_certify_error); + vVerified.setImageResource(R.drawable.status_signature_invalid_cutout); + vVerified.setColorFilter( + mContext.getResources().getColor(R.color.android_red_dark), + PorterDuff.Mode.SRC_IN); break; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index d723f88af..ef2659cf8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -33,8 +33,8 @@ import android.support.v4.app.FragmentActivity; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; -import android.view.WindowManager.LayoutParams; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; @@ -44,8 +44,8 @@ import android.widget.Toast; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; -import org.sufficientlysecure.keychain.pgp.WrappedSecretKey; -import org.sufficientlysecure.keychain.pgp.WrappedSecretKeyRing; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.service.PassphraseCacheService; @@ -62,7 +62,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor private Messenger mMessenger; private EditText mPassphraseEditText; - private boolean mCanKB; /** * Shows passphrase dialog to cache a new passphrase the user enters for using it later for @@ -102,10 +101,10 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor // check if secret key has a passphrase if (!(secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none)) { try { - if (!new ProviderHelper(context).getWrappedSecretKeyRing(secretKeyId).hasPassphrase()) { + if (!new ProviderHelper(context).getCanonicalizedSecretKeyRing(secretKeyId).hasPassphrase()) { throw new PgpGeneralException("No passphrase! No passphrase dialog needed!"); } - } catch(ProviderHelper.NotFoundException e) { + } catch (ProviderHelper.NotFoundException e) { throw new PgpGeneralException("Error: Key not found!", e); } } @@ -120,11 +119,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor return frag; } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - /** * Creates dialog */ @@ -138,7 +132,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor alert.setTitle(R.string.title_authentication); - final WrappedSecretKeyRing secretRing; + final CanonicalizedSecretKeyRing secretRing; String userId; if (secretKeyId == Constants.key.symmetric || secretKeyId == Constants.key.none) { @@ -147,7 +141,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor } else { try { ProviderHelper helper = new ProviderHelper(activity); - secretRing = helper.getWrappedSecretKeyRing(secretKeyId); + secretRing = helper.getCanonicalizedSecretKeyRing(secretKeyId); // yes the inner try/catch block is necessary, otherwise the final variable // above can't be statically verified to have been set in all cases because // the catch clause doesn't return. @@ -165,7 +159,6 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor } }); alert.setCancelable(false); - mCanKB = false; return alert.create(); } @@ -190,7 +183,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor // Early breakout if we are dealing with a symmetric key if (secretRing == null) { PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric, - passphrase, getString(R.string.passp_cache_notif_pwd)); + passphrase, getString(R.string.passp_cache_notif_pwd)); // also return passphrase back to activity Bundle data = new Bundle(); data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); @@ -198,9 +191,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor return; } - WrappedSecretKey unlockedSecretKey = null; + CanonicalizedSecretKey unlockedSecretKey = null; - for(WrappedSecretKey clickSecretKey : secretRing.secretKeyIterator()) { + for (CanonicalizedSecretKey clickSecretKey : secretRing.secretKeyIterator()) { try { boolean unlocked = clickSecretKey.unlock(passphrase); if (unlocked) { @@ -232,9 +225,9 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor try { PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase, - secretRing.getPrimaryUserIdWithFallback()); - } catch(PgpGeneralException e) { - Log.e(Constants.TAG, "adding of a passhrase failed", e); + secretRing.getPrimaryUserIdWithFallback()); + } catch (PgpGeneralException e) { + Log.e(Constants.TAG, "adding of a passphrase failed", e); } if (unlockedSecretKey.getKeyId() != masterKeyId) { @@ -258,20 +251,30 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor } }); - mCanKB = true; - return alert.show(); - } + // Hack to open keyboard. + // This is the only method that I found to work across all Android versions + // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/ + // Notes: * onCreateView can't be used because we want to add buttons to the dialog + // * opening in onActivityCreated does not work on Android 4.4 + mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + mPassphraseEditText.post(new Runnable() { + @Override + public void run() { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT); + } + }); + } + }); + mPassphraseEditText.requestFocus(); - @Override - public void onActivityCreated(Bundle arg0) { - super.onActivityCreated(arg0); - if (mCanKB) { - // request focus and open soft keyboard - mPassphraseEditText.requestFocus(); - getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); - - mPassphraseEditText.setOnEditorActionListener(this); - } + mPassphraseEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE); + mPassphraseEditText.setOnEditorActionListener(this); + + return alert.show(); } @Override @@ -282,6 +285,27 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor sendMessageToHandler(MESSAGE_CANCEL); } + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + Log.d(Constants.TAG, "onDismiss"); + + // hide keyboard on dismiss + hideKeyboard(); + } + + private void hideKeyboard() { + InputMethodManager inputManager = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + + //check if no view has focus: + View v = getActivity().getCurrentFocus(); + if (v == null) + return; + + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); + } + /** * Associate the "done" button on the soft keyboard with the okay button in the view */ 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 93da48b75..1386ed098 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 @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui.dialog; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; +import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Message; @@ -32,6 +33,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager.LayoutParams; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; @@ -164,18 +166,50 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi } }); + // Hack to open keyboard. + // This is the only method that I found to work across all Android versions + // http://turbomanage.wordpress.com/2012/05/02/show-soft-keyboard-automatically-when-edittext-receives-focus/ + // Notes: * onCreateView can't be used because we want to add buttons to the dialog + // * opening in onActivityCreated does not work on Android 4.4 + mPassphraseEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + mPassphraseEditText.post(new Runnable() { + @Override + public void run() { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mPassphraseEditText, InputMethodManager.SHOW_IMPLICIT); + } + }); + } + }); + mPassphraseEditText.requestFocus(); + + mPassphraseAgainEditText.setImeActionLabel(getString(android.R.string.ok), EditorInfo.IME_ACTION_DONE); + mPassphraseAgainEditText.setOnEditorActionListener(this); + return alert.show(); } @Override - public void onActivityCreated(Bundle arg0) { - super.onActivityCreated(arg0); + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); - // request focus and open soft keyboard - mPassphraseEditText.requestFocus(); - getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE); + // hide keyboard on dismiss + hideKeyboard(); + } - mPassphraseAgainEditText.setOnEditorActionListener(this); + private void hideKeyboard() { + InputMethodManager inputManager = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + + //check if no view has focus: + View v = getActivity().getCurrentFocus(); + if (v == null) + return; + + inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0); } /** diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java deleted file mode 100644 index 24608784b..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/ShareQrCodeDialogFragment.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2012-2014 Dominik Schürmann <dominik@dominikschuermann.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package org.sufficientlysecure.keychain.ui.dialog; - -import android.app.Activity; -import android.app.Dialog; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.devspark.appmsg.AppMsg; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.util.Log; -import org.sufficientlysecure.keychain.util.QrCodeUtils; - -public class ShareQrCodeDialogFragment extends DialogFragment { - private static final String ARG_KEY_URI = "uri"; - - private ImageView mImage; - private TextView mText; - - private static final int QR_CODE_SIZE = 1000; - - /** - * Creates new instance of this dialog fragment - */ - public static ShareQrCodeDialogFragment newInstance(Uri dataUri) { - ShareQrCodeDialogFragment frag = new ShareQrCodeDialogFragment(); - Bundle args = new Bundle(); - args.putParcelable(ARG_KEY_URI, dataUri); - - frag.setArguments(args); - - return frag; - } - - /** - * Creates dialog - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final Activity activity = getActivity(); - - Uri dataUri = getArguments().getParcelable(ARG_KEY_URI); - - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(getActivity()); - alert.setTitle(R.string.share_qr_code_dialog_title); - - LayoutInflater inflater = activity.getLayoutInflater(); - View view = inflater.inflate(R.layout.share_qr_code_dialog, null); - alert.setView(view); - - mImage = (ImageView) view.findViewById(R.id.share_qr_code_dialog_image); - mText = (TextView) view.findViewById(R.id.share_qr_code_dialog_text); - - ProviderHelper providerHelper = new ProviderHelper(getActivity()); - String content; - try { - alert.setPositiveButton(R.string.btn_okay, null); - - byte[] blob = (byte[]) providerHelper.getGenericData( - KeyRings.buildUnifiedKeyRingUri(dataUri), - KeyRings.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB); - if (blob == null) { - Log.e(Constants.TAG, "key not found!"); - AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); - return null; - } - - String fingerprint = PgpKeyHelper.convertFingerprintToHex(blob); - mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint); - content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; - setQrCode(content); - } catch (ProviderHelper.NotFoundException e) { - Log.e(Constants.TAG, "key not found!", e); - AppMsg.makeText(getActivity(), R.string.error_key_not_found, AppMsg.STYLE_ALERT).show(); - return null; - } - - return alert.show(); - } - - private void setQrCode(String data) { - mImage.setImageBitmap(QrCodeUtils.getQRCodeBitmap(data, QR_CODE_SIZE)); - } - -} |