aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java6
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java416
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java74
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_result_include.xml44
-rw-r--r--OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml49
-rw-r--r--OpenKeychain/src/main/res/menu/decrypt_menu.xml17
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml15
7 files changed, 391 insertions, 230 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
index 766e65e8b..6c1902af1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java
@@ -240,7 +240,7 @@ public class DecryptFilesFragment extends DecryptFragment {
}
case KeychainIntentService.ACTION_DECRYPT_VERIFY: {
// display signature result in activity
- onResult(pgpResult);
+ loadVerifyResult(pgpResult);
if (mDeleteAfter.isChecked()) {
// Create and show dialog to delete original file
@@ -308,4 +308,8 @@ public class DecryptFilesFragment extends DecryptFragment {
}
}
+ @Override
+ protected void onVerifyLoaded(boolean verified) {
+
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
index 33209be86..d641f02f9 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java
@@ -17,26 +17,49 @@
package org.sufficientlysecure.keychain.ui;
+import java.util.ArrayList;
+
import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.Message;
+import android.os.Messenger;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.openintents.openpgp.OpenPgpSignatureResult;
+import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
+import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
+import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.KeyRing;
+import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
+import org.sufficientlysecure.keychain.ui.util.Notify;
+import org.sufficientlysecure.keychain.ui.util.Notify.Style;
+import org.sufficientlysecure.keychain.util.Preferences;
+
-public abstract class DecryptFragment extends CryptoOperationFragment {
- private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
+public abstract class DecryptFragment extends CryptoOperationFragment implements
+ LoaderManager.LoaderCallbacks<Cursor> {
- protected long mSignatureKeyId = 0;
+ public static final int LOADER_ID_UNIFIED = 0;
protected LinearLayout mResultLayout;
@@ -46,155 +69,118 @@ public abstract class DecryptFragment extends CryptoOperationFragment {
protected TextView mSignatureText;
protected View mSignatureLayout;
- protected View mSignatureDivider1;
- protected View mSignatureDivider2;
protected TextView mSignatureName;
protected TextView mSignatureEmail;
protected TextView mSignatureAction;
+ private OpenPgpSignatureResult mSignatureResult;
+
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
- mResultLayout = (LinearLayout) getView().findViewById(R.id.result_main_layout);
+ mResultLayout = (LinearLayout) view.findViewById(R.id.result_main_layout);
mResultLayout.setVisibility(View.GONE);
- mEncryptionIcon = (ImageView) getView().findViewById(R.id.result_encryption_icon);
- mEncryptionText = (TextView) getView().findViewById(R.id.result_encryption_text);
- mSignatureIcon = (ImageView) getView().findViewById(R.id.result_signature_icon);
- mSignatureText = (TextView) getView().findViewById(R.id.result_signature_text);
- mSignatureLayout = getView().findViewById(R.id.result_signature_layout);
- mSignatureDivider1 = getView().findViewById(R.id.result_signature_divider1);
- mSignatureDivider2 = getView().findViewById(R.id.result_signature_divider2);
- mSignatureName = (TextView) getView().findViewById(R.id.result_signature_name);
- mSignatureEmail = (TextView) getView().findViewById(R.id.result_signature_email);
- mSignatureAction = (TextView) getView().findViewById(R.id.result_signature_action);
+ mEncryptionIcon = (ImageView) view.findViewById(R.id.result_encryption_icon);
+ mEncryptionText = (TextView) view.findViewById(R.id.result_encryption_text);
+ mSignatureIcon = (ImageView) view.findViewById(R.id.result_signature_icon);
+ mSignatureText = (TextView) view.findViewById(R.id.result_signature_text);
+ mSignatureLayout = view.findViewById(R.id.result_signature_layout);
+ mSignatureName = (TextView) view.findViewById(R.id.result_signature_name);
+ mSignatureEmail = (TextView) view.findViewById(R.id.result_signature_email);
+ mSignatureAction = (TextView) view.findViewById(R.id.result_signature_action);
}
private void lookupUnknownKey(long unknownKeyId) {
- Intent intent = new Intent(getActivity(), ImportKeysActivity.class);
- intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_KEYSERVER);
- intent.putExtra(ImportKeysActivity.EXTRA_KEY_ID, unknownKeyId);
- startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY);
- }
-
- private void showKey(long keyId) {
- Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class);
- viewKeyIntent.setData(KeychainContract.KeyRings
- .buildGenericKeyRingUri(keyId));
- startActivity(viewKeyIntent);
- }
- /**
- *
- * @return returns false if signature is invalid, key is revoked or expired.
- */
- protected boolean onResult(DecryptVerifyResult decryptVerifyResult) {
- final OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
+ // Message is received after importing is done in KeychainIntentService
+ ServiceProgressHandler serviceHandler = new ServiceProgressHandler(getActivity()) {
+ public void handleMessage(Message message) {
+ // handle messages by standard KeychainIntentServiceHandler first
+ super.handleMessage(message);
- boolean valid = false;
+ if (message.arg1 == MessageStatus.OKAY.ordinal()) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
- mSignatureKeyId = 0;
- mResultLayout.setVisibility(View.VISIBLE);
- if (signatureResult != null) {
- mSignatureKeyId = signatureResult.getKeyId();
-
- String userId = signatureResult.getPrimaryUserId();
- KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
- if (userIdSplit.name != null) {
- mSignatureName.setText(userIdSplit.name);
- } else {
- mSignatureName.setText(R.string.user_id_no_name);
- }
- if (userIdSplit.email != null) {
- mSignatureEmail.setText(userIdSplit.email);
- } else {
- mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(getActivity(), mSignatureKeyId));
- }
+ if (returnData == null) {
+ return;
+ }
- if (signatureResult.isSignatureOnly()) {
- mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
- KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED);
- } else {
- mEncryptionText.setText(R.string.decrypt_result_encrypted);
- KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
- }
+ final ImportKeyResult result =
+ returnData.getParcelable(OperationResult.EXTRA_RESULT);
- switch (signatureResult.getStatus()) {
- case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
- mSignatureText.setText(R.string.decrypt_result_signature_certified);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED);
+ // if (!result.success()) {
+ result.createNotify(getActivity()).show();
+ // }
- setSignatureLayoutVisibility(View.VISIBLE);
- setShowAction(mSignatureKeyId);
+ getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, DecryptFragment.this);
- valid = true;
- break;
}
+ }
+ };
- case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
- mSignatureText.setText(R.string.decrypt_result_signature_uncertified);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED);
+ // fill values for this action
+ Bundle data = new Bundle();
- setSignatureLayoutVisibility(View.VISIBLE);
- setShowAction(mSignatureKeyId);
+ // search config
+ {
+ Preferences prefs = Preferences.getPreferences(getActivity());
+ Preferences.CloudSearchPrefs cloudPrefs =
+ new Preferences.CloudSearchPrefs(true, true, prefs.getPreferredKeyserver());
+ data.putString(KeychainIntentService.IMPORT_KEY_SERVER, cloudPrefs.keyserver);
+ }
- valid = true;
- break;
- }
+ {
+ ParcelableKeyRing keyEntry = new ParcelableKeyRing(null,
+ KeyFormattingUtils.convertKeyIdToHex(unknownKeyId), null);
+ ArrayList<ParcelableKeyRing> selectedEntries = new ArrayList<>();
+ selectedEntries.add(keyEntry);
- case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: {
- mSignatureText.setText(R.string.decrypt_result_signature_missing_key);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY);
-
- setSignatureLayoutVisibility(View.VISIBLE);
- mSignatureAction.setText(R.string.decrypt_result_action_Lookup);
- mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_file_download_grey_24dp, 0);
- mSignatureLayout.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- lookupUnknownKey(mSignatureKeyId);
- }
- });
-
- valid = true;
- break;
- }
+ data.putParcelableArrayList(KeychainIntentService.IMPORT_KEY_LIST, selectedEntries);
+ }
- case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: {
- mSignatureText.setText(R.string.decrypt_result_signature_expired_key);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED);
+ // Send all information needed to service to query keys in other thread
+ Intent intent = new Intent(getActivity(), KeychainIntentService.class);
+ intent.setAction(KeychainIntentService.ACTION_IMPORT_KEYRING);
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
- setSignatureLayoutVisibility(View.VISIBLE);
- setShowAction(mSignatureKeyId);
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(serviceHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
- valid = false;
- break;
- }
+ getActivity().startService(intent);
- case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: {
- mSignatureText.setText(R.string.decrypt_result_signature_revoked_key);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.REVOKED);
+ }
- setSignatureLayoutVisibility(View.VISIBLE);
- setShowAction(mSignatureKeyId);
+ private void showKey(long keyId) {
+ try {
- valid = false;
- break;
- }
+ Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class);
+ long masterKeyId = new ProviderHelper(getActivity()).getCachedPublicKeyRing(
+ KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(keyId)
+ ).getMasterKeyId();
+ viewKeyIntent.setData(KeyRings.buildGenericKeyRingUri(masterKeyId));
+ startActivity(viewKeyIntent);
+
+ } catch (PgpKeyNotFoundException e) {
+ Notify.create(getActivity(), R.string.error_key_not_found, Style.ERROR);
+ }
+ }
+
+ /**
+ * @return returns false if signature is invalid, key is revoked or expired.
+ */
+ protected void loadVerifyResult(DecryptVerifyResult decryptVerifyResult) {
- case OpenPgpSignatureResult.SIGNATURE_ERROR: {
- mSignatureText.setText(R.string.decrypt_result_invalid_signature);
- KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID);
+ mSignatureResult = decryptVerifyResult.getSignatureResult();
+ mResultLayout.setVisibility(View.VISIBLE);
- setSignatureLayoutVisibility(View.GONE);
+ // unsigned data
+ if (mSignatureResult == null) {
- valid = false;
- break;
- }
- }
- } else {
setSignatureLayoutVisibility(View.GONE);
mSignatureText.setText(R.string.decrypt_result_no_signature);
@@ -202,16 +188,27 @@ public abstract class DecryptFragment extends CryptoOperationFragment {
mEncryptionText.setText(R.string.decrypt_result_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
- valid = true;
+ getLoaderManager().destroyLoader(LOADER_ID_UNIFIED);
+
+ onVerifyLoaded(true);
+
+ return;
+ }
+
+ if (mSignatureResult.isSignatureOnly()) {
+ mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
+ KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.NOT_ENCRYPTED);
+ } else {
+ mEncryptionText.setText(R.string.decrypt_result_encrypted);
+ KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, State.ENCRYPTED);
}
- return valid;
+ getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this);
+
}
private void setSignatureLayoutVisibility(int visibility) {
mSignatureLayout.setVisibility(visibility);
- mSignatureDivider1.setVisibility(visibility);
- mSignatureDivider2.setVisibility(visibility);
}
private void setShowAction(final long signatureKeyId) {
@@ -225,4 +222,177 @@ public abstract class DecryptFragment extends CryptoOperationFragment {
});
}
+ // These are the rows that we will retrieve.
+ static final String[] UNIFIED_PROJECTION = new String[]{
+ KeychainContract.KeyRings._ID,
+ KeychainContract.KeyRings.MASTER_KEY_ID,
+ KeychainContract.KeyRings.USER_ID,
+ KeychainContract.KeyRings.IS_REVOKED,
+ KeychainContract.KeyRings.IS_EXPIRED,
+ KeychainContract.KeyRings.VERIFIED,
+ };
+
+ @SuppressWarnings("unused")
+ static final int INDEX_MASTER_KEY_ID = 1;
+ static final int INDEX_USER_ID = 2;
+ static final int INDEX_IS_REVOKED = 3;
+ static final int INDEX_IS_EXPIRED = 4;
+ static final int INDEX_VERIFIED = 5;
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ if (id != LOADER_ID_UNIFIED) {
+ return null;
+ }
+
+ Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
+ mSignatureResult.getKeyId());
+ return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+
+ if (loader.getId() != LOADER_ID_UNIFIED) {
+ return;
+ }
+
+ // If the key is unknown, show it as such
+ if (data.getCount() == 0 || !data.moveToFirst()) {
+ showUnknownKeyStatus();
+ return;
+ }
+
+ long signatureKeyId = mSignatureResult.getKeyId();
+
+ String userId = data.getString(INDEX_USER_ID);
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
+ if (userIdSplit.name != null) {
+ mSignatureName.setText(userIdSplit.name);
+ } else {
+ mSignatureName.setText(R.string.user_id_no_name);
+ }
+ if (userIdSplit.email != null) {
+ mSignatureEmail.setText(userIdSplit.email);
+ } else {
+ mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(
+ getActivity(), mSignatureResult.getKeyId()));
+ }
+
+ boolean isRevoked = data.getInt(INDEX_IS_REVOKED) != 0;
+ boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
+ boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
+
+ if (isRevoked) {
+ mSignatureText.setText(R.string.decrypt_result_signature_revoked_key);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.REVOKED);
+
+ setSignatureLayoutVisibility(View.VISIBLE);
+ setShowAction(signatureKeyId);
+
+ onVerifyLoaded(false);
+
+ } else if (isExpired) {
+ mSignatureText.setText(R.string.decrypt_result_signature_expired_key);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.EXPIRED);
+
+ setSignatureLayoutVisibility(View.VISIBLE);
+ setShowAction(signatureKeyId);
+
+ onVerifyLoaded(true);
+
+ } else if (isVerified) {
+ mSignatureText.setText(R.string.decrypt_result_signature_certified);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED);
+
+ setSignatureLayoutVisibility(View.VISIBLE);
+ setShowAction(signatureKeyId);
+
+ onVerifyLoaded(true);
+
+ } else {
+ mSignatureText.setText(R.string.decrypt_result_signature_uncertified);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNVERIFIED);
+
+ setSignatureLayoutVisibility(View.VISIBLE);
+ setShowAction(signatureKeyId);
+
+ onVerifyLoaded(true);
+ }
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+
+ if (loader.getId() != LOADER_ID_UNIFIED) {
+ return;
+ }
+
+ setSignatureLayoutVisibility(View.GONE);
+
+ }
+
+ private void showUnknownKeyStatus() {
+
+ final long signatureKeyId = mSignatureResult.getKeyId();
+
+ int result = mSignatureResult.getStatus();
+ if (result != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING
+ && result != OpenPgpSignatureResult.SIGNATURE_ERROR) {
+ Log.e(Constants.TAG, "got missing status for non-missing key, shouldn't happen!");
+ }
+
+ String userId = mSignatureResult.getPrimaryUserId();
+ KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
+ if (userIdSplit.name != null) {
+ mSignatureName.setText(userIdSplit.name);
+ } else {
+ mSignatureName.setText(R.string.user_id_no_name);
+ }
+ if (userIdSplit.email != null) {
+ mSignatureEmail.setText(userIdSplit.email);
+ } else {
+ mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(
+ getActivity(), mSignatureResult.getKeyId()));
+ }
+
+ switch (mSignatureResult.getStatus()) {
+
+ case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: {
+ mSignatureText.setText(R.string.decrypt_result_signature_missing_key);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.UNKNOWN_KEY);
+
+ setSignatureLayoutVisibility(View.VISIBLE);
+ mSignatureAction.setText(R.string.decrypt_result_action_Lookup);
+ mSignatureAction
+ .setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_file_download_grey_24dp, 0);
+ mSignatureLayout.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ lookupUnknownKey(signatureKeyId);
+ }
+ });
+
+ onVerifyLoaded(true);
+
+ break;
+ }
+
+ case OpenPgpSignatureResult.SIGNATURE_ERROR: {
+ mSignatureText.setText(R.string.decrypt_result_invalid_signature);
+ KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.INVALID);
+
+ setSignatureLayoutVisibility(View.GONE);
+
+ onVerifyLoaded(false);
+ break;
+ }
+
+ }
+
+ }
+
+ protected abstract void onVerifyLoaded(boolean verified);
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
index 9c6c89c43..1b9ae917f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java
@@ -23,6 +23,9 @@ import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -39,7 +42,6 @@ import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
-import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ShareHelper;
import java.io.UnsupportedEncodingException;
@@ -54,6 +56,7 @@ public class DecryptTextFragment extends DecryptFragment {
// model
private String mCiphertext;
+ private boolean mShowMenuOptions = false;
/**
* Creates new instance of this fragment
@@ -79,22 +82,6 @@ public class DecryptTextFragment extends DecryptFragment {
mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid);
mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext);
- View vShareButton = view.findViewById(R.id.action_decrypt_share_plaintext);
- vShareButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString()));
- }
- });
-
- View vCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext);
- vCopyButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- copyToClipboard(mText.getText().toString());
- }
- });
-
Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button);
vInvalidButton.setOnClickListener(new View.OnClickListener() {
@Override
@@ -139,6 +126,8 @@ public class DecryptTextFragment extends DecryptFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+
String ciphertext = getArguments().getString(ARG_CIPHERTEXT);
if (ciphertext != null) {
mCiphertext = ciphertext;
@@ -147,6 +136,33 @@ public class DecryptTextFragment extends DecryptFragment {
}
@Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ if (mShowMenuOptions) {
+ inflater.inflate(R.menu.decrypt_menu, menu);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.decrypt_share: {
+ startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString()));
+ break;
+ }
+ case R.id.decrypt_copy: {
+ copyToClipboard(mText.getText().toString());
+ break;
+ }
+ default: {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ return true;
+ }
+
+ @Override
protected void cryptoOperation(CryptoInputParcel cryptoInput) {
// Send all information needed to service to decrypt in other thread
Intent intent = new Intent(getActivity(), KeychainIntentService.class);
@@ -206,15 +222,8 @@ public class DecryptTextFragment extends DecryptFragment {
pgpResult.createNotify(getActivity()).show();
// display signature result in activity
- boolean valid = onResult(pgpResult);
+ loadVerifyResult(pgpResult);
- if (valid) {
- mInvalidLayout.setVisibility(View.GONE);
- mValidLayout.setVisibility(View.VISIBLE);
- } else {
- mInvalidLayout.setVisibility(View.VISIBLE);
- mValidLayout.setVisibility(View.GONE);
- }
} else {
pgpResult.createNotify(getActivity()).show();
// TODO: show also invalid layout with different text?
@@ -234,4 +243,19 @@ public class DecryptTextFragment extends DecryptFragment {
getActivity().startService(intent);
}
+ @Override
+ protected void onVerifyLoaded(boolean verified) {
+
+ mShowMenuOptions = verified;
+ getActivity().supportInvalidateOptionsMenu();
+
+ if (verified) {
+ mInvalidLayout.setVisibility(View.GONE);
+ mValidLayout.setVisibility(View.VISIBLE);
+ } else {
+ mInvalidLayout.setVisibility(View.VISIBLE);
+ mValidLayout.setVisibility(View.GONE);
+ }
+
+ }
}
diff --git a/OpenKeychain/src/main/res/layout/decrypt_result_include.xml b/OpenKeychain/src/main/res/layout/decrypt_result_include.xml
index debc1106f..f64d72987 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_result_include.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_result_include.xml
@@ -1,10 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/result_main_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/holo_gray_bright">
+ android:background="@color/holo_gray_bright"
+ tools:showIn="@layout/decrypt_text_fragment">
<LinearLayout
android:orientation="vertical"
@@ -13,7 +15,8 @@
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="4dp"
- android:paddingBottom="4dp">
+ android:paddingBottom="4dp"
+ android:animateLayoutChanges="true">
<LinearLayout
android:orientation="horizontal"
@@ -32,10 +35,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="Not Encrypted (set in-code)"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp" />
+ android:layout_marginBottom="8dp"
+ tools:text="Encryption status text"
+ />
</LinearLayout>
<LinearLayout
@@ -55,25 +59,19 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="Signed by (set in-code)"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp" />
+ android:layout_marginBottom="8dp"
+ tools:text="Signature status text"
+ />
</LinearLayout>
- <View
- android:id="@+id/result_signature_divider1"
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_marginLeft="32dp"
- android:background="?android:attr/listDivider" />
-
<LinearLayout
android:id="@+id/result_signature_layout"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:clickable="true"
- android:layout_marginLeft="32dp"
+ android:paddingLeft="4dp"
android:paddingRight="4dp"
android:background="?android:selectableItemBackground"
android:orientation="horizontal">
@@ -83,6 +81,7 @@
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingRight="4dp"
+ android:paddingLeft="4dp"
android:gravity="center_vertical"
android:orientation="vertical">
@@ -91,15 +90,16 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="Alice (set in-code)" />
+ tools:text="Alice" />
<TextView
android:id="@+id/result_signature_email"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="alice@example.com (set in-code)"
- android:gravity="center_vertical" />
+ android:gravity="center_vertical"
+ tools:text="alice@example.com"
+ />
</LinearLayout>
@@ -114,6 +114,7 @@
<TextView
android:id="@+id/result_signature_action"
android:paddingLeft="8dp"
+ android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -121,17 +122,10 @@
android:drawableRight="@drawable/ic_vpn_key_grey_24dp"
android:drawablePadding="8dp"
android:gravity="center_vertical"
- android:background="?android:selectableItemBackground" />
+ />
</LinearLayout>
- <View
- android:id="@+id/result_signature_divider2"
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_marginLeft="32dp"
- android:background="?android:attr/listDivider" />
-
</LinearLayout>
<View
diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
index 1d0873c96..efdbf03c0 100644
--- a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml
@@ -36,55 +36,6 @@
</ScrollView>
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:background="?android:attr/listDivider" />
-
- <LinearLayout
- android:id="@+id/action_decrypt_share_plaintext"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:clickable="true"
- android:background="?android:selectableItemBackground"
- android:orientation="horizontal">
-
- <TextView
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:text="@string/btn_add_share_decrypted_text"
- android:drawableRight="@drawable/ic_share_grey_24dp"
- android:drawablePadding="8dp"
- android:gravity="center_vertical"
- android:layout_weight="1" />
-
- <View
- android:layout_width="1dip"
- android:layout_height="match_parent"
- android:gravity="right"
- android:layout_marginBottom="8dp"
- android:layout_marginTop="8dp"
- android:background="?android:attr/listDivider" />
-
- <ImageButton
- android:id="@+id/action_decrypt_copy_plaintext"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:padding="8dp"
- android:src="@drawable/ic_content_copy_grey_24dp"
- android:layout_gravity="center_vertical"
- android:background="?android:selectableItemBackground" />
-
- </LinearLayout>
-
</LinearLayout>
<LinearLayout
diff --git a/OpenKeychain/src/main/res/menu/decrypt_menu.xml b/OpenKeychain/src/main/res/menu/decrypt_menu.xml
new file mode 100644
index 000000000..c0d7a519f
--- /dev/null
+++ b/OpenKeychain/src/main/res/menu/decrypt_menu.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/decrypt_copy"
+ android:title="@string/btn_copy_decrypted_text"
+ android:icon="@drawable/ic_action_encrypt_copy_24dp"
+ app:showAsAction="ifRoom" />
+
+ <item
+ android:id="@+id/decrypt_share"
+ android:title="@string/btn_share_decrypted_text"
+ android:icon="@drawable/ic_action_encrypt_share_24dp"
+ app:showAsAction="ifRoom" />
+
+</menu> \ No newline at end of file
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index 155ff6dee..0c80066c0 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -79,7 +79,8 @@
<string name="btn_view_cert_key">"View certification key"</string>
<string name="btn_create_key">"Create key"</string>
<string name="btn_add_files">"Add file(s)"</string>
- <string name="btn_add_share_decrypted_text">"Share decrypted text"</string>
+ <string name="btn_share_decrypted_text">"Share decrypted text"</string>
+ <string name="btn_copy_decrypted_text">"Copy decrypted text"</string>
<string name="btn_decrypt_clipboard">"Decrypt text from clipboard"</string>
<string name="btn_decrypt_and_verify">"and verify signatures"</string>
<string name="btn_decrypt_files">"Decrypt files"</string>
@@ -284,16 +285,16 @@
<!-- results shown after decryption/verification -->
<string name="decrypt_result_no_signature">"Not Signed"</string>
<string name="decrypt_result_invalid_signature">"Invalid signature!"</string>
- <string name="decrypt_result_signature_uncertified">"Signed by (not certified!)"</string>
- <string name="decrypt_result_signature_certified">"Signed by"</string>
- <string name="decrypt_result_signature_expired_key">"Key is expired!"</string>
- <string name="decrypt_result_signature_revoked_key">"Key has been revoked!"</string>
- <string name="decrypt_result_signature_missing_key">"Unknown public key"</string>
+ <string name="decrypt_result_signature_uncertified">"Signed by <b>unconfirmed</b> key"</string>
+ <string name="decrypt_result_signature_certified">"Signed by confirmed key"</string>
+ <string name="decrypt_result_signature_expired_key">"Signed by <b>expired</b> key!"</string>
+ <string name="decrypt_result_signature_revoked_key">"Signed by <b>revoked</b> key!"</string>
+ <string name="decrypt_result_signature_missing_key">"Signed by <b>unknown public key</b>"</string>
<string name="decrypt_result_encrypted">"Encrypted"</string>
<string name="decrypt_result_not_encrypted">"Not Encrypted"</string>
<string name="decrypt_result_action_show">"Show"</string>
<string name="decrypt_result_action_Lookup">"Lookup"</string>
- <string name="decrypt_invalid_text">"Either the signature is invalid or the key has been revoked/is expired. You cannot be sure who wrote the text. Do you still want to display it?"</string>
+ <string name="decrypt_invalid_text">"Either the signature is invalid or the key has been revoked. You cannot be sure who wrote the text. Do you still want to display it?"</string>
<string name="decrypt_invalid_button">"I understand the risks, display it!"</string>
<!-- Add keys -->