From de698b89552a02a445f808cf97d3ce94d35a2777 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 29 Jun 2014 22:34:53 +0200 Subject: add create key capabilities to SaveKeyringParcel --- .../keychain/pgp/PgpKeyOperation.java | 76 +++++++++++++++++++--- .../keychain/pgp/WrappedSecretKeyRing.java | 26 -------- .../keychain/service/KeychainIntentService.java | 44 ++++++++----- .../keychain/service/OperationResultParcel.java | 5 ++ .../keychain/service/SaveKeyringParcel.java | 25 ++++--- 5 files changed, 116 insertions(+), 60 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 1b59e7cc0..bde79eee0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -38,6 +38,7 @@ import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor; import org.spongycastle.openpgp.operator.PGPContentSignerBuilder; import org.spongycastle.openpgp.operator.PGPDigestCalculator; +import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator; import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcaPGPKeyPair; @@ -50,6 +51,8 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogLevel; import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; +import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Primes; import java.io.IOException; @@ -175,6 +178,40 @@ public class PgpKeyOperation { } } + public UncachedKeyRing createSecretKeyRing(SaveKeyringParcel saveParcel, OperationLog log, + int indent) { + + try { + + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_KEYID, indent); + indent += 1; + updateProgress(R.string.progress_building_key, 0, 100); + + if (saveParcel.addSubKeys == null || saveParcel.addSubKeys.isEmpty()) { + log.add(LogLevel.ERROR, LogType.MSG_CR_ERROR_NO_MASTER, indent); + return null; + } + + SubkeyAdd add = saveParcel.addSubKeys.remove(0); + PGPSecretKey masterSecretKey = createKey(add.mAlgorithm, add.mKeysize, + saveParcel.newPassphrase, true); + PGPSecretKeyRing sKR = new PGPSecretKeyRing( + masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator()); + + return internal(sKR, masterSecretKey, saveParcel, saveParcel.newPassphrase, log, indent); + + } catch (PGPException e) { + Log.e(Constants.TAG, "pgp error encoding key", e); + return null; + } catch (IOException e) { + Log.e(Constants.TAG, "io error encoding key", e); + return null; + } catch (PgpGeneralMsgIdException e) { + return null; + } + + } + /** This method introduces a list of modifications specified by a SaveKeyringParcel to a * WrappedSecretKeyRing. * @@ -204,28 +241,49 @@ public class PgpKeyOperation { indent += 1; updateProgress(R.string.progress_building_key, 0, 100); + // Make sure this is called with a proper SaveKeyringParcel + if (saveParcel.mMasterKeyId == null || saveParcel.mMasterKeyId != wsKR.getMasterKeyId()) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_KEYID, indent); + return null; + } + // We work on bouncycastle object level here PGPSecretKeyRing sKR = wsKR.getRing(); - PGPPublicKey masterPublicKey = sKR.getPublicKey(); PGPSecretKey masterSecretKey = sKR.getSecretKey(); + // Make sure the fingerprint matches + if (saveParcel.mFingerprint == null + || !Arrays.equals(saveParcel.mFingerprint, + masterSecretKey.getPublicKey().getFingerprint())) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_FINGERPRINT, indent); + return null; + } + + return internal(sKR, masterSecretKey, saveParcel, passphrase, log, indent); + + } + + private UncachedKeyRing internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey, + SaveKeyringParcel saveParcel, String passphrase, + OperationLog log, int indent) { + + updateProgress(R.string.progress_certifying_master_key, 20, 100); + + PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey(); + // 1. Unlock private key log.add(LogLevel.DEBUG, LogType.MSG_MF_UNLOCK, indent); - PGPPrivateKey masterPrivateKey; { + PGPPrivateKey masterPrivateKey; + { try { PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider( Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor); } catch (PGPException e) { - log.add(LogLevel.ERROR, LogType.MSG_MF_UNLOCK_ERROR, indent+1); + log.add(LogLevel.ERROR, LogType.MSG_MF_UNLOCK_ERROR, indent + 1); return null; } } - if (!Arrays.equals(saveParcel.mFingerprint, sKR.getPublicKey().getFingerprint())) { - return null; - } - - updateProgress(R.string.progress_certifying_master_key, 20, 100); // work on master secret key try { @@ -262,7 +320,7 @@ public class PgpKeyOperation { } - // 4a. For each subkey change, generate new subkey binding certificate + // 4a. For each subkey change, generate new subkey binding certificate for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) { log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE, indent, PgpKeyHelper.convertKeyIdToHex(change.mKeyId)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java index d7148f710..c737b7c46 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/WrappedSecretKeyRing.java @@ -8,16 +8,13 @@ import org.spongycastle.openpgp.PGPPublicKey; import org.spongycastle.openpgp.PGPSecretKey; import org.spongycastle.openpgp.PGPSecretKeyRing; import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor; -import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder; -import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import java.io.IOException; -import java.security.NoSuchProviderException; import java.util.Iterator; public class WrappedSecretKeyRing extends WrappedKeyRing { @@ -91,29 +88,6 @@ public class WrappedSecretKeyRing extends WrappedKeyRing { } } - public UncachedKeyRing changeSecretKeyPassphrase(String oldPassphrase, - String newPassphrase) - throws IOException, PGPException, NoSuchProviderException { - - if (oldPassphrase == null) { - oldPassphrase = ""; - } - if (newPassphrase == null) { - newPassphrase = ""; - } - - PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword( - mRing, - new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider( - Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()), - new JcePBESecretKeyEncryptorBuilder(mRing.getSecretKey() - .getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray())); - - return new UncachedKeyRing(newKeyRing); - - } - public IterableIterator secretKeyIterator() { final Iterator it = mRing.getSecretKeys(); return new IterableIterator(new Iterator() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index e1514b16f..4fbdfab76 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -209,6 +209,10 @@ public class KeychainIntentService extends IntentService mMessenger = (Messenger) extras.get(EXTRA_MESSENGER); Bundle data = extras.getBundle(EXTRA_DATA); + if (data == null) { + Log.e(Constants.TAG, "data extra is null!"); + return; + } OtherHelper.logDebugBundle(data, "EXTRA_DATA"); @@ -320,33 +324,40 @@ public class KeychainIntentService extends IntentService try { /* Input */ SaveKeyringParcel saveParcel = data.getParcelable(SAVE_KEYRING_PARCEL); - long masterKeyId = saveParcel.mMasterKeyId; + if (saveParcel == null) { + Log.e(Constants.TAG, "bug: missing save_keyring_parcel in data!"); + return; + } /* Operation */ ProviderHelper providerHelper = new ProviderHelper(this); PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 10, 50, 100)); try { - String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE); - WrappedSecretKeyRing secRing = providerHelper.getWrappedSecretKeyRing(masterKeyId); - OperationLog log = new OperationLog(); - UncachedKeyRing ring = keyOperations.modifySecretKeyRing(secRing, saveParcel, - passphrase, log, 0); - providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 60, 95, 100)); + UncachedKeyRing ring; + if (saveParcel.mMasterKeyId != null) { + String passphrase = data.getString(SAVE_KEYRING_PASSPHRASE); + WrappedSecretKeyRing secRing = + providerHelper.getWrappedSecretKeyRing(saveParcel.mMasterKeyId); + + ring = keyOperations.modifySecretKeyRing(secRing, saveParcel, + passphrase, log, 0); + } else { + ring = keyOperations.createSecretKeyRing(saveParcel, log, 0); + } + + providerHelper.saveSecretKeyRing(ring, new ProgressScaler(this, 10, 95, 100)); + + if (saveParcel.newPassphrase != null) { + PassphraseCacheService.addCachedPassphrase(this, ring.getMasterKeyId(), + saveParcel.newPassphrase); + } } catch (ProviderHelper.NotFoundException e) { - // UncachedKeyRing ring = keyOperations.(saveParcel); //new Keyring - // save the pair - setProgress(R.string.progress_saving_key_ring, 95, 100); - // providerHelper.saveSecretKeyRing(ring); sendErrorToHandler(e); } setProgress(R.string.progress_done, 100, 100); - if (saveParcel.newPassphrase != null) { - PassphraseCacheService.addCachedPassphrase(this, masterKeyId, saveParcel.newPassphrase); - } - /* Output */ sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY); } catch (Exception e) { @@ -437,7 +448,7 @@ public class KeychainIntentService extends IntentService new FileOutputStream(outputFile)); if (mIsCanceled) { - boolean isDeleted = new File(outputFile).delete(); + new File(outputFile).delete(); } sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); @@ -593,6 +604,7 @@ public class KeychainIntentService extends IntentService return; } Message msg = Message.obtain(); + assert msg != null; msg.arg1 = arg1; if (arg2 != null) { msg.arg2 = arg2; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 7f91ab490..535fa08cf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -233,9 +233,14 @@ public class OperationResultParcel implements Parcelable { MSG_MG_NEW_SUBKEY (R.string.msg_mg_new_subkey), MSG_MG_FOUND_NEW (R.string.msg_mg_found_new), + // secret key create + MSG_CR_ERROR_NO_MASTER (R.string.msg_mr), + // secret key modify MSG_MF (R.string.msg_mr), MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode), + MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint), + MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 020b808b9..1ad19cdd0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -22,10 +22,10 @@ import java.util.ArrayList; */ public class SaveKeyringParcel implements Parcelable { - // the master key id to be edited - public final long mMasterKeyId; - // the key fingerprint, for safety - public final byte[] mFingerprint; + // the master key id to be edited. if this is null, a new one will be created + public Long mMasterKeyId; + // the key fingerprint, for safety. MUST be null for a new key. + public byte[] mFingerprint; public String newPassphrase; @@ -38,9 +38,7 @@ public class SaveKeyringParcel implements Parcelable { public ArrayList revokeUserIds; public ArrayList revokeSubKeys; - public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) { - mMasterKeyId = masterKeyId; - mFingerprint = fingerprint; + public SaveKeyringParcel() { addUserIds = new ArrayList(); addSubKeys = new ArrayList(); changeSubKeys = new ArrayList(); @@ -48,6 +46,12 @@ public class SaveKeyringParcel implements Parcelable { revokeSubKeys = new ArrayList(); } + public SaveKeyringParcel(long masterKeyId, byte[] fingerprint) { + this(); + mMasterKeyId = masterKeyId; + mFingerprint = fingerprint; + } + // performance gain for using Parcelable here would probably be negligible, // use Serializable instead. public static class SubkeyAdd implements Serializable { @@ -75,7 +79,7 @@ public class SaveKeyringParcel implements Parcelable { } public SaveKeyringParcel(Parcel source) { - mMasterKeyId = source.readLong(); + mMasterKeyId = source.readInt() != 0 ? source.readLong() : null; mFingerprint = source.createByteArray(); addUserIds = source.createStringArrayList(); @@ -90,7 +94,10 @@ public class SaveKeyringParcel implements Parcelable { @Override public void writeToParcel(Parcel destination, int flags) { - destination.writeLong(mMasterKeyId); + destination.writeInt(mMasterKeyId == null ? 0 : 1); + if(mMasterKeyId != null) { + destination.writeLong(mMasterKeyId); + } destination.writeByteArray(mFingerprint); destination.writeStringList(addUserIds); -- cgit v1.2.3 From 7408a35e1984c4791ce956bdc2ba225f8e0c3a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 1 Jul 2014 12:36:02 +0200 Subject: edit key: part 3 --- .../keychain/ui/EditKeyFragment.java | 65 ++++---- .../keychain/ui/adapter/UserIdsArrayAdapter.java | 131 ---------------- .../keychain/ui/adapter/UserIdsNewAdapter.java | 146 ++++++++++++++++++ .../ui/dialog/AddUserIdDialogFragment.java | 165 --------------------- 4 files changed, 180 insertions(+), 327 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java (limited to 'OpenKeychain/src/main/java') 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 b6a95a517..079263e64 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -51,7 +51,7 @@ import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; -import org.sufficientlysecure.keychain.ui.adapter.UserIdsArrayAdapter; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsNewAdapter; import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; @@ -76,7 +76,7 @@ public class EditKeyFragment extends LoaderFragment implements private UserIdsAdapter mUserIdsAdapter; private SubkeysAdapter mKeysAdapter; - private UserIdsArrayAdapter mUserIdsAddedAdapter; + private UserIdsNewAdapter mUserIdsAddedAdapter; private Uri mDataUri; @@ -189,7 +189,7 @@ public class EditKeyFragment extends LoaderFragment implements } }); - mUserIdsAddedAdapter = new UserIdsArrayAdapter(getActivity()); + mUserIdsAddedAdapter = new UserIdsNewAdapter(getActivity()); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); @@ -321,34 +321,37 @@ public class EditKeyFragment extends LoaderFragment implements } private void addUserId() { - Handler returnHandler = new Handler() { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case AddUserIdDialogFragment.MESSAGE_OKAY: - Bundle data = message.getData(); - String userId = data.getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID); - - if (userId != null) { - mSaveKeyringParcel.addUserIds.add(userId); - mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); - } - } - getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); - } - }; - - // Create a new Messenger for the communication back - final Messenger messenger = new Messenger(returnHandler); - - DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { - public void run() { - AddUserIdDialogFragment dialogFragment = - AddUserIdDialogFragment.newInstance(messenger); - - dialogFragment.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); - } - }); +// mSaveKeyringParcel.addUserIds.add(userId); +// mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); + + +// Handler returnHandler = new Handler() { +// @Override +// public void handleMessage(Message message) { +// switch (message.what) { +// case AddUserIdDialogFragment.MESSAGE_OKAY: +// Bundle data = message.getData(); +// String userId = data.getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID); +// +// if (userId != null) { + +// } +// } +// getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); +// } +// }; +// +// // Create a new Messenger for the communication back +// final Messenger messenger = new Messenger(returnHandler); +// +// DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { +// public void run() { +// AddUserIdDialogFragment dialogFragment = +// AddUserIdDialogFragment.newInstance(messenger); +// +// dialogFragment.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); +// } +// }); } private void save() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java deleted file mode 100644 index e6445c074..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsArrayAdapter.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.adapter; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Context; -import android.os.Build; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.KeyRing; - -import java.util.List; - -public class UserIdsArrayAdapter extends ArrayAdapter { - protected LayoutInflater mInflater; - protected Activity mActivity; - - protected List mData; - - static class ViewHolder { - public TextView vName; - public TextView vAddress; - public TextView vComment; - public ImageView vVerified; - public ImageView vHasChanges; - public CheckBox vCheckBox; - } - - public UserIdsArrayAdapter(Activity activity) { - super(activity, -1); - mActivity = activity; - mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void setData(List data) { - clear(); - if (data != null) { - this.mData = data; - - // add data to extended ArrayAdapter - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - addAll(data); - } else { - for (String entry : data) { - add(entry); - } - } - } - } - - public List getData() { - return mData; - } - - @Override - public boolean hasStableIds() { - return true; - } - - public View getView(int position, View convertView, ViewGroup parent) { - String entry = mData.get(position); - ViewHolder holder; - if (convertView == null) { - holder = new ViewHolder(); - convertView = mInflater.inflate(R.layout.view_key_userids_item, null); - holder.vName = (TextView) convertView.findViewById(R.id.userId); - holder.vAddress = (TextView) convertView.findViewById(R.id.address); - holder.vComment = (TextView) convertView.findViewById(R.id.comment); - holder.vVerified = (ImageView) convertView.findViewById(R.id.certified); - holder.vHasChanges = (ImageView) convertView.findViewById(R.id.has_changes); - holder.vCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox); - convertView.setTag(holder); - } else { - holder = (ViewHolder) convertView.getTag(); - } - - // user id - String[] splitUserId = KeyRing.splitUserId(entry); - if (splitUserId[0] != null) { - holder.vName.setText(splitUserId[0]); - } else { - holder.vName.setText(R.string.user_id_no_name); - } - if (splitUserId[1] != null) { - holder.vAddress.setText(splitUserId[1]); - holder.vAddress.setVisibility(View.VISIBLE); - } else { - holder.vAddress.setVisibility(View.GONE); - } - if (splitUserId[2] != null) { - holder.vComment.setText(splitUserId[2]); - holder.vComment.setVisibility(View.VISIBLE); - } else { - holder.vComment.setVisibility(View.GONE); - } - - holder.vCheckBox.setVisibility(View.GONE); - - holder.vVerified.setImageResource(R.drawable.key_certify_ok_depth0); - - // all items are "new" - holder.vHasChanges.setVisibility(View.VISIBLE); - - return convertView; - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java new file mode 100644 index 000000000..dffce50a4 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2013-2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.Context; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.KeyRing; + +import java.util.List; + +public class UserIdsNewAdapter extends ArrayAdapter { + protected LayoutInflater mInflater; + protected Activity mActivity; + + protected List mData; + +// static class ViewHolder { +// public TextView vName; +// public TextView vAddress; +// public TextView vComment; +// public ImageView vVerified; +// public ImageView vHasChanges; +// public CheckBox vCheckBox; +// } + + public UserIdsNewAdapter(Activity activity) { + super(activity, -1); + mActivity = activity; + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void setData(List data) { + clear(); + if (data != null) { + this.mData = data; + + // add data to extended ArrayAdapter + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + addAll(data); + } else { + for (String entry : data) { + add(entry); + } + } + } + } + + public List getData() { +// String name = mName.getText().toString(); +// - String email = mAddress.getText().toString(); +// - String comment = mComment.getText().toString(); +// - +// - String userId = null; +// - if (!TextUtils.isEmpty(name)) { +// - userId = name; +// - if (!TextUtils.isEmpty(comment)) { +// - userId += " (" + comment + ")"; +// - } +// - if (!TextUtils.isEmpty(email)) { +// - userId += " <" + email + ">"; +// - } +// - } + return mData; + } + + @Override + public boolean hasStableIds() { + return true; + } + + public View getView(int position, View convertView, ViewGroup parent) { + String entry = mData.get(position); +// ViewHolder holder; +// if (convertView == null) { +// holder = new ViewHolder(); + convertView = mInflater.inflate(R.layout.edit_key_new_userids_item, null); + EditText vName = (EditText) convertView.findViewById(R.id.userId); + EditText vAddress = (EditText) convertView.findViewById(R.id.address); + EditText vComment = (EditText) convertView.findViewById(R.id.comment); +// holder.vVerified = (ImageView) convertView.findViewById(R.id.certified); + ImageView vHasChanges = (ImageView) convertView.findViewById(R.id.has_changes); +// holder.vCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox); +// convertView.setTag(holder); +// } else { +// holder = (ViewHolder) convertView.getTag(); +// } + +// // user id +// String[] splitUserId = KeyRing.splitUserId(entry); +// if (splitUserId[0] != null) { +// vName.setText(splitUserId[0]); +// } else { +// vName.setText(R.string.user_id_no_name); +// } +// if (splitUserId[1] != null) { +// vAddress.setText(splitUserId[1]); +// vAddress.setVisibility(View.VISIBLE); +// } else { +// holder.vAddress.setVisibility(View.GONE); +// } +// if (splitUserId[2] != null) { +// vComment.setText(splitUserId[2]); +// vComment.setVisibility(View.VISIBLE); +// } else { +// holder.vComment.setVisibility(View.GONE); +// } +// +// holder.vCheckBox.setVisibility(View.GONE); +// +// holder.vVerified.setImageResource(R.drawable.key_certify_ok_depth0); +// +// // all items are "new" +// holder.vHasChanges.setVisibility(View.VISIBLE); + + return convertView; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java deleted file mode 100644 index c27266e3f..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddUserIdDialogFragment.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.dialog; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.support.v4.app.DialogFragment; -import android.text.TextUtils; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; -import android.view.inputmethod.EditorInfo; -import android.widget.EditText; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Log; - -public class AddUserIdDialogFragment extends DialogFragment implements EditText.OnEditorActionListener { - private static final String ARG_MESSENGER = "messenger"; - - public static final int MESSAGE_OKAY = 1; - - public static final String MESSAGE_DATA_USER_ID = "user_id"; - - private Messenger mMessenger; - - EditText mName; - EditText mAddress; - EditText mComment; - - /** - * Creates new instance of this dialog fragment - */ - public static AddUserIdDialogFragment newInstance(Messenger messenger) { - AddUserIdDialogFragment frag = new AddUserIdDialogFragment(); - Bundle args = new Bundle(); - args.putParcelable(ARG_MESSENGER, messenger); - - frag.setArguments(args); - - return frag; - } - - /** - * Creates dialog - */ - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - mMessenger = getArguments().getParcelable(ARG_MESSENGER); - - CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(getActivity()); - LayoutInflater inflater = getActivity().getLayoutInflater(); - View view = inflater.inflate(R.layout.add_user_id_dialog, null); - alert.setView(view); - alert.setTitle("Add Identity"); - - mName = (EditText) view.findViewById(R.id.name); - mAddress = (EditText) view.findViewById(R.id.address); - mComment = (EditText) view.findViewById(R.id.comment); - - alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - done(); - } - }); - - alert.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - - - return alert.show(); - } - - @Override - public void onActivityCreated(Bundle arg0) { - super.onActivityCreated(arg0); - // Show soft keyboard automatically - mName.requestFocus(); - getDialog().getWindow().setSoftInputMode( - WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - mComment.setOnEditorActionListener(this); - } - - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (EditorInfo.IME_ACTION_DONE == actionId) { - done(); - return true; - } - return false; - } - - private void done() { - String name = mName.getText().toString(); - String email = mAddress.getText().toString(); - String comment = mComment.getText().toString(); - - String userId = null; - if (!TextUtils.isEmpty(name)) { - userId = name; - if (!TextUtils.isEmpty(comment)) { - userId += " (" + comment + ")"; - } - if (!TextUtils.isEmpty(email)) { - userId += " <" + email + ">"; - } - } - Bundle data = new Bundle(); - data.putString(MESSAGE_DATA_USER_ID, userId); - sendMessageToHandler(MESSAGE_OKAY, data); - - this.dismiss(); - } - - /** - * Send message back to handler which is initialized in a activity - * - * @param what Message integer you want to send - */ - private void sendMessageToHandler(Integer what, Bundle data) { - Message msg = Message.obtain(); - msg.what = what; - if (data != null) { - msg.setData(data); - } - - try { - mMessenger.send(msg); - } catch (RemoteException e) { - Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); - } catch (NullPointerException e) { - Log.w(Constants.TAG, "Messenger is null!", e); - } - } - -} -- cgit v1.2.3 From 287b74885e68ef1d922fc3178f9f446440c4e530 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Jul 2014 14:51:11 +0200 Subject: don't use zero plural string for english closes #703 --- .../org/sufficientlysecure/keychain/provider/ProviderHelper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 28495d51d..b5609a327 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -405,7 +405,11 @@ public class ProviderHelper { // classify and order user ids. primary are moved to the front, revoked to the back, // otherwise the order in the keyfile is preserved. - log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size()); + if (trustedKeys.size() == 0) { + log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING_ZERO); + } else { + log(LogLevel.INFO, LogType.MSG_IP_UID_CLASSIFYING, trustedKeys.size()); + } mIndent += 1; List uids = new ArrayList(); for (String userId : new IterableIterator( -- cgit v1.2.3 From 144a10a3d043686755651852419c5a8bc6619f2a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Jul 2014 14:53:25 +0200 Subject: forgot a line in previous commit --- .../org/sufficientlysecure/keychain/service/OperationResultParcel.java | 1 + 1 file changed, 1 insertion(+) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 7f91ab490..575180505 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -165,6 +165,7 @@ public class OperationResultParcel implements Parcelable { MSG_IP_UID_CERT_ERROR (R.string.msg_ip_uid_cert_error), MSG_IP_UID_CERT_GOOD (R.string.msg_ip_uid_cert_good), MSG_IP_UID_CERTS_UNKNOWN (R.plurals.msg_ip_uid_certs_unknown), + MSG_IP_UID_CLASSIFYING_ZERO (R.string.msg_ip_uid_classifying_zero), MSG_IP_UID_CLASSIFYING (R.plurals.msg_ip_uid_classifying), MSG_IP_UID_REORDER(R.string.msg_ip_uid_reorder), MSG_IP_UID_PROCESSING (R.string.msg_ip_uid_processing), -- cgit v1.2.3 From 9fb92c8642faf9338a13459a717892edbea0855e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Jul 2014 15:03:28 +0200 Subject: fix subkey addition --- .../keychain/pgp/PgpKeyOperation.java | 96 +++++++++++++--------- .../service/KeychainIntentServiceHandler.java | 3 + 2 files changed, 62 insertions(+), 37 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index bde79eee0..528d36da2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -102,18 +102,13 @@ public class PgpKeyOperation { } /** Creates new secret key. */ - private PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase, - boolean isMasterKey) throws PgpGeneralMsgIdException { + private PGPKeyPair createKey(int algorithmChoice, int keySize) throws PgpGeneralMsgIdException { try { if (keySize < 512) { throw new PgpGeneralMsgIdException(R.string.error_key_size_minimum512bit); } - if (passphrase == null) { - passphrase = ""; - } - int algorithm; KeyPairGenerator keyGen; @@ -126,9 +121,6 @@ public class PgpKeyOperation { } case Constants.choice.algorithm.elgamal: { - if (isMasterKey) { - throw new PgpGeneralMsgIdException(R.string.error_master_key_must_not_be_el_gamal); - } keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME); BigInteger p = Primes.getBestPrime(keySize); BigInteger g = new BigInteger("2"); @@ -154,19 +146,8 @@ public class PgpKeyOperation { } // build new key pair - PGPKeyPair keyPair = new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date()); - - // define hashing and signing algos - PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get( - HashAlgorithmTags.SHA1); - - // Build key encrypter and decrypter based on passphrase - PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( - PGPEncryptedData.CAST5, sha1Calc) - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray()); + return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date()); - return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), - sha1Calc, isMasterKey, keyEncryptor); } catch(NoSuchProviderException e) { throw new RuntimeException(e); } catch(NoSuchAlgorithmException e) { @@ -193,12 +174,26 @@ public class PgpKeyOperation { } SubkeyAdd add = saveParcel.addSubKeys.remove(0); - PGPSecretKey masterSecretKey = createKey(add.mAlgorithm, add.mKeysize, - saveParcel.newPassphrase, true); + PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize); + + if (add.mAlgorithm == Constants.choice.algorithm.elgamal) { + throw new PgpGeneralMsgIdException(R.string.error_master_key_must_not_be_el_gamal); + } + + // define hashing and signing algos + PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(HashAlgorithmTags.SHA1); + // Build key encrypter and decrypter based on passphrase + PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( + PGPEncryptedData.CAST5, sha1Calc) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray()); + PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(), + sha1Calc, true, keyEncryptor); + PGPSecretKeyRing sKR = new PGPSecretKeyRing( masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator()); - return internal(sKR, masterSecretKey, saveParcel, saveParcel.newPassphrase, log, indent); + return internal(sKR, masterSecretKey, saveParcel, "", log, indent); } catch (PGPException e) { Log.e(Constants.TAG, "pgp error encoding key", e); @@ -207,6 +202,7 @@ public class PgpKeyOperation { Log.e(Constants.TAG, "io error encoding key", e); return null; } catch (PgpGeneralMsgIdException e) { + Log.e(Constants.TAG, "pgp msg id error", e); return null; } @@ -374,16 +370,36 @@ public class PgpKeyOperation { } log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent); - PGPSecretKey sKey = createKey(add.mAlgorithm, add.mKeysize, passphrase, false); + + // generate a new secret key (privkey only for now) + PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize); + + // add subkey binding signature (making this a sub rather than master key) + PGPPublicKey pKey = keyPair.getPublicKey(); + PGPSignature cert = generateSubkeyBindingSignature( + masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey, + add.mFlags, add.mExpiry); + pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert); + + PGPSecretKey sKey; { + // define hashing and signing algos + PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder() + .build().get(HashAlgorithmTags.SHA1); + + // Build key encrypter and decrypter based on passphrase + PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( + PGPEncryptedData.CAST5, sha1Calc) + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray()); + + sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey, + sha1Calc, false, keyEncryptor); + } + log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID, indent+1, PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); - PGPPublicKey pKey = sKey.getPublicKey(); - PGPSignature cert = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, - sKey, pKey, add.mFlags, add.mExpiry, passphrase); - pKey = PGPPublicKey.addCertification(pKey, cert); - sKey = PGPSecretKey.replacePublicKey(sKey, pKey); - sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey)); + sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey); + } catch (PgpGeneralMsgIdException e) { return null; } @@ -478,6 +494,18 @@ public class PgpKeyOperation { PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPSecretKey sKey, PGPPublicKey pKey, int flags, Long expiry, String passphrase) throws IOException, PGPException, SignatureException { + PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() + .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( + passphrase.toCharArray()); + PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor); + return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey, + pKey, flags, expiry); + } + + private static PGPSignature generateSubkeyBindingSignature( + PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, + PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, Long expiry) + throws IOException, PGPException, SignatureException { // date for signing Date todayDate = new Date(); @@ -485,12 +513,6 @@ public class PgpKeyOperation { // If this key can sign, we need a primary key binding signature if ((flags & KeyFlags.SIGN_DATA) != 0) { - - PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder() - .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build( - passphrase.toCharArray()); - PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor); - // cross-certify signing keys PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); subHashedPacketsGen.setSignatureCreationTime(false, todayDate); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java index d5d02081a..755827482 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java @@ -27,8 +27,10 @@ import android.support.v4.app.FragmentManager; import com.devspark.appmsg.AppMsg; +import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; +import org.sufficientlysecure.keychain.util.Log; public class KeychainIntentServiceHandler extends Handler { @@ -126,6 +128,7 @@ public class KeychainIntentServiceHandler extends Handler { break; default: + Log.e(Constants.TAG, "unknown handler message!"); break; } } -- cgit v1.2.3 From 6f558add35c7c68a6b28a638dadfff75838ef9ba Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Jul 2014 15:05:02 +0200 Subject: use expert create key for key creation testing (revert this later on!) --- .../keychain/ui/KeyListActivity.java | 55 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 7ce7a06aa..849576284 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java @@ -17,21 +17,33 @@ 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.OtherHelper; +import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; 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 java.io.IOException; +import java.util.ArrayList; public class KeyListActivity extends DrawerActivity { @@ -121,9 +133,42 @@ public class KeyListActivity extends DrawerActivity { } private void createKeyExpert() { - Intent intent = new Intent(this, EditKeyActivity.class); - intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); - startActivityForResult(intent, 0); + 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); + Bundle data = message.getData(); + // OtherHelper.logDebugBundle(data, "message reply"); + } + }; + + // fill values for this action + Bundle data = new Bundle(); + + SaveKeyringParcel parcel = new SaveKeyringParcel(); + parcel.addSubKeys.add(new SubkeyAdd(algorithm.rsa, 1024, KeyFlags.CERTIFY_OTHER, null)); + parcel.addSubKeys.add(new SubkeyAdd(algorithm.rsa, 1024, KeyFlags.SIGN_DATA, null)); + parcel.addUserIds.add("swagerinho"); + parcel.newPassphrase = "swag"; + + // 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); } - -} +} \ No newline at end of file -- cgit v1.2.3 From 4f83a4f1636e674bea60d806610f55022c2d9b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 2 Jul 2014 15:10:50 +0200 Subject: Edit key: adding user ids --- .../keychain/service/PassphraseCacheService.java | 31 ++-- .../keychain/ui/EditKeyActivity.java | 2 +- .../keychain/ui/EditKeyFragment.java | 47 ++--- .../keychain/ui/KeyListFragment.java | 14 -- .../keychain/ui/LoaderFragment.java | 24 ++- .../keychain/ui/adapter/UserIdsAdapter.java | 3 + .../keychain/ui/adapter/UserIdsAddedAdapter.java | 206 +++++++++++++++++++++ .../keychain/ui/adapter/UserIdsNewAdapter.java | 146 --------------- .../keychain/ui/widget/FixedListView.java | 4 +- .../keychain/ui/widget/SectionView.java | 2 +- 10 files changed, 258 insertions(+), 221 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java index d42bae67a..28f230f71 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/PassphraseCacheService.java @@ -49,7 +49,6 @@ import java.util.Date; * convenience. */ public class PassphraseCacheService extends Service { - public static final String TAG = Constants.TAG + ": PassphraseCacheService"; public static final String ACTION_PASSPHRASE_CACHE_ADD = Constants.INTENT_PREFIX + "PASSPHRASE_CACHE_ADD"; @@ -83,7 +82,7 @@ public class PassphraseCacheService extends Service { * @param passphrase */ public static void addCachedPassphrase(Context context, long keyId, String passphrase) { - Log.d(TAG, "cacheNewPassphrase() for " + keyId); + Log.d(Constants.TAG, "PassphraseCacheService.cacheNewPassphrase() for " + keyId); Intent intent = new Intent(context, PassphraseCacheService.class); intent.setAction(ACTION_PASSPHRASE_CACHE_ADD); @@ -103,7 +102,7 @@ public class PassphraseCacheService extends Service { * @return passphrase or null (if no passphrase is cached for this keyId) */ public static String getCachedPassphrase(Context context, long keyId) { - Log.d(TAG, "getCachedPassphrase() get masterKeyId for " + keyId); + Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphrase() get masterKeyId for " + keyId); Intent intent = new Intent(context, PassphraseCacheService.class); intent.setAction(ACTION_PASSPHRASE_CACHE_GET); @@ -159,7 +158,7 @@ public class PassphraseCacheService extends Service { private String getCachedPassphraseImpl(long keyId) { // passphrase for symmetric encryption? if (keyId == Constants.key.symmetric) { - Log.d(TAG, "getCachedPassphraseImpl() for symmetric encryption"); + Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for symmetric encryption"); String cachedPassphrase = mPassphraseCache.get(Constants.key.symmetric); if (cachedPassphrase == null) { return null; @@ -170,7 +169,7 @@ public class PassphraseCacheService extends Service { // try to get master key id which is used as an identifier for cached passphrases try { - Log.d(TAG, "getCachedPassphraseImpl() for masterKeyId " + keyId); + Log.d(Constants.TAG, "PassphraseCacheService.getCachedPassphraseImpl() for masterKeyId " + keyId); WrappedSecretKeyRing key = new ProviderHelper(this).getWrappedSecretKeyRing( KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId)); // no passphrase needed? just add empty string and return it, then @@ -184,18 +183,18 @@ public class PassphraseCacheService extends Service { // get cached passphrase String cachedPassphrase = mPassphraseCache.get(keyId); if (cachedPassphrase == null) { - Log.d(TAG, "Passphrase not (yet) cached, returning null"); + Log.d(Constants.TAG, "PassphraseCacheService Passphrase not (yet) cached, returning null"); // not really an error, just means the passphrase is not cached but not empty either return null; } // set it again to reset the cache life cycle - Log.d(TAG, "Cache passphrase again when getting it!"); + Log.d(Constants.TAG, "PassphraseCacheService Cache passphrase again when getting it!"); addCachedPassphrase(this, keyId, cachedPassphrase); return cachedPassphrase; } catch (ProviderHelper.NotFoundException e) { - Log.e(TAG, "Passphrase for unknown key was requested!"); + Log.e(Constants.TAG, "PassphraseCacheService Passphrase for unknown key was requested!"); return null; } } @@ -212,7 +211,7 @@ public class PassphraseCacheService extends Service { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - Log.d(TAG, "Received broadcast..."); + Log.d(Constants.TAG, "PassphraseCacheService Received broadcast..."); if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) { long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); @@ -248,7 +247,7 @@ public class PassphraseCacheService extends Service { */ @Override public int onStartCommand(Intent intent, int flags, int startId) { - Log.d(TAG, "onStartCommand()"); + Log.d(Constants.TAG, "PassphraseCacheService.onStartCommand()"); // register broadcastreceiver registerReceiver(); @@ -259,8 +258,8 @@ public class PassphraseCacheService extends Service { long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1); String passphrase = intent.getStringExtra(EXTRA_PASSPHRASE); - Log.d(TAG, - "Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: " + Log.d(Constants.TAG, + "PassphraseCacheService Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with keyId: " + keyId + ", ttl: " + ttl); // add keyId and passphrase to memory @@ -285,10 +284,10 @@ public class PassphraseCacheService extends Service { try { messenger.send(msg); } catch (RemoteException e) { - Log.e(Constants.TAG, "Sending message failed", e); + Log.e(Constants.TAG, "PassphraseCacheService Sending message failed", e); } } else { - Log.e(Constants.TAG, "Intent or Intent Action not supported!"); + Log.e(Constants.TAG, "PassphraseCacheService Intent or Intent Action not supported!"); } } @@ -305,11 +304,11 @@ public class PassphraseCacheService extends Service { // remove passphrase corresponding to keyId from memory mPassphraseCache.remove(keyId); - Log.d(TAG, "Timeout of keyId " + keyId + ", removed from memory!"); + Log.d(Constants.TAG, "PassphraseCacheService Timeout of keyId " + keyId + ", removed from memory!"); // stop whole service if no cached passphrases remaining if (mPassphraseCache.size() == 0) { - Log.d(TAG, "No passphrases remaining in memory, stopping service!"); + Log.d(Constants.TAG, "PassphraseCacheServic No passphrases remaining in memory, stopping service!"); stopSelf(); } } 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 d734c31db..906ed347e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -231,7 +231,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { // get new key from data bundle returned from service - Bundle data = message.getData(); + Bundle data = message.getDataAsStringList(); ArrayList newKeys = PgpConversionHelper.BytesToPGPSecretKeyList(data 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 079263e64..ccb525c05 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -51,13 +51,14 @@ import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; -import org.sufficientlysecure.keychain.ui.adapter.UserIdsNewAdapter; -import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; import org.sufficientlysecure.keychain.util.Log; +import java.util.ArrayList; + public class EditKeyFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { @@ -76,7 +77,8 @@ public class EditKeyFragment extends LoaderFragment implements private UserIdsAdapter mUserIdsAdapter; private SubkeysAdapter mKeysAdapter; - private UserIdsNewAdapter mUserIdsAddedAdapter; + private UserIdsAddedAdapter mUserIdsAddedAdapter; + private ArrayList mUserIdsAddedData; private Uri mDataUri; @@ -189,9 +191,10 @@ public class EditKeyFragment extends LoaderFragment implements } }); - mUserIdsAddedAdapter = new UserIdsNewAdapter(getActivity()); + // TODO: from savedInstance?! + mUserIdsAddedData = new ArrayList(); + mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mUserIdsAddedData); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); - mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0); mKeysList.setAdapter(mKeysAdapter); @@ -321,40 +324,12 @@ public class EditKeyFragment extends LoaderFragment implements } private void addUserId() { -// mSaveKeyringParcel.addUserIds.add(userId); -// mUserIdsAddedAdapter.setData(mSaveKeyringParcel.addUserIds); - - -// Handler returnHandler = new Handler() { -// @Override -// public void handleMessage(Message message) { -// switch (message.what) { -// case AddUserIdDialogFragment.MESSAGE_OKAY: -// Bundle data = message.getData(); -// String userId = data.getString(AddUserIdDialogFragment.MESSAGE_DATA_USER_ID); -// -// if (userId != null) { - -// } -// } -// getLoaderManager().getLoader(LOADER_ID_USER_IDS).forceLoad(); -// } -// }; -// -// // Create a new Messenger for the communication back -// final Messenger messenger = new Messenger(returnHandler); -// -// DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { -// public void run() { -// AddUserIdDialogFragment dialogFragment = -// AddUserIdDialogFragment.newInstance(messenger); -// -// dialogFragment.show(getActivity().getSupportFragmentManager(), "addUserIdDialog"); -// } -// }); + mUserIdsAddedAdapter.add(new UserIdsAddedAdapter.UserIdModel()); } private void save() { + Log.d(Constants.TAG, "data: " + mUserIdsAddedAdapter.getDataAsStringList()); + String passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSaveKeyringParcel.mMasterKeyId); if (passphrase == null) { 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 d2cb5283d..68ac6d30c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -441,7 +441,6 @@ public class KeyListFragment extends LoaderFragment TextView mMainUserIdRest; View mStatusDivider; FrameLayout mStatusLayout; - ImageButton mButton; TextView mRevoked; ImageView mVerified; } @@ -454,7 +453,6 @@ public class KeyListFragment extends LoaderFragment holder.mMainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); holder.mStatusDivider = (View) view.findViewById(R.id.status_divider); holder.mStatusLayout = (FrameLayout) view.findViewById(R.id.status_layout); - holder.mButton = (ImageButton) view.findViewById(R.id.edit); holder.mRevoked = (TextView) view.findViewById(R.id.revoked); holder.mVerified = (ImageView) view.findViewById(R.id.verified); view.setTag(holder); @@ -496,21 +494,9 @@ public class KeyListFragment extends LoaderFragment h.mStatusLayout.setVisibility(View.VISIBLE); h.mRevoked.setVisibility(View.GONE); h.mVerified.setVisibility(View.GONE); - h.mButton.setVisibility(View.VISIBLE); - - final long id = cursor.getLong(INDEX_MASTER_KEY_ID); - h.mButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - Intent editIntent = new Intent(getActivity(), EditKeyActivity.class); - editIntent.setData(KeyRingData.buildSecretKeyRingUri(Long.toString(id))); - editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); - startActivityForResult(editIntent, 0); - } - }); } else { // this is a public key - hide the edit mButton, show if it's revoked h.mStatusDivider.setVisibility(View.GONE); - h.mButton.setVisibility(View.GONE); boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; boolean isExpired = !cursor.isNull(INDEX_EXPIRY) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java index 87ab1bb8c..8634070cc 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/LoaderFragment.java @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + package org.sufficientlysecure.keychain.ui; import android.os.Bundle; @@ -9,14 +26,14 @@ import android.view.animation.AnimationUtils; import org.sufficientlysecure.keychain.R; -/** This is a fragment helper class, which implements a generic +/** + * This is a fragment helper class, which implements a generic * progressbar/container view. - * + *

* To use it in a fragment, simply subclass, use onCreateView to create the * layout's root view, and ues getContainer() as root view of your subclass. * The layout shows a progress bar by default, and can be switched to the * actual contents by calling setContentShown(). - * */ public class LoaderFragment extends Fragment { private boolean mContentShown; @@ -35,7 +52,6 @@ public class LoaderFragment extends Fragment { mContentShown = false; return root; - } protected ViewGroup getContainer() { 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 7fc78dc41..7bf9334b8 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 @@ -123,6 +123,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC TextView vComment = (TextView) view.findViewById(R.id.comment); ImageView vVerified = (ImageView) view.findViewById(R.id.certified); ImageView vHasChanges = (ImageView) view.findViewById(R.id.has_changes); + ImageView vEditImage = (ImageView) view.findViewById(R.id.edit_image); String userId = cursor.getString(mIndexUserId); String[] splitUserId = KeyRing.splitUserId(userId); @@ -167,8 +168,10 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC } else { vHasChanges.setVisibility(View.GONE); } + vEditImage.setVisibility(View.VISIBLE); } else { vHasChanges.setVisibility(View.GONE); + vEditImage.setVisibility(View.GONE); } if (isRevoked) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java new file mode 100644 index 000000000..ff0ec70f3 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +import android.app.Activity; +import android.content.Context; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Patterns; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; +import android.widget.ImageButton; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; + +public class UserIdsAddedAdapter extends ArrayAdapter { + private LayoutInflater mInflater; + private Activity mActivity; + + private ArrayAdapter mAutoCompleteNameAdapter; + private ArrayAdapter mAutoCompleteEmailAdapter; + + // hold a private reference to the underlying data List + private List mData; + + public static class UserIdModel { + String name = ""; + String address = ""; + String comment = ""; + + @Override + public String toString() { + String userId = null; + if (!TextUtils.isEmpty(name)) { + userId = name; + if (!TextUtils.isEmpty(comment)) { + userId += " (" + comment + ")"; + } + if (!TextUtils.isEmpty(address)) { + userId += " <" + address + ">"; + } + } + return userId; + } + } + + public UserIdsAddedAdapter(Activity activity, List data) { + super(activity, -1, data); + mActivity = activity; + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mData = data; + mAutoCompleteNameAdapter = new ArrayAdapter + (mActivity, android.R.layout.simple_dropdown_item_1line, + ContactHelper.getPossibleUserNames(mActivity) + ); + mAutoCompleteEmailAdapter = new ArrayAdapter + (mActivity, android.R.layout.simple_dropdown_item_1line, + ContactHelper.getPossibleUserEmails(mActivity) + ); + } + + public List getDataAsStringList() { + ArrayList out = new ArrayList(); + for (UserIdModel id : mData) { + out.add(id.toString()); + } + + return out; + } + + static class ViewHolder { + public AutoCompleteTextView vAddress; + public AutoCompleteTextView vName; + public EditText vComment; + public ImageButton vDelete; + // also hold a reference to the model item + public UserIdModel mModel; + } + + public View getView(final int position, View convertView, ViewGroup parent) { + if (convertView == null) { + // Not recycled, inflate a new view + convertView = mInflater.inflate(R.layout.edit_key_user_id_added_item, null); + final ViewHolder viewHolder = new ViewHolder(); + viewHolder.vAddress = (AutoCompleteTextView) convertView.findViewById(R.id.user_id_added_item_address); + viewHolder.vName = (AutoCompleteTextView) convertView.findViewById(R.id.user_id_added_item_name); + viewHolder.vComment = (EditText) convertView.findViewById(R.id.user_id_added_item_comment); + viewHolder.vDelete = (ImageButton) convertView.findViewById(R.id.user_id_added_item_delete); + convertView.setTag(viewHolder); + + viewHolder.vAddress.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + // update referenced item in view holder + viewHolder.mModel.address = s.toString(); + + // show icon on valid email addresses + if (viewHolder.mModel.address.length() > 0) { + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(viewHolder.mModel.address); + if (emailMatcher.matches()) { + viewHolder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_ok, 0); + } else { + viewHolder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, + R.drawable.uid_mail_bad, 0); + } + } else { + // remove drawable if email is empty + viewHolder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + }); + + viewHolder.vName.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + // update referenced item in view holder + viewHolder.mModel.name = s.toString(); + } + }); + + viewHolder.vComment.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + // update referenced item in view holder + viewHolder.mModel.comment = s.toString(); + } + }); + + viewHolder.vDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // remove reference model item from adapter (data and notify about change) + UserIdsAddedAdapter.this.remove(viewHolder.mModel); + } + }); + + } + final ViewHolder holder = (ViewHolder) convertView.getTag(); + + // save reference to model item + holder.mModel = getItem(position); + + holder.vAddress.setText(holder.mModel.address); + holder.vAddress.setThreshold(1); // Start working from first character + holder.vAddress.setAdapter(mAutoCompleteEmailAdapter); + + holder.vName.setText(holder.mModel.name); + holder.vName.setThreshold(1); // Start working from first character + holder.vName.setAdapter(mAutoCompleteNameAdapter); + + holder.vComment.setText(holder.mModel.comment); + + return convertView; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java deleted file mode 100644 index dffce50a4..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsNewAdapter.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2013-2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.adapter; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Context; -import android.os.Build; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.CheckBox; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TextView; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.pgp.KeyRing; - -import java.util.List; - -public class UserIdsNewAdapter extends ArrayAdapter { - protected LayoutInflater mInflater; - protected Activity mActivity; - - protected List mData; - -// static class ViewHolder { -// public TextView vName; -// public TextView vAddress; -// public TextView vComment; -// public ImageView vVerified; -// public ImageView vHasChanges; -// public CheckBox vCheckBox; -// } - - public UserIdsNewAdapter(Activity activity) { - super(activity, -1); - mActivity = activity; - mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void setData(List data) { - clear(); - if (data != null) { - this.mData = data; - - // add data to extended ArrayAdapter - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - addAll(data); - } else { - for (String entry : data) { - add(entry); - } - } - } - } - - public List getData() { -// String name = mName.getText().toString(); -// - String email = mAddress.getText().toString(); -// - String comment = mComment.getText().toString(); -// - -// - String userId = null; -// - if (!TextUtils.isEmpty(name)) { -// - userId = name; -// - if (!TextUtils.isEmpty(comment)) { -// - userId += " (" + comment + ")"; -// - } -// - if (!TextUtils.isEmpty(email)) { -// - userId += " <" + email + ">"; -// - } -// - } - return mData; - } - - @Override - public boolean hasStableIds() { - return true; - } - - public View getView(int position, View convertView, ViewGroup parent) { - String entry = mData.get(position); -// ViewHolder holder; -// if (convertView == null) { -// holder = new ViewHolder(); - convertView = mInflater.inflate(R.layout.edit_key_new_userids_item, null); - EditText vName = (EditText) convertView.findViewById(R.id.userId); - EditText vAddress = (EditText) convertView.findViewById(R.id.address); - EditText vComment = (EditText) convertView.findViewById(R.id.comment); -// holder.vVerified = (ImageView) convertView.findViewById(R.id.certified); - ImageView vHasChanges = (ImageView) convertView.findViewById(R.id.has_changes); -// holder.vCheckBox = (CheckBox) convertView.findViewById(R.id.checkBox); -// convertView.setTag(holder); -// } else { -// holder = (ViewHolder) convertView.getTag(); -// } - -// // user id -// String[] splitUserId = KeyRing.splitUserId(entry); -// if (splitUserId[0] != null) { -// vName.setText(splitUserId[0]); -// } else { -// vName.setText(R.string.user_id_no_name); -// } -// if (splitUserId[1] != null) { -// vAddress.setText(splitUserId[1]); -// vAddress.setVisibility(View.VISIBLE); -// } else { -// holder.vAddress.setVisibility(View.GONE); -// } -// if (splitUserId[2] != null) { -// vComment.setText(splitUserId[2]); -// vComment.setVisibility(View.VISIBLE); -// } else { -// holder.vComment.setVisibility(View.GONE); -// } -// -// holder.vCheckBox.setVisibility(View.GONE); -// -// holder.vVerified.setImageResource(R.drawable.key_certify_ok_depth0); -// -// // all items are "new" -// holder.vHasChanges.setVisibility(View.VISIBLE); - - return convertView; - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java index da29f808a..294ff1500 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/FixedListView.java @@ -25,9 +25,7 @@ import android.widget.ListView; * Automatically calculate height of ListView based on contained items. This enables to put this * ListView into a ScrollView without messing up. *

- * from - * http://stackoverflow.com/questions/2419246/how-do-i-create-a-listview-thats-not-in-a-scrollview- - * or-has-the-scrollview-dis + * from http://stackoverflow.com/a/3580117 */ public class FixedListView extends ListView { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java index 4ecc96cee..cd5671801 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SectionView.java @@ -388,7 +388,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { // get new key from data bundle returned from service - Bundle data = message.getData(); + Bundle data = message.getDataAsStringList(); UncachedSecretKey newKey = PgpConversionHelper .BytesToPGPSecretKey(data .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); -- cgit v1.2.3 From 3d34eb8ca44c03b74577158b82460b7e1842e35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 2 Jul 2014 15:42:38 +0200 Subject: edit key: work on saving --- .../keychain/ui/EditKeyFragment.java | 17 +++++++++++------ .../keychain/ui/KeyListFragment.java | 8 ++------ .../keychain/ui/adapter/UserIdsAddedAdapter.java | 22 +++++++++++----------- 3 files changed, 24 insertions(+), 23 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 ccb525c05..1defa4034 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -328,8 +328,6 @@ public class EditKeyFragment extends LoaderFragment implements } private void save() { - Log.d(Constants.TAG, "data: " + mUserIdsAddedAdapter.getDataAsStringList()); - String passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSaveKeyringParcel.mMasterKeyId); if (passphrase == null) { @@ -338,17 +336,23 @@ public class EditKeyFragment extends LoaderFragment implements @Override public void handleMessage(Message message) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - saveFinal(); + String passphrase = + message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); + Log.d(Constants.TAG, "after caching passphrase"); + saveFinal(passphrase); } } } ); - + } else { + saveFinal(passphrase); } - } - private void saveFinal() { + private void saveFinal(String passphrase) { + Log.d(Constants.TAG, "add userids to parcel: " + mUserIdsAddedAdapter.getDataAsStringList()); + mSaveKeyringParcel.addUserIds = mUserIdsAddedAdapter.getDataAsStringList(); + // Message is received after importing is done in KeychainIntentService KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler( getActivity(), @@ -386,6 +390,7 @@ public class EditKeyFragment extends LoaderFragment implements // fill values for this action Bundle data = new Bundle(); + data.putString(KeychainIntentService.SAVE_KEYRING_PASSPHRASE, passphrase); data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, mSaveKeyringParcel); intent.putExtra(KeychainIntentService.EXTRA_DATA, data); 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 68ac6d30c..d6b0c7944 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -439,7 +439,6 @@ public class KeyListFragment extends LoaderFragment private class ItemViewHolder { TextView mMainUserId; TextView mMainUserIdRest; - View mStatusDivider; FrameLayout mStatusLayout; TextView mRevoked; ImageView mVerified; @@ -451,7 +450,6 @@ 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.mStatusDivider = (View) view.findViewById(R.id.status_divider); 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); @@ -489,14 +487,12 @@ 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 - show the edit mButton - h.mStatusDivider.setVisibility(View.VISIBLE); + // 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 - hide the edit mButton, show if it's revoked - h.mStatusDivider.setVisibility(View.GONE); + // this is a public key - show if it's revoked boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; boolean isExpired = !cursor.isNull(INDEX_EXPIRY) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java index ff0ec70f3..137217ff4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java @@ -55,15 +55,12 @@ public class UserIdsAddedAdapter extends ArrayAdapter"; - } + String userId = name; + if (!TextUtils.isEmpty(comment)) { + userId += " (" + comment + ")"; + } + if (!TextUtils.isEmpty(address)) { + userId += " <" + address + ">"; } return userId; } @@ -84,10 +81,13 @@ public class UserIdsAddedAdapter extends ArrayAdapter getDataAsStringList() { + public ArrayList getDataAsStringList() { ArrayList out = new ArrayList(); for (UserIdModel id : mData) { - out.add(id.toString()); + // ignore empty user ids + if (!TextUtils.isEmpty(id.toString())) { + out.add(id.toString()); + } } return out; -- cgit v1.2.3 From ebcd243e975ce8f04298f6cd94cb940bfcea3d59 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 2 Jul 2014 16:02:56 +0200 Subject: support changing primary user id in SaveKeyringParcel Closes #695 --- .../keychain/pgp/PgpKeyOperation.java | 115 ++++++++++++++++++++- .../keychain/service/OperationResultParcel.java | 2 + 2 files changed, 113 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java index 528d36da2..9a08290e4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java @@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.service.OperationResultParcel.LogType; import org.sufficientlysecure.keychain.service.OperationResultParcel.OperationLog; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd; +import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Primes; @@ -66,6 +67,7 @@ import java.security.SignatureException; import java.util.Arrays; import java.util.Calendar; import java.util.Date; +import java.util.Iterator; import java.util.TimeZone; /** @@ -289,14 +291,42 @@ public class PgpKeyOperation { // 2a. Add certificates for new user ids for (String userId : saveParcel.addUserIds) { log.add(LogLevel.INFO, LogType.MSG_MF_UID_ADD, indent); + + // this operation supersedes all previous binding and revocation certificates, + // so remove those to retain assertions from canonicalization for later operations + @SuppressWarnings("unchecked") + Iterator it = modifiedPublicKey.getSignaturesForID(userId); + if (it != null) { + for (PGPSignature cert : new IterableIterator(it)) { + // if it's not a self cert, never mind + if (cert.getKeyID() != masterPublicKey.getKeyID()) { + continue; + } + if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION + || cert.getSignatureType() == PGPSignature.NO_CERTIFICATION + || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION + || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION + || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, cert); + } + } + } + + // if it's supposed to be primary, we can do that here as well + boolean isPrimary = saveParcel.changePrimaryUserId != null + && userId.equals(saveParcel.changePrimaryUserId); + // generate and add new certificate PGPSignature cert = generateUserIdSignature(masterPrivateKey, - masterPublicKey, userId, false); + masterPublicKey, userId, isPrimary); modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert); } // 2b. Add revocations for revoked user ids for (String userId : saveParcel.revokeUserIds) { log.add(LogLevel.INFO, LogType.MSG_MF_UID_REVOKE, indent); + // a duplicate revocatin will be removed during canonicalization, so no need to + // take care of that here. PGPSignature cert = generateRevocationSignature(masterPrivateKey, masterPublicKey, userId); modifiedPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, cert); @@ -305,7 +335,84 @@ public class PgpKeyOperation { // 3. If primary user id changed, generate new certificates for both old and new if (saveParcel.changePrimaryUserId != null) { log.add(LogLevel.INFO, LogType.MSG_MF_UID_PRIMARY, indent); - // todo + + // we work on the modifiedPublicKey here, to respect new or newly revoked uids + // noinspection unchecked + for (String userId : new IterableIterator(modifiedPublicKey.getUserIDs())) { + boolean isRevoked = false; + PGPSignature currentCert = null; + // noinspection unchecked + for (PGPSignature cert : new IterableIterator( + masterPublicKey.getSignaturesForID(userId))) { + // if it's not a self cert, never mind + if (cert.getKeyID() != masterPublicKey.getKeyID()) { + continue; + } + // we know from canonicalization that if there is any revocation here, it + // is valid and not superseded by a newer certification. + if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) { + isRevoked = true; + continue; + } + // we know from canonicalization that there is only one binding + // certification here, so we can just work with the first one. + if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || + cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || + cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || + cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) { + currentCert = cert; + } + } + + if (currentCert == null) { + // no certificate found?! error error error + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_INTEGRITY, indent); + return null; + } + + // we definitely should not update certifications of revoked keys, so just leave it. + if (isRevoked) { + // revoked user ids cannot be primary! + if (userId.equals(saveParcel.changePrimaryUserId)) { + log.add(LogLevel.ERROR, LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent); + return null; + } + continue; + } + + // if this is~ the/a primary user id + if (currentCert.hasSubpackets() && currentCert.getHashedSubPackets().isPrimaryUserID()) { + // if it's the one we want, just leave it as is + if (userId.equals(saveParcel.changePrimaryUserId)) { + continue; + } + // otherwise, generate new non-primary certification + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, currentCert); + PGPSignature newCert = generateUserIdSignature( + masterPrivateKey, masterPublicKey, userId, false); + modifiedPublicKey = PGPPublicKey.addCertification( + modifiedPublicKey, userId, newCert); + continue; + } + + // if we are here, this is not currently a primary user id + + // if it should be + if (userId.equals(saveParcel.changePrimaryUserId)) { + // add shiny new primary user id certificate + modifiedPublicKey = PGPPublicKey.removeCertification( + modifiedPublicKey, userId, currentCert); + PGPSignature newCert = generateUserIdSignature( + masterPrivateKey, masterPublicKey, userId, true); + modifiedPublicKey = PGPPublicKey.addCertification( + modifiedPublicKey, userId, newCert); + } + + // user id is not primary and is not supposed to be - nothing to do here. + + } + } // Update the secret key ring @@ -315,7 +422,6 @@ public class PgpKeyOperation { sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey); } - // 4a. For each subkey change, generate new subkey binding certificate for (SaveKeyringParcel.SubkeyChange change : saveParcel.changeSubKeys) { log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_CHANGE, @@ -334,7 +440,8 @@ public class PgpKeyOperation { return null; } - // generate and add new signature + // generate and add new signature. we can be sloppy here and just leave the old one, + // it will be removed during canonicalization PGPSignature sig = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, sKey, pKey, change.mFlags, change.mExpiry, passphrase); pKey = PGPPublicKey.addCertification(pKey, sig); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java index 535fa08cf..f5d5b8f97 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/OperationResultParcel.java @@ -241,6 +241,8 @@ public class OperationResultParcel implements Parcelable { MSG_MF_ERROR_ENCODE (R.string.msg_mf_error_encode), MSG_MF_ERROR_FINGERPRINT (R.string.msg_mf_error_fingerprint), MSG_MF_ERROR_KEYID (R.string.msg_mf_error_keyid), + MSG_MF_ERROR_INTEGRITY (R.string.msg_mf_error_integrity), + MSG_MF_ERROR_REVOKED_PRIMARY (R.string.msg_mf_error_revoked_primary), MSG_MF_ERROR_PGP (R.string.msg_mf_error_pgp), MSG_MF_ERROR_SIG (R.string.msg_mf_error_sig), MSG_MF_PASSPHRASE (R.string.msg_mf_passphrase), -- cgit v1.2.3 From 94a58f3aa8e202b1a7d5587aeeb85b13a99d4895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 2 Jul 2014 16:33:30 +0200 Subject: remove init methods from adapter --- .../keychain/service/KeychainIntentService.java | 1 + .../keychain/ui/EditKeyFragment.java | 16 ++--- .../keychain/ui/adapter/SubkeysAdapter.java | 81 ++++++++-------------- .../keychain/ui/adapter/UserIdsAdapter.java | 43 ++++-------- 4 files changed, 53 insertions(+), 88 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index e1514b16f..48119a831 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -343,6 +343,7 @@ public class KeychainIntentService extends IntentService setProgress(R.string.progress_done, 100, 100); + // cache new passphrase if (saveParcel.newPassphrase != null) { PassphraseCacheService.addCachedPassphrase(this, masterKeyId, saveParcel.newPassphrase); } 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 1defa4034..8c7606cf9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -65,7 +65,7 @@ public class EditKeyFragment extends LoaderFragment implements public static final String ARG_DATA_URI = "uri"; private ListView mUserIdsList; - private ListView mKeysList; + private ListView mSubkeysList; private ListView mUserIdsAddedList; private ListView mKeysAddedList; private View mChangePassphrase; @@ -76,7 +76,7 @@ public class EditKeyFragment extends LoaderFragment implements private static final int LOADER_ID_KEYS = 1; private UserIdsAdapter mUserIdsAdapter; - private SubkeysAdapter mKeysAdapter; + private SubkeysAdapter mSubkeysAdapter; private UserIdsAddedAdapter mUserIdsAddedAdapter; private ArrayList mUserIdsAddedData; @@ -104,7 +104,7 @@ public class EditKeyFragment extends LoaderFragment implements View view = inflater.inflate(R.layout.edit_key_fragment, getContainer()); mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids); - mKeysList = (ListView) view.findViewById(R.id.edit_key_keys); + mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys); mUserIdsAddedList = (ListView) view.findViewById(R.id.edit_key_user_ids_added); mKeysAddedList = (ListView) view.findViewById(R.id.edit_key_keys_added); mChangePassphrase = view.findViewById(R.id.edit_key_action_change_passphrase); @@ -191,13 +191,13 @@ public class EditKeyFragment extends LoaderFragment implements } }); - // TODO: from savedInstance?! + // TODO: mUserIdsAddedData and SaveParcel from savedInstance?! mUserIdsAddedData = new ArrayList(); mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mUserIdsAddedData); mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter); - mKeysAdapter = new SubkeysAdapter(getActivity(), null, 0); - mKeysList.setAdapter(mKeysAdapter); + mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0); + mSubkeysList.setAdapter(mSubkeysAdapter); // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. @@ -235,7 +235,7 @@ public class EditKeyFragment extends LoaderFragment implements break; case LOADER_ID_KEYS: - mKeysAdapter.swapCursor(data); + mSubkeysAdapter.swapCursor(data); break; } @@ -252,7 +252,7 @@ public class EditKeyFragment extends LoaderFragment implements mUserIdsAdapter.swapCursor(null); break; case LOADER_ID_KEYS: - mKeysAdapter.swapCursor(null); + mSubkeysAdapter.swapCursor(null); break; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index 6d8455589..f5f4b32e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -38,22 +38,11 @@ import java.util.Date; public class SubkeysAdapter extends CursorAdapter { private LayoutInflater mInflater; - private int mIndexKeyId; - private int mIndexAlgorithm; - private int mIndexKeySize; - private int mIndexRank; - private int mIndexCanCertify; - private int mIndexCanEncrypt; - private int mIndexCanSign; - private int mIndexHasSecret; - private int mIndexRevokedKey; - private int mIndexExpiry; - private boolean hasAnySecret; private ColorStateList mDefaultTextColor; - public static final String[] KEYS_PROJECTION = new String[] { + public static final String[] KEYS_PROJECTION = new String[]{ Keys._ID, Keys.KEY_ID, Keys.RANK, @@ -68,24 +57,33 @@ public class SubkeysAdapter extends CursorAdapter { Keys.EXPIRY, Keys.FINGERPRINT }; + private static final int INDEX_ID = 0; + private static final int INDEX_KEY_ID = 1; + private static final int INDEX_RANK = 2; + private static final int INDEX_ALGORITHM = 3; + private static final int INDEX_KEY_SIZE = 4; + private static final int INDEX_HAS_SECRET = 5; + private static final int INDEX_CAN_CERTIFY = 6; + private static final int INDEX_CAN_ENCRYPT = 7; + private static final int INDEX_CAN_SIGN = 8; + private static final int INDEX_IS_REVOKED = 9; + private static final int INDEX_CREATION = 10; + private static final int INDEX_EXPIRY = 11; + private static final int INDEX_FINGERPRINT = 12; public SubkeysAdapter(Context context, Cursor c, int flags) { super(context, c, flags); mInflater = LayoutInflater.from(context); - - initIndex(c); } @Override public Cursor swapCursor(Cursor newCursor) { - initIndex(newCursor); - hasAnySecret = false; if (newCursor != null) { newCursor.moveToFirst(); do { - if (newCursor.getInt(mIndexHasSecret) != 0) { + if (newCursor.getInt(INDEX_HAS_SECRET) != 0) { hasAnySecret = true; break; } @@ -95,27 +93,6 @@ public class SubkeysAdapter extends CursorAdapter { return super.swapCursor(newCursor); } - /** - * Get column indexes for performance reasons just once in constructor and swapCursor. For a - * performance comparison see http://stackoverflow.com/a/17999582 - * - * @param cursor - */ - private void initIndex(Cursor cursor) { - if (cursor != null) { - mIndexKeyId = cursor.getColumnIndexOrThrow(Keys.KEY_ID); - mIndexAlgorithm = cursor.getColumnIndexOrThrow(Keys.ALGORITHM); - mIndexKeySize = cursor.getColumnIndexOrThrow(Keys.KEY_SIZE); - mIndexRank = cursor.getColumnIndexOrThrow(Keys.RANK); - mIndexCanCertify = cursor.getColumnIndexOrThrow(Keys.CAN_CERTIFY); - mIndexCanEncrypt = cursor.getColumnIndexOrThrow(Keys.CAN_ENCRYPT); - mIndexCanSign = cursor.getColumnIndexOrThrow(Keys.CAN_SIGN); - mIndexHasSecret = cursor.getColumnIndexOrThrow(Keys.HAS_SECRET); - mIndexRevokedKey = cursor.getColumnIndexOrThrow(Keys.IS_REVOKED); - mIndexExpiry = cursor.getColumnIndexOrThrow(Keys.EXPIRY); - } - } - @Override public void bindView(View view, Context context, Cursor cursor) { TextView keyId = (TextView) view.findViewById(R.id.keyId); @@ -127,16 +104,16 @@ public class SubkeysAdapter extends CursorAdapter { ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey); ImageView revokedKeyIcon = (ImageView) view.findViewById(R.id.ic_revokedKey); - String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId)); + String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(INDEX_KEY_ID)); String algorithmStr = PgpKeyHelper.getAlgorithmInfo( context, - cursor.getInt(mIndexAlgorithm), - cursor.getInt(mIndexKeySize) + cursor.getInt(INDEX_ALGORITHM), + cursor.getInt(INDEX_KEY_SIZE) ); keyId.setText(keyIdStr); // may be set with additional "stripped" later on - if (hasAnySecret && cursor.getInt(mIndexHasSecret) == 0) { + if (hasAnySecret && cursor.getInt(INDEX_HAS_SECRET) == 0) { keyDetails.setText(algorithmStr + ", " + context.getString(R.string.key_stripped)); } else { @@ -144,13 +121,13 @@ public class SubkeysAdapter extends CursorAdapter { } // Set icons according to properties - masterKeyIcon.setVisibility(cursor.getInt(mIndexRank) == 0 ? View.VISIBLE : View.INVISIBLE); - certifyIcon.setVisibility(cursor.getInt(mIndexCanCertify) != 0 ? View.VISIBLE : View.GONE); - encryptIcon.setVisibility(cursor.getInt(mIndexCanEncrypt) != 0 ? View.VISIBLE : View.GONE); - signIcon.setVisibility(cursor.getInt(mIndexCanSign) != 0 ? View.VISIBLE : View.GONE); + masterKeyIcon.setVisibility(cursor.getInt(INDEX_RANK) == 0 ? View.VISIBLE : View.INVISIBLE); + certifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE); + encryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE); + signIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE); boolean valid = true; - if (cursor.getInt(mIndexRevokedKey) > 0) { + if (cursor.getInt(INDEX_IS_REVOKED) > 0) { revokedKeyIcon.setVisibility(View.VISIBLE); valid = false; @@ -162,17 +139,19 @@ public class SubkeysAdapter extends CursorAdapter { revokedKeyIcon.setVisibility(View.GONE); } - if (!cursor.isNull(mIndexExpiry)) { - Date expiryDate = new Date(cursor.getLong(mIndexExpiry) * 1000); + if (!cursor.isNull(INDEX_EXPIRY)) { + Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000); valid = valid && expiryDate.after(new Date()); keyExpiry.setText( context.getString(R.string.label_expiry) + ": " + - DateFormat.getDateFormat(context).format(expiryDate)); + DateFormat.getDateFormat(context).format(expiryDate) + ); } else { keyExpiry.setText( context.getString(R.string.label_expiry) + ": " + - context.getString(R.string.none)); + context.getString(R.string.none) + ); } // if key is expired or revoked, strike through text 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 7bf9334b8..47f17357a 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 @@ -41,9 +41,6 @@ import java.util.ArrayList; public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemClickListener { private LayoutInflater mInflater; - private int mIndexUserId, mIndexRank; - private int mVerifiedId, mIsRevoked, mIsPrimary; - private final ArrayList mCheckStates; private SaveKeyringParcel mSaveKeyringParcel; @@ -56,6 +53,13 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC UserIds.IS_PRIMARY, UserIds.IS_REVOKED }; + private static final int INDEX_ID = 0; + private static final int INDEX_USER_ID = 1; + private static final int INDEX_RANK = 2; + private static final int INDEX_VERIFIED = 3; + private static final int INDEX_IS_PRIMARY = 4; + private static final int INDEX_IS_REVOKED = 5; + public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes, SaveKeyringParcel saveKeyringParcel) { @@ -64,8 +68,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC mCheckStates = showCheckBoxes ? new ArrayList() : null; mSaveKeyringParcel = saveKeyringParcel; - - initIndex(c); } public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) { @@ -82,7 +84,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC @Override public Cursor swapCursor(Cursor newCursor) { - initIndex(newCursor); if (mCheckStates != null) { mCheckStates.clear(); if (newCursor != null) { @@ -91,7 +92,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC // initialize to true (use case knowledge: we usually want to sign all uids) for (int i = 0; i < count; i++) { newCursor.moveToPosition(i); - int verified = newCursor.getInt(mVerifiedId); + int verified = newCursor.getInt(INDEX_VERIFIED); mCheckStates.add(verified != Certs.VERIFIED_SECRET); } } @@ -100,22 +101,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC return super.swapCursor(newCursor); } - /** - * Get column indexes for performance reasons just once in constructor and swapCursor. For a - * performance comparison see http://stackoverflow.com/a/17999582 - * - * @param cursor - */ - private void initIndex(Cursor cursor) { - if (cursor != null) { - mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID); - mIndexRank = cursor.getColumnIndexOrThrow(UserIds.RANK); - mVerifiedId = cursor.getColumnIndexOrThrow(UserIds.VERIFIED); - mIsRevoked = cursor.getColumnIndexOrThrow(UserIds.IS_REVOKED); - mIsPrimary = cursor.getColumnIndexOrThrow(UserIds.IS_PRIMARY); - } - } - @Override public void bindView(View view, Context context, Cursor cursor) { TextView vName = (TextView) view.findViewById(R.id.userId); @@ -125,7 +110,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC ImageView vHasChanges = (ImageView) view.findViewById(R.id.has_changes); ImageView vEditImage = (ImageView) view.findViewById(R.id.edit_image); - String userId = cursor.getString(mIndexUserId); + String userId = cursor.getString(INDEX_USER_ID); String[] splitUserId = KeyRing.splitUserId(userId); if (splitUserId[0] != null) { vName.setText(splitUserId[0]); @@ -145,8 +130,8 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC vComment.setVisibility(View.GONE); } - boolean isPrimary = cursor.getInt(mIsPrimary) != 0; - boolean isRevoked = cursor.getInt(mIsRevoked) > 0; + boolean isPrimary = cursor.getInt(INDEX_IS_PRIMARY) != 0; + boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; // for edit key if (mSaveKeyringParcel != null) { @@ -189,7 +174,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC // verified: has been verified // isPrimary: show small star icon for primary user ids - int verified = cursor.getInt(mVerifiedId); + int verified = cursor.getInt(INDEX_VERIFIED); switch (verified) { case Certs.VERIFIED_SECRET: vVerified.setImageResource(isPrimary @@ -237,7 +222,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC for (int i = 0; i < mCheckStates.size(); i++) { if (mCheckStates.get(i)) { mCursor.moveToPosition(i); - result.add(mCursor.getString(mIndexUserId)); + result.add(mCursor.getString(INDEX_USER_ID)); } } return result; @@ -245,7 +230,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC public String getUserId(int position) { mCursor.moveToPosition(position); - return mCursor.getString(mIndexUserId); + return mCursor.getString(INDEX_USER_ID); } @Override -- cgit v1.2.3 From 13a13829a8b8ad49237fb9bc8bb5a03ff5a4cce4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 2 Jul 2014 16:47:12 +0200 Subject: fix nullpointer, cleanup --- .../org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 12 ++++++------ .../sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java | 2 +- .../keychain/ui/adapter/SubkeysAdapter.java | 5 ++--- 3 files changed, 9 insertions(+), 10 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 8c7606cf9..b00049ac7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -73,7 +73,7 @@ public class EditKeyFragment extends LoaderFragment implements private View mAddKey; private static final int LOADER_ID_USER_IDS = 0; - private static final int LOADER_ID_KEYS = 1; + private static final int LOADER_ID_SUBKEYS = 1; private UserIdsAdapter mUserIdsAdapter; private SubkeysAdapter mSubkeysAdapter; @@ -202,7 +202,7 @@ public class EditKeyFragment extends LoaderFragment implements // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); - getLoaderManager().initLoader(LOADER_ID_KEYS, null, this); + getLoaderManager().initLoader(LOADER_ID_SUBKEYS, null, this); } public Loader onCreateLoader(int id, Bundle args) { @@ -215,10 +215,10 @@ public class EditKeyFragment extends LoaderFragment implements UserIdsAdapter.USER_IDS_PROJECTION, null, null, null); } - case LOADER_ID_KEYS: { + case LOADER_ID_SUBKEYS: { Uri baseUri = KeychainContract.Keys.buildKeysUri(mDataUri); return new CursorLoader(getActivity(), baseUri, - SubkeysAdapter.KEYS_PROJECTION, null, null, null); + SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null); } default: @@ -234,7 +234,7 @@ public class EditKeyFragment extends LoaderFragment implements mUserIdsAdapter.swapCursor(data); break; - case LOADER_ID_KEYS: + case LOADER_ID_SUBKEYS: mSubkeysAdapter.swapCursor(data); break; @@ -251,7 +251,7 @@ public class EditKeyFragment extends LoaderFragment implements case LOADER_ID_USER_IDS: mUserIdsAdapter.swapCursor(null); break; - case LOADER_ID_KEYS: + case LOADER_ID_SUBKEYS: mSubkeysAdapter.swapCursor(null); break; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java index 4be572b4e..e46637871 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyKeysFragment.java @@ -87,7 +87,7 @@ public class ViewKeyKeysFragment extends LoaderFragment implements setContentShown(false); Uri baseUri = Keys.buildKeysUri(mDataUri); return new CursorLoader(getActivity(), baseUri, - SubkeysAdapter.KEYS_PROJECTION, null, null, null); + SubkeysAdapter.SUBKEYS_PROJECTION, null, null, null); } public void onLoadFinished(Loader loader, Cursor data) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java index f5f4b32e6..02b1f31e2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java @@ -42,7 +42,7 @@ public class SubkeysAdapter extends CursorAdapter { private ColorStateList mDefaultTextColor; - public static final String[] KEYS_PROJECTION = new String[]{ + public static final String[] SUBKEYS_PROJECTION = new String[]{ Keys._ID, Keys.KEY_ID, Keys.RANK, @@ -80,8 +80,7 @@ public class SubkeysAdapter extends CursorAdapter { @Override public Cursor swapCursor(Cursor newCursor) { hasAnySecret = false; - if (newCursor != null) { - newCursor.moveToFirst(); + if (newCursor != null && newCursor.moveToFirst()) { do { if (newCursor.getInt(INDEX_HAS_SECRET) != 0) { hasAnySecret = true; -- cgit v1.2.3 From 3512ac71994c4e2df039b342b982de91726344ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 2 Jul 2014 20:53:16 +0200 Subject: Remove unnecessary error logs --- .../main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java | 2 +- .../main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index 5b21be6e4..dba742268 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -170,7 +170,7 @@ public class DecryptActivity extends DrawerActivity { // end activity finish(); } - } else { + } else if (ACTION_DECRYPT.equals(action)) { Log.e(Constants.TAG, "Include the extra 'text' or an Uri with setData() in your Intent!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index 39d4a09bc..cc69148c1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -249,7 +249,7 @@ public class EncryptActivity extends DrawerActivity implements // end activity finish(); } - } else { + } else if (ACTION_ENCRYPT.equals(action)) { Log.e(Constants.TAG, "Include the extra 'text' or an Uri with setData() in your Intent!"); } -- cgit v1.2.3 From 8cbdf7b1c514f7b9148e1fef1a6776666d1e04aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 08:48:33 +0200 Subject: smaller dropdown items --- .../main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java | 4 ++-- .../sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java index 20b47ed01..601fc09f9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/WizardActivity.java @@ -142,7 +142,7 @@ public class WizardActivity extends ActionBarActivity { emailView.setThreshold(1); // Start working from first character emailView.setAdapter( new ArrayAdapter - (getActivity(), android.R.layout.simple_dropdown_item_1line, + (getActivity(), android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserEmails(getActivity()) ) ); @@ -177,7 +177,7 @@ public class WizardActivity extends ActionBarActivity { nameView.setThreshold(1); // Start working from first character nameView.setAdapter( new ArrayAdapter - (getActivity(), android.R.layout.simple_dropdown_item_1line, + (getActivity(), android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserNames(getActivity()) ) ); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java index 137217ff4..898e60e2d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java @@ -72,11 +72,11 @@ public class UserIdsAddedAdapter extends ArrayAdapter - (mActivity, android.R.layout.simple_dropdown_item_1line, + (mActivity, android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserNames(mActivity) ); mAutoCompleteEmailAdapter = new ArrayAdapter - (mActivity, android.R.layout.simple_dropdown_item_1line, + (mActivity, android.R.layout.simple_spinner_dropdown_item, ContactHelper.getPossibleUserEmails(mActivity) ); } -- cgit v1.2.3 From 55f067b0633a177c2d441a7c79115dd44d7c4a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 15:05:43 +0200 Subject: Work on edit --- .../keychain/service/SaveKeyringParcel.java | 14 ++++---- .../keychain/ui/EditKeyFragment.java | 30 +++++++++++++--- .../keychain/ui/adapter/UserIdsAdapter.java | 22 ++++++------ .../keychain/ui/adapter/UserIdsAddedAdapter.java | 40 +++++++++++----------- .../ui/dialog/CreateKeyDialogFragment.java | 8 ++--- 5 files changed, 66 insertions(+), 48 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index 1ad19cdd0..c48cf4b3b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -55,10 +55,10 @@ public class SaveKeyringParcel implements Parcelable { // performance gain for using Parcelable here would probably be negligible, // use Serializable instead. public static class SubkeyAdd implements Serializable { - public final int mAlgorithm; - public final int mKeysize; - public final int mFlags; - public final Long mExpiry; + public int mAlgorithm; + public int mKeysize; + public int mFlags; + public Long mExpiry; public SubkeyAdd(int algorithm, int keysize, int flags, Long expiry) { mAlgorithm = algorithm; mKeysize = keysize; @@ -68,9 +68,9 @@ public class SaveKeyringParcel implements Parcelable { } public static class SubkeyChange implements Serializable { - public final long mKeyId; - public final Integer mFlags; - public final Long mExpiry; + public long mKeyId; + public Integer mFlags; + public Long mExpiry; public SubkeyChange(long keyId, Integer flags, Long expiry) { mKeyId = keyId; mFlags = flags; 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 b00049ac7..97e4ffca9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -37,6 +37,7 @@ import android.widget.AdapterView; import android.widget.ListView; import android.widget.Toast; +import org.spongycastle.bcpg.sig.KeyFlags; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; @@ -50,6 +51,7 @@ import org.sufficientlysecure.keychain.service.OperationResults; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.service.SaveKeyringParcel; import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter; +import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter; import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment; @@ -67,17 +69,22 @@ public class EditKeyFragment extends LoaderFragment implements private ListView mUserIdsList; private ListView mSubkeysList; private ListView mUserIdsAddedList; - private ListView mKeysAddedList; + private ListView mSubkeysAddedList; private View mChangePassphrase; private View mAddUserId; - private View mAddKey; + private View mAddSubkey; private static final int LOADER_ID_USER_IDS = 0; private static final int LOADER_ID_SUBKEYS = 1; + // cursor adapter private UserIdsAdapter mUserIdsAdapter; private SubkeysAdapter mSubkeysAdapter; + + // array adapter private UserIdsAddedAdapter mUserIdsAddedAdapter; + private SubkeysAddedAdapter mSubkeysAddedAdapter; + private ArrayList mUserIdsAddedData; private Uri mDataUri; @@ -106,10 +113,10 @@ public class EditKeyFragment extends LoaderFragment implements mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids); mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys); mUserIdsAddedList = (ListView) view.findViewById(R.id.edit_key_user_ids_added); - mKeysAddedList = (ListView) view.findViewById(R.id.edit_key_keys_added); + mSubkeysAddedList = (ListView) view.findViewById(R.id.edit_key_keys_added); mChangePassphrase = view.findViewById(R.id.edit_key_action_change_passphrase); mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id); - mAddKey = view.findViewById(R.id.edit_key_action_add_key); + mAddSubkey = view.findViewById(R.id.edit_key_action_add_key); return root; } @@ -180,6 +187,13 @@ public class EditKeyFragment extends LoaderFragment implements } }); + mAddSubkey.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + addSubkey(); + } + }); + mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, mSaveKeyringParcel); mUserIdsList.setAdapter(mUserIdsAdapter); @@ -199,6 +213,9 @@ public class EditKeyFragment extends LoaderFragment implements mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0); mSubkeysList.setAdapter(mSubkeysAdapter); + mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.addSubKeys); + mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter); + // Prepare the loaders. Either re-connect with an existing ones, // or start new ones. getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); @@ -327,6 +344,11 @@ public class EditKeyFragment extends LoaderFragment implements mUserIdsAddedAdapter.add(new UserIdsAddedAdapter.UserIdModel()); } + private void addSubkey() { + // default values + mSubkeysAddedAdapter.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); + } + private void save() { String passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSaveKeyringParcel.mMasterKeyId); 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 47f17357a..d729648e5 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 @@ -107,7 +107,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC TextView vAddress = (TextView) view.findViewById(R.id.address); TextView vComment = (TextView) view.findViewById(R.id.comment); ImageView vVerified = (ImageView) view.findViewById(R.id.certified); - ImageView vHasChanges = (ImageView) view.findViewById(R.id.has_changes); ImageView vEditImage = (ImageView) view.findViewById(R.id.edit_image); String userId = cursor.getString(INDEX_USER_ID); @@ -135,27 +134,23 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC // for edit key if (mSaveKeyringParcel != null) { - boolean changeUserId = (mSaveKeyringParcel.changePrimaryUserId != null + boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.changePrimaryUserId != null); + boolean changeThisPrimaryUserId = (mSaveKeyringParcel.changePrimaryUserId != null && mSaveKeyringParcel.changePrimaryUserId.equals(userId)); - boolean revoke = (mSaveKeyringParcel.revokeUserIds.contains(userId)); + boolean revokeThisUserId = (mSaveKeyringParcel.revokeUserIds.contains(userId)); - if (changeUserId) { - isPrimary = !isPrimary; + if (changeAnyPrimaryUserId) { + // change all user ids, only this one should be primary + isPrimary = changeThisPrimaryUserId; } - if (revoke) { + if (revokeThisUserId) { if (!isRevoked) { isRevoked = true; } } - if (changeUserId || revoke) { - vHasChanges.setVisibility(View.VISIBLE); - } else { - vHasChanges.setVisibility(View.GONE); - } vEditImage.setVisibility(View.VISIBLE); } else { - vHasChanges.setVisibility(View.GONE); vEditImage.setVisibility(View.GONE); } @@ -166,11 +161,14 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC // disable and strike through text for revoked user ids vName.setEnabled(false); vAddress.setEnabled(false); + vComment.setEnabled(false); vName.setText(OtherHelper.strikeOutText(vName.getText())); vAddress.setText(OtherHelper.strikeOutText(vAddress.getText())); + vComment.setText(OtherHelper.strikeOutText(vComment.getText())); } else { vName.setEnabled(true); vAddress.setEnabled(true); + vComment.setEnabled(true); // verified: has been verified // isPrimary: show small star icon for primary user ids diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java index 898e60e2d..3fe5574ee 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAddedAdapter.java @@ -106,14 +106,14 @@ public class UserIdsAddedAdapter extends ArrayAdapter 0) { - Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(viewHolder.mModel.address); + if (holder.mModel.address.length() > 0) { + Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(holder.mModel.address); if (emailMatcher.matches()) { - viewHolder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, + holder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.uid_mail_ok, 0); } else { - viewHolder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, + holder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.uid_mail_bad, 0); } } else { // remove drawable if email is empty - viewHolder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + holder.vAddress.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); } } }); - viewHolder.vName.addTextChangedListener(new TextWatcher() { + holder.vName.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @@ -156,11 +156,11 @@ public class UserIdsAddedAdapter extends ArrayAdapter Date: Thu, 3 Jul 2014 15:14:06 +0200 Subject: edit key: subkey adapter --- .../keychain/ui/EditKeyFragment.java | 2 +- .../keychain/ui/adapter/SubkeysAddedAdapter.java | 360 +++++++++++++++++++++ 2 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java (limited to 'OpenKeychain/src/main/java') 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 97e4ffca9..e651ed269 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -113,7 +113,7 @@ public class EditKeyFragment extends LoaderFragment implements mUserIdsList = (ListView) view.findViewById(R.id.edit_key_user_ids); mSubkeysList = (ListView) view.findViewById(R.id.edit_key_keys); mUserIdsAddedList = (ListView) view.findViewById(R.id.edit_key_user_ids_added); - mSubkeysAddedList = (ListView) view.findViewById(R.id.edit_key_keys_added); + mSubkeysAddedList = (ListView) view.findViewById(R.id.edit_key_subkeys_added); mChangePassphrase = view.findViewById(R.id.edit_key_action_change_passphrase); mAddUserId = view.findViewById(R.id.edit_key_action_add_user_id); mAddSubkey = view.findViewById(R.id.edit_key_action_add_key); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java new file mode 100644 index 000000000..e42140ee6 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.adapter; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Build; +import android.text.Editable; +import android.text.TextUtils; +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.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Spinner; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.ContactHelper; +import org.sufficientlysecure.keychain.service.SaveKeyringParcel; +import org.sufficientlysecure.keychain.ui.dialog.CreateKeyDialogFragment; +import org.sufficientlysecure.keychain.util.Choice; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; + +public class SubkeysAddedAdapter extends ArrayAdapter { + private LayoutInflater mInflater; + private Activity mActivity; + + public interface OnAlgorithmSelectedListener { + public void onAlgorithmSelected(Choice algorithmChoice, int keySize); + } + + // hold a private reference to the underlying data List + private List mData; + + public SubkeysAddedAdapter(Activity activity, List data) { + super(activity, -1, data); + mActivity = activity; + mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mData = data; + } + + static class ViewHolder { + public OnAlgorithmSelectedListener mAlgorithmSelectedListener; + public Spinner mAlgorithmSpinner; + public Spinner mKeySizeSpinner; + public TextView mCustomKeyTextView; + public EditText mCustomKeyEditText; + public TextView mCustomKeyInfoTextView; + public ImageButton vDelete; + // also hold a reference to the model item + public SaveKeyringParcel.SubkeyAdd mModel; + } + + public View getView(final int position, View convertView, ViewGroup parent) { + if (convertView == null) { + // Not recycled, inflate a new view + convertView = mInflater.inflate(R.layout.edit_key_subkey_added_item, null); + final ViewHolder holder = new ViewHolder(); + holder.mAlgorithmSpinner = (Spinner) convertView.findViewById(R.id.create_key_algorithm); + holder.mKeySizeSpinner = (Spinner) convertView.findViewById(R.id.create_key_size); + holder.mCustomKeyTextView = (TextView) convertView.findViewById(R.id.custom_key_size_label); + holder.mCustomKeyEditText = (EditText) convertView.findViewById(R.id.custom_key_size_input); + holder.mCustomKeyInfoTextView = (TextView) convertView.findViewById(R.id.custom_key_size_info); + holder.vDelete = (ImageButton) convertView.findViewById(R.id.subkey_added_item_delete); + convertView.setTag(holder); + + holder.mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + Choice newKeyAlgorithmChoice = (Choice) holder.mAlgorithmSpinner.getSelectedItem(); + // update referenced model item + holder.mModel.mAlgorithm = newKeyAlgorithmChoice.getId(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + + holder.mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + Choice newKeyAlgorithmChoice = (Choice) holder.mAlgorithmSpinner.getSelectedItem(); + int newKeySize = getProperKeyLength(newKeyAlgorithmChoice.getId(), + getSelectedKeyLength(holder.mKeySizeSpinner, holder.mCustomKeyEditText)); + // update referenced model item + holder.mModel.mKeysize = newKeySize; + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + + holder.vDelete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + // remove reference model item from adapter (data and notify about change) + SubkeysAddedAdapter.this.remove(holder.mModel); + } + }); + + } + final ViewHolder holder = (ViewHolder) convertView.getTag(); + + // save reference to model item + holder.mModel = getItem(position); + + // TODO + boolean wouldBeMasterKey = false; +// boolean wouldBeMasterKey = (childCount == 0); + + ArrayList choices = new ArrayList(); + choices.add(new Choice(Constants.choice.algorithm.dsa, mActivity.getResources().getString( + R.string.dsa))); + if (!wouldBeMasterKey) { + choices.add(new Choice(Constants.choice.algorithm.elgamal, mActivity.getResources().getString( + R.string.elgamal))); + } + + choices.add(new Choice(Constants.choice.algorithm.rsa, mActivity.getResources().getString( + R.string.rsa))); + + ArrayAdapter adapter = new ArrayAdapter(mActivity, + android.R.layout.simple_spinner_item, choices); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + holder.mAlgorithmSpinner.setAdapter(adapter); + // make RSA the default + for (int i = 0; i < choices.size(); ++i) { + if (choices.get(i).getId() == Constants.choice.algorithm.rsa) { + holder.mAlgorithmSpinner.setSelection(i); + break; + } + } + + // dynamic ArrayAdapter must be created (instead of ArrayAdapter.getFromResource), because it's content may change + ArrayAdapter keySizeAdapter = new ArrayAdapter(mActivity, android.R.layout.simple_spinner_item, + new ArrayList(Arrays.asList(mActivity.getResources().getStringArray(R.array.rsa_key_size_spinner_values)))); + keySizeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + holder.mKeySizeSpinner.setAdapter(keySizeAdapter); + holder.mKeySizeSpinner.setSelection(1); // Default to 4096 for the key length + + holder.mCustomKeyEditText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { +// setOkButtonAvailability(alertDialog); + } + }); + + holder.mKeySizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setCustomKeyVisibility(holder.mKeySizeSpinner, holder.mCustomKeyEditText, + holder.mCustomKeyTextView, holder.mCustomKeyInfoTextView); +// setOkButtonAvailability(alertDialog); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); + + holder.mAlgorithmSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setKeyLengthSpinnerValuesForAlgorithm(((Choice) parent.getSelectedItem()).getId(), + holder.mKeySizeSpinner, holder.mCustomKeyInfoTextView); + + setCustomKeyVisibility(holder.mKeySizeSpinner, holder.mCustomKeyEditText, + holder.mCustomKeyTextView, holder.mCustomKeyInfoTextView); +// setOkButtonAvailability(alertDialog); + } + + @Override + public void onNothingSelected(AdapterView parent) { + } + }); +// +// holder.vAddress.setText(holder.mModel.address); +// holder.vAddress.setThreshold(1); // Start working from first character +// holder.vAddress.setAdapter(mAutoCompleteEmailAdapter); +// +// holder.vName.setText(holder.mModel.name); +// holder.vName.setThreshold(1); // Start working from first character +// holder.vName.setAdapter(mAutoCompleteNameAdapter); +// +// holder.vComment.setText(holder.mModel.comment); + + return convertView; + } + + + private int getSelectedKeyLength(Spinner keySizeSpinner, EditText customKeyEditText) { + final String selectedItemString = (String) keySizeSpinner.getSelectedItem(); + final String customLengthString = mActivity.getResources().getString(R.string.key_size_custom); + final boolean customSelected = customLengthString.equals(selectedItemString); + String keyLengthString = customSelected ? customKeyEditText.getText().toString() : selectedItemString; + int keySize; + try { + keySize = Integer.parseInt(keyLengthString); + } catch (NumberFormatException e) { + keySize = 0; + } + return keySize; + } + + /** + *

RSA

+ *

for RSA algorithm, key length must be greater than 1024 (according to + * #102). Possibility to generate keys bigger + * than 8192 bits is currently disabled, because it's almost impossible to generate them on a mobile device (check + * RSA key length plot and + * Cryptographic Key Length Recommendation). Also, key length must be a + * multiplicity of 8.

+ *

ElGamal

+ *

For ElGamal algorithm, supported key lengths are 1536, 2048, 3072, 4096 or 8192 bits.

+ *

DSA

+ *

For DSA algorithm key length must be between 512 and 1024. Also, it must me dividable by 64.

+ * + * @return correct key length, according to SpongyCastle specification. Returns -1, if key length is + * inappropriate. + */ + private int getProperKeyLength(int algorithmId, int currentKeyLength) { + final int[] elGamalSupportedLengths = {1536, 2048, 3072, 4096, 8192}; + int properKeyLength = -1; + switch (algorithmId) { + case Constants.choice.algorithm.rsa: + if (currentKeyLength > 1024 && currentKeyLength <= 8192) { + properKeyLength = currentKeyLength + ((8 - (currentKeyLength % 8)) % 8); + } + break; + case Constants.choice.algorithm.elgamal: + int[] elGammalKeyDiff = new int[elGamalSupportedLengths.length]; + for (int i = 0; i < elGamalSupportedLengths.length; i++) { + elGammalKeyDiff[i] = Math.abs(elGamalSupportedLengths[i] - currentKeyLength); + } + int minimalValue = Integer.MAX_VALUE; + int minimalIndex = -1; + for (int i = 0; i < elGammalKeyDiff.length; i++) { + if (elGammalKeyDiff[i] <= minimalValue) { + minimalValue = elGammalKeyDiff[i]; + minimalIndex = i; + } + } + properKeyLength = elGamalSupportedLengths[minimalIndex]; + break; + case Constants.choice.algorithm.dsa: + if (currentKeyLength >= 512 && currentKeyLength <= 1024) { + properKeyLength = currentKeyLength + ((64 - (currentKeyLength % 64)) % 64); + } + break; + } + return properKeyLength; + } + +// private boolean setOkButtonAvailability(AlertDialog alertDialog) { +// final Choice selectedAlgorithm = (Choice) mAlgorithmSpinner.getSelectedItem(); +// final int selectedKeySize = getSelectedKeyLength(); //Integer.parseInt((String) mKeySizeSpinner.getSelectedItem()); +// final int properKeyLength = getProperKeyLength(selectedAlgorithm.getId(), selectedKeySize); +// alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(properKeyLength > 0); +// } + + private void setCustomKeyVisibility(Spinner keySizeSpinner, EditText customkeyedittext, TextView customKeyTextView, TextView customKeyInfoTextView) { + final String selectedItemString = (String) keySizeSpinner.getSelectedItem(); + final String customLengthString = mActivity.getResources().getString(R.string.key_size_custom); + final boolean customSelected = customLengthString.equals(selectedItemString); + final int visibility = customSelected ? View.VISIBLE : View.GONE; + + customkeyedittext.setVisibility(visibility); + customKeyTextView.setVisibility(visibility); + customKeyInfoTextView.setVisibility(visibility); + + // hide keyboard after setting visibility to gone + if (visibility == View.GONE) { + InputMethodManager imm = (InputMethodManager) + mActivity.getSystemService(mActivity.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(customkeyedittext.getWindowToken(), 0); + } + } + + private void setKeyLengthSpinnerValuesForAlgorithm(int algorithmId, Spinner keySizeSpinner, TextView customKeyInfoTextView) { + final ArrayAdapter keySizeAdapter = (ArrayAdapter) keySizeSpinner.getAdapter(); + final Object selectedItem = keySizeSpinner.getSelectedItem(); + keySizeAdapter.clear(); + switch (algorithmId) { + case Constants.choice.algorithm.rsa: + replaceArrayAdapterContent(keySizeAdapter, R.array.rsa_key_size_spinner_values); + customKeyInfoTextView.setText(mActivity.getResources().getString(R.string.key_size_custom_info_rsa)); + break; + case Constants.choice.algorithm.elgamal: + replaceArrayAdapterContent(keySizeAdapter, R.array.elgamal_key_size_spinner_values); + customKeyInfoTextView.setText(""); // ElGamal does not support custom key length + break; + case Constants.choice.algorithm.dsa: + replaceArrayAdapterContent(keySizeAdapter, R.array.dsa_key_size_spinner_values); + customKeyInfoTextView.setText(mActivity.getResources().getString(R.string.key_size_custom_info_dsa)); + break; + } + keySizeAdapter.notifyDataSetChanged(); + + // when switching algorithm, try to select same key length as before + for (int i = 0; i < keySizeAdapter.getCount(); i++) { + if (selectedItem.equals(keySizeAdapter.getItem(i))) { + keySizeSpinner.setSelection(i); + break; + } + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private void replaceArrayAdapterContent(ArrayAdapter arrayAdapter, int stringArrayResourceId) { + final String[] spinnerValuesStringArray = mActivity.getResources().getStringArray(stringArrayResourceId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + arrayAdapter.addAll(spinnerValuesStringArray); + } else { + for (final String value : spinnerValuesStringArray) { + arrayAdapter.add(value); + } + } + } + +} -- cgit v1.2.3 From 9cbf78f7add8a0ea263c9485c58c848b10a0678c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 15:24:04 +0200 Subject: cleanup --- .../main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 4 ++++ .../sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java | 1 + 2 files changed, 5 insertions(+) (limited to 'OpenKeychain/src/main/java') 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 e651ed269..9d5a7e4ff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -287,6 +287,7 @@ public class EditKeyFragment extends LoaderFragment implements .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE); mSaveKeyringParcel.newPassphrase = newPassphrase; + Log.d(Constants.TAG, "newPassphrase set"); } } }; @@ -385,6 +386,9 @@ 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) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java index e42140ee6..25509fee5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAddedAdapter.java @@ -291,6 +291,7 @@ public class SubkeysAddedAdapter extends ArrayAdapter Date: Thu, 3 Jul 2014 15:28:45 +0200 Subject: parcel newPassphrase --- .../org/sufficientlysecure/keychain/service/SaveKeyringParcel.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java index c48cf4b3b..a56095767 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/SaveKeyringParcel.java @@ -82,6 +82,8 @@ public class SaveKeyringParcel implements Parcelable { mMasterKeyId = source.readInt() != 0 ? source.readLong() : null; mFingerprint = source.createByteArray(); + newPassphrase = source.readString(); + addUserIds = source.createStringArrayList(); addSubKeys = (ArrayList) source.readSerializable(); @@ -100,6 +102,8 @@ public class SaveKeyringParcel implements Parcelable { } destination.writeByteArray(mFingerprint); + destination.writeString(newPassphrase); + destination.writeStringList(addUserIds); destination.writeSerializable(addSubKeys); -- cgit v1.2.3 From 2988ac6e7b9fd997dad7ce9da66645a2d84e74a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 15:48:46 +0200 Subject: Cache passphrase for edit --- .../keychain/ui/EditKeyActivity.java | 2 +- .../keychain/ui/EditKeyFragment.java | 23 ++++---- .../ui/dialog/SetPassphraseDialogFragment.java | 65 +++++++++++++++------- 3 files changed, 60 insertions(+), 30 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 906ed347e..76ef9bf6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -357,7 +357,7 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener } SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance( - messenger, title); + messenger, null, title); setPassphraseDialog.show(getSupportFragmentManager(), "setPassphraseDialog"); } 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 9d5a7e4ff..46d3e9718 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -91,6 +91,8 @@ public class EditKeyFragment extends LoaderFragment implements private SaveKeyringParcel mSaveKeyringParcel; + private String mCurrentPassphrase; + /** * Creates new instance of this fragment */ @@ -125,6 +127,8 @@ public class EditKeyFragment extends LoaderFragment implements public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + cachePassphraseForEdit(); + // Inflate a "Done"/"Cancel" custom action bar view ActionBarHelper.setTwoButtonView(((ActionBarActivity) getActivity()).getSupportActionBar(), R.string.btn_save, R.drawable.ic_action_save, @@ -132,7 +136,7 @@ public class EditKeyFragment extends LoaderFragment implements @Override public void onClick(View v) { // Save - save(); + save(mCurrentPassphrase); } }, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel, new OnClickListener() { @@ -296,7 +300,7 @@ public class EditKeyFragment extends LoaderFragment implements Messenger messenger = new Messenger(returnHandler); SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance( - messenger, R.string.title_change_passphrase); + messenger, mCurrentPassphrase, R.string.title_change_passphrase); setPassphraseDialog.show(getActivity().getSupportFragmentManager(), "setPassphraseDialog"); } @@ -350,29 +354,28 @@ public class EditKeyFragment extends LoaderFragment implements mSubkeysAddedAdapter.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null)); } - private void save() { - String passphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), + private void cachePassphraseForEdit() { + mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(getActivity(), mSaveKeyringParcel.mMasterKeyId); - if (passphrase == null) { + if (mCurrentPassphrase == null) { PassphraseDialogFragment.show(getActivity(), mSaveKeyringParcel.mMasterKeyId, new Handler() { @Override public void handleMessage(Message message) { if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - String passphrase = + mCurrentPassphrase = message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); Log.d(Constants.TAG, "after caching passphrase"); - saveFinal(passphrase); + } else { + EditKeyFragment.this.getActivity().finish(); } } } ); - } else { - saveFinal(passphrase); } } - private void saveFinal(String passphrase) { + private void save(String passphrase) { Log.d(Constants.TAG, "add userids to parcel: " + mUserIdsAddedAdapter.getDataAsStringList()); mSaveKeyringParcel.addUserIds = mUserIdsAddedAdapter.getDataAsStringList(); 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 04bec3282..0fe5fdeda 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 @@ -26,12 +26,15 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; +import android.text.TextUtils; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager.LayoutParams; import android.view.inputmethod.EditorInfo; import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.EditText; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; @@ -44,6 +47,7 @@ import org.sufficientlysecure.keychain.util.Log; public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener { private static final String ARG_MESSENGER = "messenger"; private static final String ARG_TITLE = "title"; + private static final String ARG_OLD_PASSPHRASE = "title"; public static final int MESSAGE_OKAY = 1; @@ -52,6 +56,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi private Messenger mMessenger; private EditText mPassphraseEditText; private EditText mPassphraseAgainEditText; + private CheckBox mNoPassphraseCheckBox; /** * Creates new instance of this dialog fragment @@ -60,11 +65,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi * @param messenger to communicate back after setting the passphrase * @return */ - public static SetPassphraseDialogFragment newInstance(Messenger messenger, int title) { + public static SetPassphraseDialogFragment newInstance(Messenger messenger, String oldPassphrase, int title) { SetPassphraseDialogFragment frag = new SetPassphraseDialogFragment(); Bundle args = new Bundle(); args.putInt(ARG_TITLE, title); args.putParcelable(ARG_MESSENGER, messenger); + args.putString(ARG_OLD_PASSPHRASE, oldPassphrase); frag.setArguments(args); @@ -80,6 +86,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi int title = getArguments().getInt(ARG_TITLE); mMessenger = getArguments().getParcelable(ARG_MESSENGER); + String oldPassphrase = getArguments().getString(ARG_OLD_PASSPHRASE); CustomAlertDialogBuilder alert = new CustomAlertDialogBuilder(activity); @@ -92,6 +99,19 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase); mPassphraseAgainEditText = (EditText) view.findViewById(R.id.passphrase_passphrase_again); + mNoPassphraseCheckBox = (CheckBox) view.findViewById(R.id.passphrase_no_passphrase); + + if (TextUtils.isEmpty(oldPassphrase)) { + mNoPassphraseCheckBox.setChecked(true); + } + + mNoPassphraseCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mPassphraseEditText.setEnabled(!isChecked); + mPassphraseAgainEditText.setEnabled(!isChecked); + } + }); alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @@ -99,24 +119,31 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi public void onClick(DialogInterface dialog, int id) { dismiss(); - String passphrase1 = mPassphraseEditText.getText().toString(); - String passphrase2 = mPassphraseAgainEditText.getText().toString(); - if (!passphrase1.equals(passphrase2)) { - Toast.makeText( - activity, - getString(R.string.error_message, - getString(R.string.passphrases_do_not_match)), Toast.LENGTH_SHORT) - .show(); - return; - } - - if (passphrase1.equals("")) { - Toast.makeText( - activity, - getString(R.string.error_message, - getString(R.string.passphrase_must_not_be_empty)), - Toast.LENGTH_SHORT).show(); - return; + String passphrase1; + if (mNoPassphraseCheckBox.isChecked()) { + passphrase1 = ""; + } else { + passphrase1 = mPassphraseEditText.getText().toString(); + String passphrase2 = mPassphraseAgainEditText.getText().toString(); + if (!passphrase1.equals(passphrase2)) { + Toast.makeText( + activity, + getString(R.string.error_message, + getString(R.string.passphrases_do_not_match)), Toast.LENGTH_SHORT + ) + .show(); + return; + } + + if (passphrase1.equals("")) { + Toast.makeText( + activity, + getString(R.string.error_message, + getString(R.string.passphrase_must_not_be_empty)), + Toast.LENGTH_SHORT + ).show(); + return; + } } // return resulting data back to activity -- cgit v1.2.3 From b9d2ae938ab6f26afb8f5806cb34f363443250e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 15:49:46 +0200 Subject: Cache passphrase for edit --- .../main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 46d3e9718..42f007d49 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -127,8 +127,6 @@ public class EditKeyFragment extends LoaderFragment implements public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - cachePassphraseForEdit(); - // Inflate a "Done"/"Cancel" custom action bar view ActionBarHelper.setTwoButtonView(((ActionBarActivity) getActivity()).getSupportActionBar(), R.string.btn_save, R.drawable.ic_action_save, @@ -177,6 +175,8 @@ public class EditKeyFragment extends LoaderFragment implements getActivity().finish(); } + cachePassphraseForEdit(); + mChangePassphrase.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { -- cgit v1.2.3 From 6ca9d8a2689a24c2e57f95903e59d8db62bf4dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 15:54:07 +0200 Subject: fix no passphrase check --- .../keychain/ui/dialog/SetPassphraseDialogFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'OpenKeychain/src/main/java') 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 0fe5fdeda..93da48b75 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 @@ -47,7 +47,7 @@ import org.sufficientlysecure.keychain.util.Log; public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener { private static final String ARG_MESSENGER = "messenger"; private static final String ARG_TITLE = "title"; - private static final String ARG_OLD_PASSPHRASE = "title"; + private static final String ARG_OLD_PASSPHRASE = "old_passphrase"; public static final int MESSAGE_OKAY = 1; @@ -103,6 +103,8 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi if (TextUtils.isEmpty(oldPassphrase)) { mNoPassphraseCheckBox.setChecked(true); + mPassphraseEditText.setEnabled(false); + mPassphraseAgainEditText.setEnabled(false); } mNoPassphraseCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { -- cgit v1.2.3 From bd7b4ccf2b1a1f45fa47777194194c1fe238118c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 15:58:03 +0200 Subject: cleanup, debug for passphrase set --- .../java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'OpenKeychain/src/main/java') 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 42f007d49..c76dc0164 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -286,12 +286,9 @@ public class EditKeyFragment extends LoaderFragment implements if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) { Bundle data = message.getData(); - // set new returned passphrase! - String newPassphrase = data + // cache new returned passphrase! + mSaveKeyringParcel.newPassphrase = data .getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE); - - mSaveKeyringParcel.newPassphrase = newPassphrase; - Log.d(Constants.TAG, "newPassphrase set"); } } }; @@ -377,6 +374,8 @@ public class EditKeyFragment extends LoaderFragment implements private void save(String passphrase) { Log.d(Constants.TAG, "add userids to parcel: " + mUserIdsAddedAdapter.getDataAsStringList()); + Log.d(Constants.TAG, "mSaveKeyringParcel.newPassphrase: " + mSaveKeyringParcel.newPassphrase); + mSaveKeyringParcel.addUserIds = mUserIdsAddedAdapter.getDataAsStringList(); // Message is received after importing is done in KeychainIntentService -- cgit v1.2.3 From 1ba41e74824d73a2c3306a94f12a7d6c5225b174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 16:21:16 +0200 Subject: Remove old edit button, rename activities --- .../remote/ui/AccountSettingsFragment.java | 10 +- .../keychain/ui/EditKeyActivity.java | 729 +------------------- .../keychain/ui/EditKeyActivityNew.java | 68 -- .../keychain/ui/EditKeyActivityOld.java | 744 +++++++++++++++++++++ .../keychain/ui/KeyListFragment.java | 10 +- .../keychain/ui/ViewKeyMainFragment.java | 20 +- 6 files changed, 780 insertions(+), 801 deletions(-) delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java index e49c11e08..0b1d521ad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsFragment.java @@ -35,7 +35,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.remote.AccountSettings; -import org.sufficientlysecure.keychain.ui.EditKeyActivity; +import org.sufficientlysecure.keychain.ui.EditKeyActivityOld; import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment; import org.sufficientlysecure.keychain.ui.adapter.KeyValueSpinnerAdapter; import org.sufficientlysecure.keychain.util.AlgorithmNames; @@ -163,11 +163,11 @@ public class AccountSettingsFragment extends Fragment implements } private void createKey() { - Intent intent = new Intent(getActivity(), EditKeyActivity.class); - intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); - intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); + Intent intent = new Intent(getActivity(), EditKeyActivityOld.class); + intent.setAction(EditKeyActivityOld.ACTION_CREATE_KEY); + intent.putExtra(EditKeyActivityOld.EXTRA_GENERATE_DEFAULT_KEYS, true); // set default user id to account name - intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, mAccSettings.getAccountName()); + intent.putExtra(EditKeyActivityOld.EXTRA_USER_IDS, mAccSettings.getAccountName()); startActivityForResult(intent, REQUEST_CODE_CREATE_KEY); } 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 76ef9bf6a..d80425c3c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -1,6 +1,5 @@ /* - * Copyright (C) 2012-2014 Dominik Schürmann - * Copyright (C) 2010-2014 Thialfihar + * Copyright (C) 2014 Dominik Schürmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,732 +17,52 @@ package org.sufficientlysecure.keychain.ui; -import android.app.Activity; -import android.app.ProgressDialog; -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.PgpConversionHelper; -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.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -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 EditKeyActivity 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 mUserIds; - Vector mKeys; - Vector 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 class EditKeyActivity extends ActionBarActivity { - public void onEdited() { - somethingChanged(); - } + private EditKeyFragment mEditKeyFragment; @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(); - mKeys = new Vector(); - mKeysUsages = new Vector(); - - // 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 newKeys = - PgpConversionHelper.BytesToPGPSecretKeyList(data - .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); - - ArrayList 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.getSubKey().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.getSubKey().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(); - } - }); + setContentView(R.layout.edit_key_activity_new); - // 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( - EditKeyActivity.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 userIDs = getUserIds(mUserIdsView); - List newIDs = mUserIdsView.getNewIDFlags(); - ArrayList 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( - EditKeyActivity.this); - - alert.setIcon(R.drawable.ic_dialog_alert_holo_light); - alert.setTitle(R.string.warning); - alert.setMessage(EditKeyActivity.this.getString(R.string.ask_empty_id_ok)); - - alert.setPositiveButton(EditKeyActivity.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 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.newPassphrase = 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( - EditKeyActivity.this); - - alert.setIcon(R.drawable.ic_dialog_alert_holo_light); - alert.setTitle(R.string.warning); - alert.setMessage(EditKeyActivity.this.getString(R.string.ask_save_changed_key)); - - alert.setPositiveButton(EditKeyActivity.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); + Uri dataUri = getIntent().getData(); + if (dataUri == null) { + Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); finish(); - } - } - - /** - * Returns user ids from the SectionView - * - * @param userIdsView - * @return - */ - private ArrayList getUserIds(SectionView userIdsView) throws PgpGeneralException { - ArrayList userIds = new ArrayList(); - - 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; } - return userIds; + loadFragment(savedInstanceState, dataUri); } - /** - * Returns keys from the SectionView - * - * @param keysView - * @return - */ - private ArrayList getKeys(SectionView keysView) throws PgpGeneralException { - ArrayList keys = new ArrayList(); - - 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()); + private void loadFragment(Bundle savedInstanceState, Uri dataUri) { + // 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; } - return keys; - } - - /** - * Returns usage selections of keys from the SectionView - * - * @param keysView - * @return - */ - private ArrayList getKeysUsages(SectionView keysView) throws PgpGeneralException { - ArrayList keysUsages = new ArrayList(); - - 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 getKeysExpiryDates(SectionView keysView) throws PgpGeneralException { - ArrayList keysExpiryDates = new ArrayList(); - - 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; - } + // Create an instance of the fragment + mEditKeyFragment = EditKeyFragment.newInstance(dataUri); - private void updatePassphraseButtonText() { - mChangePassphrase.setText(isPassphraseSet() ? getString(R.string.btn_change_passphrase) - : getString(R.string.btn_set_passphrase)); + // Add the fragment to the 'fragment_container' FrameLayout + // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! + getSupportFragmentManager().beginTransaction() + .replace(R.id.edit_key_fragment_container, mEditKeyFragment) + .commitAllowingStateLoss(); + // do it immediately! + getSupportFragmentManager().executePendingTransactions(); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java deleted file mode 100644 index b45e8a6bb..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityNew.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui; - -import android.net.Uri; -import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; - -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.util.Log; - -public class EditKeyActivityNew extends ActionBarActivity { - - private EditKeyFragment mEditKeyFragment; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.edit_key_activity_new); - - Uri dataUri = getIntent().getData(); - if (dataUri == null) { - Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); - finish(); - return; - } - - loadFragment(savedInstanceState, dataUri); - } - - private void loadFragment(Bundle savedInstanceState, Uri dataUri) { - // 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; - } - - // Create an instance of the fragment - mEditKeyFragment = EditKeyFragment.newInstance(dataUri); - - // Add the fragment to the 'fragment_container' FrameLayout - // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! - getSupportFragmentManager().beginTransaction() - .replace(R.id.edit_key_fragment_container, mEditKeyFragment) - .commitAllowingStateLoss(); - // do it immediately! - getSupportFragmentManager().executePendingTransactions(); - } - -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java new file mode 100644 index 000000000..51457cd45 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java @@ -0,0 +1,744 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * Copyright (C) 2010-2014 Thialfihar + * + * 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 . + */ + +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 mUserIds; + Vector mKeys; + Vector 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(); + mKeys = new Vector(); + mKeysUsages = new Vector(); + + // 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 newKeys = + PgpConversionHelper.BytesToPGPSecretKeyList(data + .getByteArray(KeychainIntentService.RESULT_NEW_KEY)); + + ArrayList 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.getSubKey().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.getSubKey().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 userIDs = getUserIds(mUserIdsView); + List newIDs = mUserIdsView.getNewIDFlags(); + ArrayList 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 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.newPassphrase = 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 getUserIds(SectionView userIdsView) throws PgpGeneralException { + ArrayList userIds = new ArrayList(); + + 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 getKeys(SectionView keysView) throws PgpGeneralException { + ArrayList keys = new ArrayList(); + + 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 getKeysUsages(SectionView keysView) throws PgpGeneralException { + ArrayList keysUsages = new ArrayList(); + + 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 getKeysExpiryDates(SectionView keysView) throws PgpGeneralException { + ArrayList keysExpiryDates = new ArrayList(); + + 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/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index d6b0c7944..9d0a80406 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -47,7 +47,6 @@ import android.view.ViewGroup; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; import android.widget.FrameLayout; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; @@ -59,7 +58,6 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.helper.ExportHelper; import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment; import org.sufficientlysecure.keychain.util.Highlighter; @@ -106,10 +104,10 @@ public class KeyListFragment extends LoaderFragment @Override public void onClick(View v) { - Intent intent = new Intent(getActivity(), EditKeyActivity.class); - intent.setAction(EditKeyActivity.ACTION_CREATE_KEY); - intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true); - intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view + 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); } }); 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 dd48f193c..f0636cf2c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyMainFragment.java @@ -49,7 +49,6 @@ public class ViewKeyMainFragment extends LoaderFragment implements public static final String ARG_DATA_URI = "uri"; private View mActionEdit; - private View mActionEditNew; private View mActionEditDivider; private View mActionEncrypt; private View mActionCertify; @@ -74,7 +73,6 @@ public class ViewKeyMainFragment extends LoaderFragment implements mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); mActionEdit = view.findViewById(R.id.view_key_action_edit); - mActionEditNew = view.findViewById(R.id.view_key_action_edit_new); 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); @@ -118,11 +116,6 @@ public class ViewKeyMainFragment extends LoaderFragment implements editKey(mDataUri); } }); - mActionEditNew.setOnClickListener(new View.OnClickListener() { - public void onClick(View view) { - editKeyNew(mDataUri); - } - }); mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0); mUserIds.setAdapter(mUserIdsAdapter); @@ -259,16 +252,9 @@ public class ViewKeyMainFragment extends LoaderFragment implements 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); - } - - private void editKeyNew(Uri dataUri) { - Intent editIntent = new Intent(getActivity(), EditKeyActivityNew.class); -// editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri)); - editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri)); - editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); - startActivityForResult(editIntent, 0); +// editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY); +// startActivityForResult(editIntent, 0); + startActivity(editIntent); } } -- cgit v1.2.3 From 709196f774fc24dc0e7e6440391113f6be1e8e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 3 Jul 2014 16:49:25 +0200 Subject: Use strings in edit key --- .../keychain/ui/dialog/EditUserIdDialogFragment.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'OpenKeychain/src/main/java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java index f0ca73f0d..5eba3a463 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/EditUserIdDialogFragment.java @@ -26,6 +26,7 @@ import android.os.RemoteException; import android.support.v4.app.DialogFragment; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.util.Log; public class EditUserIdDialogFragment extends DialogFragment { @@ -57,9 +58,9 @@ public class EditUserIdDialogFragment extends DialogFragment { mMessenger = getArguments().getParcelable(ARG_MESSENGER); CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity()); - CharSequence[] array = {"change to primary user id", "revoke"}; + CharSequence[] array = getResources().getStringArray(R.array.edit_key_edit_user_id); - builder.setTitle("select action!"); + builder.setTitle(R.string.edit_key_edit_user_id_title); builder.setItems(array, new DialogInterface.OnClickListener() { @Override @@ -76,7 +77,7 @@ public class EditUserIdDialogFragment extends DialogFragment { } } }); - builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() { + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { dismiss(); -- cgit v1.2.3