From 2913a78b188e81fe6bd91d26fb0ae083cf504bde Mon Sep 17 00:00:00 2001 From: mar-v-in Date: Sun, 20 Jul 2014 17:09:34 +0200 Subject: Load of rework on EncryptActivity, still some TODOs --- .../keychain/helper/ContactHelper.java | 21 +- .../keychain/ui/EncryptActivity.java | 306 ++++++++++++++++++--- .../keychain/ui/EncryptActivityInterface.java | 34 ++- .../keychain/ui/EncryptAsymmetricFragment.java | 271 +++++++++--------- .../keychain/ui/EncryptFileFragment.java | 268 ++++-------------- .../keychain/ui/EncryptMessageFragment.java | 170 ++---------- .../keychain/ui/EncryptSymmetricFragment.java | 45 ++- .../ui/widget/EncryptKeyCompletionView.java | 4 +- .../res/layout/encrypt_asymmetric_fragment.xml | 29 +- .../main/res/layout/encrypt_asymmetric_signkey.xml | 19 ++ .../src/main/res/layout/encrypt_file_fragment.xml | 8 - 11 files changed, 597 insertions(+), 578 deletions(-) create mode 100644 OpenKeychain/src/main/res/layout/encrypt_asymmetric_signkey.xml (limited to 'OpenKeychain/src') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java index 1b9ef57b3..5d1bd1bb5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/ContactHelper.java @@ -236,14 +236,19 @@ public class ContactHelper { } public static Bitmap photoFromFingerprint(ContentResolver contentResolver, String fingerprint) { - int rawContactId = findRawContactId(contentResolver, fingerprint); - if (rawContactId == -1) return null; - Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); - Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri); - InputStream photoInputStream = - ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri); - if (photoInputStream == null) return null; - return BitmapFactory.decodeStream(photoInputStream); + if (fingerprint == null) return null; + try { + int rawContactId = findRawContactId(contentResolver, fingerprint); + if (rawContactId == -1) return null; + Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId); + Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri); + InputStream photoInputStream = + ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri); + if (photoInputStream == null) return null; + return BitmapFactory.decodeStream(photoInputStream); + } catch (Throwable ignored) { + return null; + } } /** 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 c98171230..ef999a449 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -18,28 +18,38 @@ package org.sufficientlysecure.keychain.ui; +import android.app.ProgressDialog; 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.Fragment; import android.support.v4.view.PagerTabStrip; import android.support.v4.view.ViewPager; import android.view.Menu; import android.view.MenuItem; -import android.view.ViewGroup; +import com.devspark.appmsg.AppMsg; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.helper.Preferences; +import org.sufficientlysecure.keychain.pgp.KeyRing; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.util.Choice; import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; -public class EncryptActivity extends DrawerActivity implements - EncryptSymmetricFragment.OnSymmetricKeySelection, - EncryptAsymmetricFragment.OnAsymmetricKeySelection, - EncryptActivityInterface { +public class EncryptActivity extends DrawerActivity implements EncryptActivityInterface { /* Intents */ public static final String ACTION_ENCRYPT = Constants.INTENT_PREFIX + "ENCRYPT"; @@ -79,75 +89,300 @@ public class EncryptActivity extends DrawerActivity implements private long mEncryptionKeyIds[] = null; private String mEncryptionUserIds[] = null; private long mSigningKeyId = Constants.key.none; - private String mPassphrase; - private String mPassphraseAgain; - private int mCurrentMode = PAGER_MODE_ASYMMETRIC; + private String mPassphrase = ""; private boolean mUseArmor; private boolean mDeleteAfterEncrypt = false; + private boolean mShareAfterEncrypt = false; + private ArrayList mInputUris; + private ArrayList mOutputUris; + private String mMessage; + + public boolean isModeSymmetric() { + return PAGER_MODE_SYMMETRIC == mViewPagerMode.getCurrentItem(); + } + + public boolean isContentMessage() { + return PAGER_CONTENT_MESSAGE == mViewPagerContent.getCurrentItem(); + } @Override - public void onSigningKeySelected(long signingKeyId) { - mSigningKeyId = signingKeyId; + public boolean isUseArmor() { + return mUseArmor; } @Override - public void onEncryptionKeysSelected(long[] encryptionKeyIds) { - mEncryptionKeyIds = encryptionKeyIds; + public long getSignatureKey() { + return mSigningKeyId; } @Override - public void onEncryptionUserSelected(String[] encryptionUserIds) { - mEncryptionUserIds = encryptionUserIds; + public long[] getEncryptionKeys() { + return mEncryptionKeyIds; } @Override - public void onPassphraseUpdate(String passphrase) { - mPassphrase = passphrase; + public String[] getEncryptionUsers() { + return mEncryptionUserIds; } @Override - public void onPassphraseAgainUpdate(String passphrase) { - mPassphraseAgain = passphrase; + public void setSignatureKey(long signatureKey) { + mSigningKeyId = signatureKey; + notifyUpdate(); } @Override - public boolean isModeSymmetric() { - return PAGER_MODE_SYMMETRIC == mCurrentMode; + public void setEncryptionKeys(long[] encryptionKeys) { + mEncryptionKeyIds = encryptionKeys; + notifyUpdate(); } @Override - public long getSignatureKey() { - return mSigningKeyId; + public void setEncryptionUsers(String[] encryptionUsers) { + mEncryptionUserIds = encryptionUsers; + notifyUpdate(); } @Override - public long[] getEncryptionKeys() { - return mEncryptionKeyIds; + public void setPassphrase(String passphrase) { + mPassphrase = passphrase; } @Override - public String[] getEncryptionUsers() { - return mEncryptionUserIds; + public ArrayList getInputUris() { + if (mInputUris == null) mInputUris = new ArrayList(); + return mInputUris; } @Override - public String getPassphrase() { - return mPassphrase; + public ArrayList getOutputUris() { + if (mOutputUris == null) mOutputUris = new ArrayList(); + return mOutputUris; } @Override - public String getPassphraseAgain() { - return mPassphraseAgain; + public void setInputUris(ArrayList uris) { + mInputUris = uris; + notifyUpdate(); } @Override - public boolean isUseArmor() { - return mUseArmor; + public void setOutputUris(ArrayList uris) { + mOutputUris = uris; + notifyUpdate(); + } + + @Override + public String getMessage() { + return mMessage; + } + + @Override + public void setMessage(String message) { + mMessage = message; + } + + @Override + public void notifyUpdate() { + for (Fragment fragment : getSupportFragmentManager().getFragments()) { + if (fragment instanceof EncryptActivityInterface.UpdateListener) { + ((UpdateListener) fragment).onNotifyUpdate(); + } + } } @Override - public boolean isDeleteAfterEncrypt() { - return mDeleteAfterEncrypt; + public void startEncrypt(boolean share) { + mShareAfterEncrypt = share; + startEncrypt(); + } + + public void startEncrypt() { + if (!inputIsValid()) { + // AppMsg was created by inputIsValid. + return; + } + + // Send all information needed to service to edit key in other thread + Intent intent = new Intent(this, KeychainIntentService.class); + intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); + intent.putExtra(KeychainIntentService.EXTRA_DATA, createEncryptBundle()); + + // Message is received after encrypting is done in KeychainIntentService + KeychainIntentServiceHandler serviceHandler = new KeychainIntentServiceHandler(this, + getString(R.string.progress_encrypting), ProgressDialog.STYLE_HORIZONTAL) { + public void handleMessage(Message message) { + // handle messages by standard KeychainIntentServiceHandler first + super.handleMessage(message); + + if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { + AppMsg.makeText(EncryptActivity.this, R.string.encrypt_sign_successful, AppMsg.STYLE_INFO).show(); + + if (!isContentMessage() && mDeleteAfterEncrypt) { + // TODO: Create and show dialog to delete original file + //DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); + //deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); + //setInputUri(null); + } + + if (mShareAfterEncrypt) { + // Share encrypted file + startActivity(Intent.createChooser(createSendIntent(message), getString(R.string.title_share_file))); + } else if (isContentMessage()) { + // Copy to clipboard + copyToClipboard(message); + AppMsg.makeText(EncryptActivity.this, + R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO).show(); + } + } + } + }; + // Create a new Messenger for the communication back + Messenger messenger = new Messenger(serviceHandler); + intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); + + // show progress dialog + serviceHandler.showProgressDialog(this); + + // start service with intent + startService(intent); + } + + private Bundle createEncryptBundle() { + // fill values for this action + Bundle data = new Bundle(); + + if (isContentMessage()) { + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES); + data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, mMessage.getBytes()); + } else { + data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUris); + + data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS); + data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUris); + } + + // Always use armor for messages + data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mUseArmor || isContentMessage()); + + // TODO: Only default compression right now... + int compressionId = Preferences.getPreferences(this).getDefaultMessageCompression(); + data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); + + if (isModeSymmetric()) { + Log.d(Constants.TAG, "Symmetric encryption enabled!"); + String passphrase = mPassphrase; + if (passphrase.length() == 0) { + passphrase = null; + } + data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase); + } else { + data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, mSigningKeyId); + data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, mEncryptionKeyIds); + } + return data; + } + + private void copyToClipboard(Message message) { + ClipboardReflection.copyToClipboard(this, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES))); + } + + private Intent createSendIntent(Message message) { + Intent sendIntent; + if (isContentMessage()) { + sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.setType("text/plain"); + sendIntent.putExtra(Intent.EXTRA_TEXT, new String(message.getData().getByteArray(KeychainIntentService.RESULT_BYTES))); + } else { + // file + if (mOutputUris.size() == 1) { + sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.setType("*/*"); + sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris.get(0)); + } else { + sendIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); + sendIntent.setType("*/*"); + sendIntent.putExtra(Intent.EXTRA_STREAM, mOutputUris); + } + } + if (!isModeSymmetric() && mEncryptionUserIds != null) { + Set users = new HashSet(); + for (String user : mEncryptionUserIds) { + String[] userId = KeyRing.splitUserId(user); + if (userId[1] != null) { + users.add(userId[1]); + } + } + sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); + } + return sendIntent; + } + + private boolean inputIsValid() { + if (!isContentMessage()) { + // file checks + + if (mInputUris.isEmpty()) { + AppMsg.makeText(this, R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); + return false; + } else if (mInputUris.size() > 1 && !mShareAfterEncrypt) { + AppMsg.makeText(this, "TODO", AppMsg.STYLE_ALERT).show(); // TODO + return false; + } + + if (mInputUris.size() != mOutputUris.size()) { + throw new IllegalStateException("Something went terribly wrong if this happens!"); + } + } + + if (isModeSymmetric()) { + // symmetric encryption checks + + + if (mPassphrase == null) { + AppMsg.makeText(this, R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); + return false; + } + if (mPassphrase.isEmpty()) { + AppMsg.makeText(this, R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT).show(); + return false; + } + + } else { + // asymmetric encryption checks + + boolean gotEncryptionKeys = (mEncryptionKeyIds != null + && mEncryptionKeyIds.length > 0); + + // Files must be encrypted, only text can be signed-only right now + if (!gotEncryptionKeys && !isContentMessage()) { + AppMsg.makeText(this, R.string.select_encryption_key, AppMsg.STYLE_ALERT).show(); + return false; + } + + if (!gotEncryptionKeys && mSigningKeyId == 0) { + AppMsg.makeText(this, R.string.select_encryption_or_signature_key, + AppMsg.STYLE_ALERT).show(); + return false; + } + + if (mSigningKeyId != 0 && PassphraseCacheService.getCachedPassphrase(this, mSigningKeyId) == null) { + PassphraseDialogFragment.show(this, mSigningKeyId, + new Handler() { + @Override + public void handleMessage(Message message) { + if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { + // restart + startEncrypt(); + } + } + }); + + return false; + } + } + return true; } private void initView() { @@ -211,12 +446,15 @@ public class EncryptActivity extends DrawerActivity implements case R.id.check_use_symmetric: mSwitchToMode = item.isChecked() ? PAGER_MODE_SYMMETRIC : PAGER_MODE_ASYMMETRIC; mViewPagerMode.setCurrentItem(mSwitchToMode); + notifyUpdate(); break; case R.id.check_use_armor: mUseArmor = item.isChecked(); + notifyUpdate(); break; case R.id.check_delete_after_encrypt: mDeleteAfterEncrypt = item.isChecked(); + notifyUpdate(); break; default: return super.onOptionsItemSelected(item); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java index 6d649c32e..54fe369a7 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivityInterface.java @@ -17,17 +17,41 @@ package org.sufficientlysecure.keychain.ui; +import android.net.Uri; + +import java.util.ArrayList; + public interface EncryptActivityInterface { - public boolean isModeSymmetric(); + public interface UpdateListener { + void onNotifyUpdate(); + } + + public boolean isUseArmor(); public long getSignatureKey(); public long[] getEncryptionKeys(); public String[] getEncryptionUsers(); + public void setSignatureKey(long signatureKey); + public void setEncryptionKeys(long[] encryptionKeys); + public void setEncryptionUsers(String[] encryptionUsers); + + public void setPassphrase(String passphrase); + + // ArrayList on purpose as only those are parcelable + public ArrayList getInputUris(); + public ArrayList getOutputUris(); + public void setInputUris(ArrayList uris); + public void setOutputUris(ArrayList uris); + + public String getMessage(); + public void setMessage(String message); - public String getPassphrase(); - public String getPassphraseAgain(); + /** + * Call this to notify the UI for changes done on the array lists or arrays, + * automatically called if setter is used + */ + public void notifyUpdate(); - boolean isUseArmor(); - boolean isDeleteAfterEncrypt(); + public void startEncrypt(boolean share); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index dc9cfe72e..9c7d7462f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -18,7 +18,7 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Intent; +import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; @@ -26,14 +26,15 @@ import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; +import android.support.v4.widget.CursorAdapter; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; - import com.tokenautocomplete.TokenCompleteTextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; import org.sufficientlysecure.keychain.provider.CachedPublicKeyRing; import org.sufficientlysecure.keychain.provider.KeychainContract; @@ -42,9 +43,13 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView; import org.sufficientlysecure.keychain.util.Log; -import java.util.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class EncryptAsymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener { + private static final String SIGN_KEY_SELECTION = KeyRings.CAN_SIGN + " = 1 AND " + KeyRings.IS_REVOKED + " = 0"; -public class EncryptAsymmetricFragment extends Fragment { public static final String ARG_SIGNATURE_KEY_ID = "signature_key_id"; public static final String ARG_ENCRYPTION_KEY_IDS = "encryption_key_ids"; @@ -53,55 +58,39 @@ public class EncryptAsymmetricFragment extends Fragment { ProviderHelper mProviderHelper; - OnAsymmetricKeySelection mKeySelectionListener; - // view - private CheckBox mSign; + private Spinner mSign; private EncryptKeyCompletionView mEncryptKeyView; + private SelectSignKeyCursorAdapter mSignAdapter = new SelectSignKeyCursorAdapter(); // model - private long mSecretKeyId = Constants.key.none; - private long mEncryptionKeyIds[] = null; - private String mEncryptionUserIds[] = null; - - // Container Activity must implement this interface - public interface OnAsymmetricKeySelection { - public void onSigningKeySelected(long signingKeyId); + private EncryptActivityInterface mEncryptInterface; - public void onEncryptionKeysSelected(long[] encryptionKeyIds); + @Override + public void onNotifyUpdate() { - public void onEncryptionUserSelected(String[] encryptionUserIds); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { - mKeySelectionListener = (OnAsymmetricKeySelection) activity; + mEncryptInterface = (EncryptActivityInterface) activity; } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement OnAsymmetricKeySelection"); + throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface"); } } private void setSignatureKeyId(long signatureKeyId) { - mSecretKeyId = signatureKeyId; - // update key selection in EncryptActivity - mKeySelectionListener.onSigningKeySelected(signatureKeyId); - updateView(); + mEncryptInterface.setSignatureKey(signatureKeyId); } private void setEncryptionKeyIds(long[] encryptionKeyIds) { - mEncryptionKeyIds = encryptionKeyIds; - // update key selection in EncryptActivity - mKeySelectionListener.onEncryptionKeysSelected(encryptionKeyIds); - updateView(); + mEncryptInterface.setEncryptionKeys(encryptionKeyIds); } private void setEncryptionUserIds(String[] encryptionUserIds) { - mEncryptionUserIds = encryptionUserIds; - // update key selection in EncryptActivity - mKeySelectionListener.onEncryptionUserSelected(encryptionUserIds); - updateView(); + mEncryptInterface.setEncryptionUsers(encryptionUserIds); } /** @@ -111,15 +100,17 @@ public class EncryptAsymmetricFragment extends Fragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.encrypt_asymmetric_fragment, container, false); - mSign = (CheckBox) view.findViewById(R.id.sign); - mSign.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - CheckBox checkBox = (CheckBox) v; - if (checkBox.isChecked()) { - selectSecretKey(); - } else { - setSignatureKeyId(Constants.key.none); - } + mSign = (Spinner) view.findViewById(R.id.sign); + mSign.setAdapter(mSignAdapter); + mSign.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + setSignatureKeyId(parent.getAdapter().getItemId(position)); + } + + @Override + public void onNothingSelected(AdapterView parent) { + setSignatureKeyId(Constants.key.none); } }); mEncryptKeyView = (EncryptKeyCompletionView) view.findViewById(R.id.recipient_list); @@ -136,6 +127,11 @@ public class EncryptAsymmetricFragment extends Fragment { mProviderHelper = new ProviderHelper(getActivity()); + // preselect keys given by arguments (given by Intent to EncryptActivity) + preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); + + // TODO: Move this into widget! + getLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks() { @Override public Loader onCreateLoader(int id, Bundle args) { @@ -146,12 +142,55 @@ public class EncryptAsymmetricFragment extends Fragment { @Override public void onLoadFinished(Loader loader, Cursor data) { - mEncryptKeyView.fromCursor(data); + mEncryptKeyView.swapCursor(data); } @Override public void onLoaderReset(Loader loader) { - mEncryptKeyView.fromCursor(null); + mEncryptKeyView.swapCursor(null); + } + }); + getLoaderManager().initLoader(1, null, new LoaderManager.LoaderCallbacks() { + @Override + public Loader onCreateLoader(int id, Bundle args) { + // This is called when a new Loader needs to be created. This + // sample only has one Loader, so we don't care about the ID. + Uri baseUri = KeyRings.buildUnifiedKeyRingsUri(); + + // These are the rows that we will retrieve. + String[] projection = new String[]{ + KeyRings._ID, + KeyRings.MASTER_KEY_ID, + KeyRings.KEY_ID, + KeyRings.USER_ID, + KeyRings.EXPIRY, + KeyRings.IS_REVOKED, + // can certify info only related to master key + KeyRings.CAN_CERTIFY, + // has sign may be any subkey + KeyRings.HAS_SIGN, + KeyRings.HAS_ANY_SECRET, + KeyRings.HAS_SECRET + }; + + String where = KeyRings.HAS_ANY_SECRET + " = 1"; + + // Now create and return a CursorLoader that will take care of + // creating a Cursor for the data being displayed. + return new CursorLoader(getActivity(), baseUri, projection, where, null, null); + /*return new CursorLoader(getActivity(), KeyRings.buildUnifiedKeyRingsUri(), + new String[]{KeyRings.USER_ID, KeyRings.KEY_ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET}, SIGN_KEY_SELECTION, + null, null);*/ + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + mSignAdapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + mSignAdapter.swapCursor(null); } }); mEncryptKeyView.setTokenListener(new TokenCompleteTextView.TokenListener() { @@ -169,9 +208,6 @@ public class EncryptAsymmetricFragment extends Fragment { } } }); - - // preselect keys given by arguments (given by Intent to EncryptActivity) - preselectKeys(signatureKeyId, encryptionKeyIds, mProviderHelper); } /** @@ -211,42 +247,6 @@ public class EncryptAsymmetricFragment extends Fragment { } } - private void updateView() { - /*if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) { - mSelectKeysButton.setText(getString(R.string.select_keys_button_default)); - } else { - mSelectKeysButton.setText(getResources().getQuantityString( - R.plurals.select_keys_button, mEncryptionKeyIds.length, - mEncryptionKeyIds.length)); - }*/ - - /* - if (mSecretKeyId == Constants.key.none) { - mSign.setChecked(false); - } else { - // See if we can get a user_id from a unified query - String[] userId; - try { - userId = mProviderHelper.getCachedPublicKeyRing( - KeyRings.buildUnifiedKeyRingUri(mSecretKeyId)).getSplitPrimaryUserId(); - } catch (PgpGeneralException e) { - userId = null; - } - if (userId != null && userId[0] != null) { - mMainUserId.setText(userId[0]); - } else { - mMainUserId.setText(getResources().getString(R.string.user_id_no_name)); - } - if (userId != null && userId[1] != null) { - mMainUserIdRest.setText(userId[1]); - } else { - mMainUserIdRest.setText(""); - } - mSign.setChecked(true); - } - */ - } - private void updateEncryptionKeys() { List objects = mEncryptKeyView.getObjects(); List keyIds = new ArrayList(); @@ -266,58 +266,81 @@ public class EncryptAsymmetricFragment extends Fragment { setEncryptionUserIds(userIds.toArray(new String[userIds.size()])); } - private void selectPublicKeys() { - Intent intent = new Intent(getActivity(), SelectPublicKeyActivity.class); - Vector keyIds = new Vector(); - if (mEncryptionKeyIds != null && mEncryptionKeyIds.length > 0) { - for (int i = 0; i < mEncryptionKeyIds.length; ++i) { - keyIds.add(mEncryptionKeyIds[i]); - } + private class SelectSignKeyCursorAdapter extends BaseAdapter implements SpinnerAdapter { + private CursorAdapter inner; + private int mIndexUserId; + private int mIndexKeyId; + private int mIndexMasterKeyId; + + public SelectSignKeyCursorAdapter() { + inner = new CursorAdapter(null, null, 0) { + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return getActivity().getLayoutInflater().inflate(R.layout.encrypt_asymmetric_signkey, null); + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ((TextView) view.findViewById(android.R.id.text1)).setText(cursor.getString(mIndexUserId)); + view.findViewById(android.R.id.text2).setVisibility(View.VISIBLE); + ((TextView) view.findViewById(android.R.id.text2)).setText(PgpKeyHelper.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); + } + + @Override + public long getItemId(int position) { + mCursor.moveToPosition(position); + return mCursor.getLong(mIndexMasterKeyId); + } + }; } - long[] initialKeyIds = null; - if (keyIds.size() > 0) { - initialKeyIds = new long[keyIds.size()]; - for (int i = 0; i < keyIds.size(); ++i) { - initialKeyIds[i] = keyIds.get(i); + + public Cursor swapCursor(Cursor newCursor) { + if (newCursor == null) return inner.swapCursor(null); + + mIndexKeyId = newCursor.getColumnIndex(KeyRings.KEY_ID); + mIndexUserId = newCursor.getColumnIndex(KeyRings.USER_ID); + mIndexMasterKeyId = newCursor.getColumnIndex(KeyRings.MASTER_KEY_ID); + if (newCursor.moveToFirst()) { + do { + if (newCursor.getLong(mIndexMasterKeyId) == mEncryptInterface.getSignatureKey()) { + mSign.setSelection(newCursor.getPosition() + 1); + } + } while (newCursor.moveToNext()); } + return inner.swapCursor(newCursor); } - intent.putExtra(SelectPublicKeyActivity.EXTRA_SELECTED_MASTER_KEY_IDS, initialKeyIds); - startActivityForResult(intent, REQUEST_CODE_PUBLIC_KEYS); - } - private void selectSecretKey() { - Intent intent = new Intent(getActivity(), SelectSecretKeyActivity.class); - intent.putExtra(SelectSecretKeyActivity.EXTRA_FILTER_SIGN, true); - startActivityForResult(intent, REQUEST_CODE_SECRET_KEYS); - } + @Override + public int getCount() { + return inner.getCount() + 1; + } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case REQUEST_CODE_PUBLIC_KEYS: { - if (resultCode == Activity.RESULT_OK) { - Bundle bundle = data.getExtras(); - setEncryptionKeyIds(bundle - .getLongArray(SelectPublicKeyActivity.RESULT_EXTRA_MASTER_KEY_IDS)); - setEncryptionUserIds(bundle.getStringArray(SelectPublicKeyActivity.RESULT_EXTRA_USER_IDS)); - } - break; - } + @Override + public Object getItem(int position) { + if (position == 0) return null; + return inner.getItem(position - 1); + } + + @Override + public long getItemId(int position) { + if (position == 0) return Constants.key.none; + return inner.getItemId(position - 1); + } - case REQUEST_CODE_SECRET_KEYS: { - if (resultCode == Activity.RESULT_OK) { - Uri uriMasterKey = data.getData(); - setSignatureKeyId(Long.valueOf(uriMasterKey.getLastPathSegment())); + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (position == 0) { + View v; + if (convertView == null) { + v = inner.newView(null, null, parent); } else { - setSignatureKeyId(Constants.key.none); + v = convertView; } - break; - } - - default: { - super.onActivityResult(requestCode, resultCode, data); - - break; + ((TextView) v.findViewById(android.R.id.text1)).setText("None"); + v.findViewById(android.R.id.text2).setVisibility(View.GONE); + return v; + } else { + return inner.getView(position - 1, convertView, parent); } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java index 350bc03aa..f782b7594 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFileFragment.java @@ -18,44 +18,28 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Point; 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.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; - -import com.devspark.appmsg.AppMsg; - import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.helper.OtherHelper; -import org.sufficientlysecure.keychain.pgp.KeyRing; -import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.helper.FileHelper; +import org.sufficientlysecure.keychain.helper.OtherHelper; import org.sufficientlysecure.keychain.helper.Preferences; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment; +import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.util.Choice; -import org.sufficientlysecure.keychain.util.Log; import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -public class EncryptFileFragment extends Fragment { +public class EncryptFileFragment extends Fragment implements EncryptActivityInterface.UpdateListener { public static final String ARG_URIS = "uris"; private static final int REQUEST_CODE_INPUT = 0x00007003; @@ -64,15 +48,11 @@ public class EncryptFileFragment extends Fragment { private EncryptActivityInterface mEncryptInterface; // view - private Spinner mFileCompression = null; + private View mAddView; private View mShareFile; private View mEncryptFile; private SelectedFilesAdapter mAdapter = new SelectedFilesAdapter(); - // model - private ArrayList mInputUri = new ArrayList(); - private ArrayList mOutputUri = new ArrayList(); - @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -105,34 +85,23 @@ public class EncryptFileFragment extends Fragment { } }); - //mFilename = (TextView) view.findViewById(R.id.filename); - //view.findViewById(R.id.btn_browse).setOnClickListener(new View.OnClickListener() { - // public void onClick(View v) { - // if (Constants.KITKAT) { - // FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); - // } else { - // FileHelper.openFile(EncryptFileFragment.this, - // mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); - // } - // } - //}); - - View addFile = inflater.inflate(R.layout.file_list_entry_add, null); - addFile.setOnClickListener(new View.OnClickListener() { + mAddView = inflater.inflate(R.layout.file_list_entry_add, null); + mAddView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (Constants.KITKAT) { FileHelper.openDocument(EncryptFileFragment.this, "*/*", REQUEST_CODE_INPUT); } else { FileHelper.openFile(EncryptFileFragment.this, - mInputUri.isEmpty() ? null : mInputUri.get(mInputUri.size() - 1), "*/*", REQUEST_CODE_INPUT); + mEncryptInterface.getInputUris().isEmpty() ? null : mEncryptInterface.getInputUris().get(mEncryptInterface.getInputUris().size() - 1), "*/*", REQUEST_CODE_INPUT); } } }); ListView listView = (ListView) view.findViewById(R.id.selected_files_list); - listView.addFooterView(addFile); + listView.addFooterView(mAddView); listView.setAdapter(mAdapter); + /* mFileCompression = (Spinner) view.findViewById(R.id.fileCompression); Choice[] choices = new Choice[]{ new Choice(Constants.choice.compression.none, getString(R.string.choice_none) + " (" @@ -149,6 +118,7 @@ public class EncryptFileFragment extends Fragment { adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mFileCompression.setAdapter(adapter); + int defaultFileCompression = Preferences.getPreferences(getActivity()).getDefaultFileCompression(); for (int i = 0; i < choices.length; ++i) { if (choices[i].getId() == defaultFileCompression) { @@ -156,6 +126,7 @@ public class EncryptFileFragment extends Fragment { break; } } + */ return view; } @@ -180,20 +151,39 @@ public class EncryptFileFragment extends Fragment { return; } - mInputUri.add(inputUri); - mAdapter.notifyDataSetChanged(); + mEncryptInterface.getInputUris().add(inputUri); + mEncryptInterface.notifyUpdate(); + + /** + * We hide the encrypt to file button if multiple files are selected. + * + * With Android L it will be possible to select a target directory for multiple files, so we might want to + * change this later + */ + + if (mEncryptInterface.getInputUris().size() > 1) { + mEncryptFile.setVisibility(View.GONE); + } else { + mEncryptFile.setVisibility(View.VISIBLE); + } } private void delInputUri(int position) { - mInputUri.remove(position); - mAdapter.notifyDataSetChanged(); + mEncryptInterface.getInputUris().remove(position); + mEncryptInterface.notifyUpdate(); + + if (mEncryptInterface.getInputUris().size() > 1) { + mEncryptFile.setVisibility(View.GONE); + } else { + mEncryptFile.setVisibility(View.VISIBLE); + } } private void showOutputFileDialog() { - if (mInputUri.size() > 1 || mInputUri.isEmpty()) { + if (mEncryptInterface.getInputUris().size() > 1 || mEncryptInterface.getInputUris().isEmpty()) { throw new IllegalStateException(); } - Uri inputUri = mInputUri.get(0); + Uri inputUri = mEncryptInterface.getInputUris().get(0); if (!Constants.KITKAT) { File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; @@ -209,176 +199,19 @@ public class EncryptFileFragment extends Fragment { } private void encryptClicked(boolean share) { - if (mInputUri.isEmpty()) { - AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); - return; - } else if (mInputUri.size() > 1 && !share) { - AppMsg.makeText(getActivity(), "TODO", AppMsg.STYLE_ALERT).show(); // TODO - return; - } - - if (mEncryptInterface.isModeSymmetric()) { - // symmetric encryption - - boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null - && mEncryptInterface.getPassphrase().length() != 0); - if (!gotPassphrase) { - AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT) - .show(); - return; - } - - if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) { - AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); - return; - } - } else { - // asymmetric encryption - - boolean gotEncryptionKeys = (mEncryptInterface.getEncryptionKeys() != null - && mEncryptInterface.getEncryptionKeys().length > 0); - - if (!gotEncryptionKeys) { - AppMsg.makeText(getActivity(), R.string.select_encryption_key, AppMsg.STYLE_ALERT).show(); - return; - } - - if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) { - AppMsg.makeText(getActivity(), R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); - return; - } - - if (mEncryptInterface.getSignatureKey() != 0 && - PassphraseCacheService.getCachedPassphrase(getActivity(), - mEncryptInterface.getSignatureKey()) == null) { - PassphraseDialogFragment.show(getActivity(), mEncryptInterface.getSignatureKey(), - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - showOutputFileDialog(); - } - } - }); - - return; - } - } - if (share) { - mOutputUri.clear(); - for (Uri uri : mInputUri) { + mEncryptInterface.getOutputUris().clear(); + for (Uri uri : mEncryptInterface.getInputUris()) { String targetName = FileHelper.getFilename(getActivity(), uri) + (mEncryptInterface.isUseArmor() ? ".asc" : ".gpg"); - mOutputUri.add(TemporaryStorageProvider.createFile(getActivity(), targetName)); + mEncryptInterface.getOutputUris().add(TemporaryStorageProvider.createFile(getActivity(), targetName)); } - encryptStart(true); - } else if (mInputUri.size() == 1) { + mEncryptInterface.startEncrypt(share); + } else if (mEncryptInterface.getInputUris().size() == 1) { showOutputFileDialog(); } } - private void encryptStart(final boolean share) { - if (mInputUri == null || mOutputUri == null || mInputUri.size() != mOutputUri.size()) { - throw new IllegalStateException("Something went terribly wrong if this happens!"); - } - - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(getActivity(), KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); - - // fill values for this action - Bundle data = new Bundle(); - - Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); - - data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URIS); - data.putParcelableArrayList(KeychainIntentService.ENCRYPT_INPUT_URIS, mInputUri); - - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URIS); - data.putParcelableArrayList(KeychainIntentService.ENCRYPT_OUTPUT_URIS, mOutputUri); - - if (mEncryptInterface.isModeSymmetric()) { - Log.d(Constants.TAG, "Symmetric encryption enabled!"); - String passphrase = mEncryptInterface.getPassphrase(); - if (passphrase.length() == 0) { - passphrase = null; - } - data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase); - } else { - data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, - mEncryptInterface.getSignatureKey()); - data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, - mEncryptInterface.getEncryptionKeys()); - } - - data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, mEncryptInterface.isUseArmor()); - - int compressionId = ((Choice) mFileCompression.getSelectedItem()).getId(); - data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after encrypting is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), - getString(R.string.progress_encrypting), ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - AppMsg.makeText(getActivity(), R.string.encrypt_sign_successful, - AppMsg.STYLE_INFO).show(); - - if (mEncryptInterface.isDeleteAfterEncrypt()) { - // Create and show dialog to delete original file - /*DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment.newInstance(mInputUri); - deleteFileDialog.show(getActivity().getSupportFragmentManager(), "deleteDialog"); - setInputUri(null);*/ - } - - if (share) { - // Share encrypted file - Intent sendFileIntent; - if (mOutputUri.size() == 1) { - sendFileIntent = new Intent(Intent.ACTION_SEND); - sendFileIntent.setType("*/*"); - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri.get(0)); - } else { - sendFileIntent = new Intent(Intent.ACTION_SEND_MULTIPLE); - sendFileIntent.setType("*/*"); - sendFileIntent.putExtra(Intent.EXTRA_STREAM, mOutputUri); - } - if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { - Set users = new HashSet(); - for (String user : mEncryptInterface.getEncryptionUsers()) { - String[] userId = KeyRing.splitUserId(user); - if (userId[1] != null) { - users.add(userId[1]); - } - } - sendFileIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); - } - startActivity(Intent.createChooser(sendFileIntent, - getString(R.string.title_share_file))); - } - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(getActivity()); - - // start service with intent - getActivity().startService(intent); - } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { @@ -391,8 +224,8 @@ public class EncryptFileFragment extends Fragment { case REQUEST_CODE_OUTPUT: { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { - mOutputUri.add(data.getData()); - encryptStart(false); + mEncryptInterface.getOutputUris().add(data.getData()); + mEncryptInterface.startEncrypt(false); } return; } @@ -405,15 +238,20 @@ public class EncryptFileFragment extends Fragment { } } + @Override + public void onNotifyUpdate() { + mAdapter.notifyDataSetChanged(); + } + private class SelectedFilesAdapter extends BaseAdapter { @Override public int getCount() { - return mInputUri.size(); + return mEncryptInterface.getInputUris().size(); } @Override public Object getItem(int position) { - return mInputUri.get(position); + return mEncryptInterface.getInputUris().get(position); } @Override @@ -429,8 +267,8 @@ public class EncryptFileFragment extends Fragment { } else { view = convertView; } - ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mInputUri.get(position))); - long size = FileHelper.getFileSize(getActivity(), mInputUri.get(position)); + ((TextView) view.findViewById(R.id.filename)).setText(FileHelper.getFilename(getActivity(), mEncryptInterface.getInputUris().get(position))); + long size = FileHelper.getFileSize(getActivity(), mEncryptInterface.getInputUris().get(position)); if (size == -1) { ((TextView) view.findViewById(R.id.filesize)).setText(""); } else { @@ -443,7 +281,7 @@ public class EncryptFileFragment extends Fragment { } }); int px = OtherHelper.dpToPx(getActivity(), 48); - Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mInputUri.get(position), new Point(px, px)); + Bitmap bitmap = FileHelper.getThumbnail(getActivity(), mEncryptInterface.getInputUris().get(position), new Point(px, px)); if (bitmap != null) { ((ImageView) view.findViewById(R.id.thumbnail)).setImageBitmap(bitmap); } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java index e4f63089f..6aae649bd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptMessageFragment.java @@ -25,6 +25,8 @@ import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.support.v4.app.Fragment; +import android.text.Editable; +import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -75,18 +77,34 @@ public class EncryptMessageFragment extends Fragment { View view = inflater.inflate(R.layout.encrypt_message_fragment, container, false); mMessage = (TextView) view.findViewById(R.id.message); + mMessage.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) { + mEncryptInterface.setMessage(s.toString()); + } + }); mEncryptClipboard = view.findViewById(R.id.action_encrypt_clipboard); mEncryptShare = view.findViewById(R.id.action_encrypt_share); mEncryptClipboard.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - encryptClicked(true); + mEncryptInterface.startEncrypt(false); } }); mEncryptShare.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - encryptClicked(false); + mEncryptInterface.startEncrypt(true); } }); @@ -98,7 +116,7 @@ public class EncryptMessageFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - String text = getArguments().getString(ARG_TEXT); + String text = mEncryptInterface.getMessage(); if (text != null) { mMessage.setText(text); } @@ -123,150 +141,4 @@ public class EncryptMessageFragment extends Fragment { return message; } - - private void encryptClicked(final boolean toClipboard) { - if (mEncryptInterface.isModeSymmetric()) { - // symmetric encryption - - boolean gotPassphrase = (mEncryptInterface.getPassphrase() != null - && mEncryptInterface.getPassphrase().length() != 0); - if (!gotPassphrase) { - AppMsg.makeText(getActivity(), R.string.passphrase_must_not_be_empty, AppMsg.STYLE_ALERT) - .show(); - return; - } - - if (!mEncryptInterface.getPassphrase().equals(mEncryptInterface.getPassphraseAgain())) { - AppMsg.makeText(getActivity(), R.string.passphrases_do_not_match, AppMsg.STYLE_ALERT).show(); - return; - } - - } else { - // asymmetric encryption - - boolean gotEncryptionKeys = (mEncryptInterface.getEncryptionKeys() != null - && mEncryptInterface.getEncryptionKeys().length > 0); - - if (!gotEncryptionKeys && mEncryptInterface.getSignatureKey() == 0) { - AppMsg.makeText(getActivity(), R.string.select_encryption_or_signature_key, - AppMsg.STYLE_ALERT).show(); - return; - } - - if (mEncryptInterface.getSignatureKey() != 0 && - PassphraseCacheService.getCachedPassphrase(getActivity(), - mEncryptInterface.getSignatureKey()) == null) { - PassphraseDialogFragment.show(getActivity(), mEncryptInterface.getSignatureKey(), - new Handler() { - @Override - public void handleMessage(Message message) { - if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { - encryptStart(toClipboard); - } - } - }); - - return; - } - } - - encryptStart(toClipboard); - } - - private void encryptStart(final boolean toClipboard) { - // Send all information needed to service to edit key in other thread - Intent intent = new Intent(getActivity(), KeychainIntentService.class); - - intent.setAction(KeychainIntentService.ACTION_ENCRYPT_SIGN); - - // fill values for this action - Bundle data = new Bundle(); - - data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES); - - String message = mMessage.getText().toString(); - - if (mEncryptInterface.isModeSymmetric()) { - Log.d(Constants.TAG, "Symmetric encryption enabled!"); - String passphrase = mEncryptInterface.getPassphrase(); - if (passphrase.length() == 0) { - passphrase = null; - } - data.putString(KeychainIntentService.ENCRYPT_SYMMETRIC_PASSPHRASE, passphrase); - } else { - data.putLong(KeychainIntentService.ENCRYPT_SIGNATURE_KEY_ID, - mEncryptInterface.getSignatureKey()); - data.putLongArray(KeychainIntentService.ENCRYPT_ENCRYPTION_KEYS_IDS, - mEncryptInterface.getEncryptionKeys()); - - boolean signOnly = (mEncryptInterface.getEncryptionKeys() == null - || mEncryptInterface.getEncryptionKeys().length == 0); - if (signOnly) { - message = fixBadCharactersForGmail(message); - } - } - - data.putByteArray(KeychainIntentService.ENCRYPT_MESSAGE_BYTES, message.getBytes()); - - data.putBoolean(KeychainIntentService.ENCRYPT_USE_ASCII_ARMOR, true); - - int compressionId = Preferences.getPreferences(getActivity()).getDefaultMessageCompression(); - data.putInt(KeychainIntentService.ENCRYPT_COMPRESSION_ID, compressionId); - - intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - - // Message is received after encrypting is done in KeychainIntentService - KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), - getString(R.string.progress_encrypting), ProgressDialog.STYLE_HORIZONTAL) { - public void handleMessage(Message message) { - // handle messages by standard KeychainIntentServiceHandler first - super.handleMessage(message); - - if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { - // get returned data bundle - Bundle data = message.getData(); - - String output = new String(data.getByteArray(KeychainIntentService.RESULT_BYTES)); - Log.d(Constants.TAG, "output: " + output); - - if (toClipboard) { - ClipboardReflection.copyToClipboard(getActivity(), output); - AppMsg.makeText(getActivity(), - R.string.encrypt_sign_clipboard_successful, AppMsg.STYLE_INFO) - .show(); - } else { - Intent sendIntent = new Intent(Intent.ACTION_SEND); - - // Type is set to text/plain so that encrypted messages can - // be sent with Whatsapp, Hangouts, SMS etc... - sendIntent.setType("text/plain"); - Log.d(Constants.TAG, "encrypt to:" + Arrays.toString(mEncryptInterface.getEncryptionUsers())); - if (!mEncryptInterface.isModeSymmetric() && mEncryptInterface.getEncryptionUsers() != null) { - Set users = new HashSet(); - for (String user : mEncryptInterface.getEncryptionUsers()) { - String[] userId = KeyRing.splitUserId(user); - if (userId[1] != null) { - users.add(userId[1]); - } - } - sendIntent.putExtra(Intent.EXTRA_EMAIL, users.toArray(new String[users.size()])); - } - sendIntent.putExtra(Intent.EXTRA_TEXT, output); - startActivity(Intent.createChooser(sendIntent, - getString(R.string.title_share_with))); - } - } - } - }; - - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(saveHandler); - intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - - // show progress dialog - saveHandler.showProgressDialog(getActivity()); - - // start service with intent - getActivity().startService(intent); - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java index 8efa07953..86731b162 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptSymmetricFragment.java @@ -29,27 +29,20 @@ import android.widget.EditText; import org.sufficientlysecure.keychain.R; -public class EncryptSymmetricFragment extends Fragment { +public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener { - OnSymmetricKeySelection mPassphraseUpdateListener; + EncryptActivityInterface mEncryptInterface; private EditText mPassphrase; private EditText mPassphraseAgain; - // Container Activity must implement this interface - public interface OnSymmetricKeySelection { - public void onPassphraseUpdate(String passphrase); - - public void onPassphraseAgainUpdate(String passphrase); - } - @Override public void onAttach(Activity activity) { super.onAttach(activity); try { - mPassphraseUpdateListener = (OnSymmetricKeySelection) activity; + mEncryptInterface = (EncryptActivityInterface) activity; } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() + " must implement OnSymmetricKeySelection"); + throw new ClassCastException(activity.toString() + " must implement EncryptActivityInterface"); } } @@ -62,7 +55,7 @@ public class EncryptSymmetricFragment extends Fragment { mPassphrase = (EditText) view.findViewById(R.id.passphrase); mPassphraseAgain = (EditText) view.findViewById(R.id.passphraseAgain); - mPassphrase.addTextChangedListener(new TextWatcher() { + TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @@ -74,25 +67,21 @@ public class EncryptSymmetricFragment extends Fragment { @Override public void afterTextChanged(Editable s) { // update passphrase in EncryptActivity - mPassphraseUpdateListener.onPassphraseUpdate(s.toString()); - } - }); - mPassphraseAgain.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (mPassphrase.getText().toString().equals(mPassphraseAgain.getText().toString())) { + mEncryptInterface.setPassphrase(s.toString()); + } else { + mEncryptInterface.setPassphrase(null); + } } + }; + mPassphrase.addTextChangedListener(textWatcher); + mPassphraseAgain.addTextChangedListener(textWatcher); - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } + return view; + } - @Override - public void afterTextChanged(Editable s) { - // update passphrase in EncryptActivity - mPassphraseUpdateListener.onPassphraseAgainUpdate(s.toString()); - } - }); + @Override + public void onNotifyUpdate() { - return view; } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index 4566e37fd..2ba2e6497 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -43,7 +43,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { } private void initView() { - fromCursor(null); + swapCursor(null); setPrefix(getContext().getString(R.string.label_to) + ": "); allowDuplicates(false); } @@ -81,7 +81,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView { return null; } - public void fromCursor(Cursor cursor) { + public void swapCursor(Cursor cursor) { if (cursor == null) { setAdapter(new EncryptKeyAdapter(Collections.emptyList())); return; diff --git a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml index 284fdd9ce..b5d7b98cd 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_asymmetric_fragment.xml @@ -9,12 +9,31 @@ android:paddingRight="16dp" android:paddingLeft="16dp"> - + android:padding="0dp" + android:layout_margin="0dp" + style="@android:style/Widget.EditText"> + + + + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml b/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml index d52097433..156fce8f0 100644 --- a/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml +++ b/OpenKeychain/src/main/res/layout/encrypt_file_fragment.xml @@ -25,14 +25,6 @@ android:layout_height="0dip" android:layout_weight="1"/> - - - -