From 441704f163279b45cb71c5f242df4d5c637aa34a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 2 Jun 2015 22:19:28 +0200 Subject: [PATCH] multi-decrypt: working in principle --- .../keychain/pgp/PgpDecryptVerify.java | 48 ++-- .../service/KeychainIntentService.java | 4 - .../keychain/ui/DecryptFilesListFragment.java | 214 +++++++++++++++--- .../keychain/ui/util/KeyFormattingUtils.java | 163 ++++++++++++- .../main/res/layout/decrypt_list_entry.xml | 54 ++--- 5 files changed, 403 insertions(+), 80 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 235b0a671..5b4f7a65b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -24,7 +24,6 @@ import android.webkit.MimeTypeMap; import org.openintents.openpgp.OpenPgpMetadata; import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.bcpg.ArmoredInputStream; -import org.spongycastle.bcpg.PublicKeyEncSessionPacket; import org.spongycastle.openpgp.PGPCompressedData; import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedDataList; @@ -674,9 +673,6 @@ public class PgpDecryptVerify extends BaseOperation { PGPLiteralData literalData = (PGPLiteralData) dataChunk; - // reported size may be null if partial packets are involved (highly unlikely though) - Long originalSize = literalData.getDataLengthIfAvailable(); - String originalFilename = literalData.getFileName(); String mimeType = null; if (literalData.getFormat() == PGPLiteralData.TEXT @@ -699,12 +695,6 @@ public class PgpDecryptVerify extends BaseOperation { } } - metadata = new OpenPgpMetadata( - originalFilename, - mimeType, - literalData.getModificationTime().getTime(), - originalSize == null ? 0 : originalSize); - if (!"".equals(originalFilename)) { log.add(LogType.MSG_DC_CLEAR_META_FILE, indent + 1, originalFilename); } @@ -712,15 +702,26 @@ public class PgpDecryptVerify extends BaseOperation { mimeType); log.add(LogType.MSG_DC_CLEAR_META_TIME, indent + 1, new Date(literalData.getModificationTime().getTime()).toString()); - if (originalSize != null) { - log.add(LogType.MSG_DC_CLEAR_META_SIZE, indent + 1, - Long.toString(originalSize)); - } else { - log.add(LogType.MSG_DC_CLEAR_META_SIZE_UNKNOWN, indent + 1); - } // return here if we want to decrypt the metadata only if (input.isDecryptMetadataOnly()) { + + // this operation skips the entire stream to find the data length! + Long originalSize = literalData.findDataLength(); + + if (originalSize != null) { + log.add(LogType.MSG_DC_CLEAR_META_SIZE, indent + 1, + Long.toString(originalSize)); + } else { + log.add(LogType.MSG_DC_CLEAR_META_SIZE_UNKNOWN, indent + 1); + } + + metadata = new OpenPgpMetadata( + originalFilename, + mimeType, + literalData.getModificationTime().getTime(), + originalSize == null ? 0 : originalSize); + log.add(LogType.MSG_DC_OK_META_ONLY, indent); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); @@ -769,6 +770,21 @@ public class PgpDecryptVerify extends BaseOperation { // TODO: slow annealing to fake a progress? } + // after going through the stream, size should be available + Long originalSize = literalData.getDataLengthIfAvailable(); + if (originalSize != null) { + log.add(LogType.MSG_DC_CLEAR_META_SIZE, indent + 1, + Long.toString(originalSize)); + } else { + log.add(LogType.MSG_DC_CLEAR_META_SIZE_UNKNOWN, indent + 1); + } + + metadata = new OpenPgpMetadata( + originalFilename, + mimeType, + literalData.getModificationTime().getTime(), + originalSize == null ? 0 : originalSize); + if (signature != null) { updateProgress(R.string.progress_verifying_signature, 90, 100); log.add(LogType.MSG_DC_CLEAR_SIGNATURE_CHECK, indent); 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 5f9c98ac5..c1e4ceef5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -358,10 +358,6 @@ public class KeychainIntentService extends IntentService implements Progressable CryptoInputParcel cryptoInput = data.getParcelable(EXTRA_CRYPTO_INPUT); PgpDecryptVerifyInputParcel input = data.getParcelable(DECRYPT_VERIFY_PARCEL); - // for compatibility - // TODO merge with ACTION_DECRYPT_METADATA - input.setDecryptMetadataOnly(false); - /* Operation */ PgpDecryptVerify op = new PgpDecryptVerify(this, new ProviderHelper(this), this); DecryptVerifyResult decryptVerifyResult = op.execute(input, cryptoInput); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java index 8768a7935..bf21421a1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesListFragment.java @@ -19,11 +19,14 @@ package org.sufficientlysecure.keychain.ui; import java.util.ArrayList; +import java.util.List; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -34,6 +37,7 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; +import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; @@ -46,6 +50,8 @@ import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyInputParcel; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.provider.TemporaryStorageProvider; import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.ServiceProgressHandler; import org.sufficientlysecure.keychain.service.ServiceProgressHandler.MessageStatus; @@ -54,7 +60,7 @@ import org.sufficientlysecure.keychain.ui.adapter.SpacesItemDecoration; import org.sufficientlysecure.keychain.ui.base.CryptoOperationFragment; import org.sufficientlysecure.keychain.ui.util.FormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.StatusHolder; import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.util.Log; @@ -64,10 +70,12 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { private static final int REQUEST_CODE_OUTPUT = 0x00007007; private ArrayList mInputUris; + private ArrayList mOutputUris; private ArrayList mPendingInputUris; - private Uri mCurrentInputUri; - private Uri mOutputUri = null; + private Uri mCurrentInputUri, mCurrentOutputUri; + private boolean mDecryptingMetadata; + private RecyclerView mFilesList; private DecryptFilesAdapter mAdapter; @@ -130,10 +138,18 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { private void displayInputUris(ArrayList uris) { mInputUris = uris; - mPendingInputUris = uris; + mOutputUris = new ArrayList<>(uris.size()); for (Uri uri : uris) { mAdapter.add(uri); + String targetName = (mEncryptFilenames ? String.valueOf(filenameCounter) : FileHelper.getFilename(getActivity(), model.inputUri)) + + (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN); + mOutputUris.add(TemporaryStorageProvider.createFile(getActivity(), targetName)); + filenameCounter++; } + + mPendingInputUris = uris; + mDecryptingMetadata = true; + cryptoOperation(); } @@ -141,8 +157,50 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { mAdapter.setProgress(uri, progress, max, msg); } - private void displayInputResult(Uri uri, DecryptVerifyResult result) { - mAdapter.addResult(uri, result); + private void displayInputResult(final Uri uri, DecryptVerifyResult result) { + Drawable icon = null; + OnClickListener onFileClick = null, onKeyClick = null; + + if (result.success()) { + + if (result.getDecryptMetadata() != null && result.getDecryptMetadata().getMimeType() != null) { + icon = loadIcon(result.getDecryptMetadata().getMimeType()); + } + + OpenPgpSignatureResult sigResult = result.getSignatureResult(); + if (sigResult != null) { + final long keyId = sigResult.getKeyId(); + if (sigResult.getStatus() != OpenPgpSignatureResult.SIGNATURE_KEY_MISSING) { + onKeyClick = new OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(getActivity(), ViewKeyActivity.class); + intent.setData(KeyRings.buildUnifiedKeyRingUri(keyId)); + getActivity().startActivity(intent); + } + }; + } + } + + if (result.success()) { + onFileClick = new OnClickListener() { + @Override + public void onClick(View view) { + if (mCurrentInputUri != null) { + return; + } + + mCurrentInputUri = uri; + mDecryptingMetadata = false; + cryptoOperation(); + } + }; + } + + } + + mAdapter.addResult(uri, result, icon, onFileClick, onKeyClick); + } @Override @@ -169,10 +227,11 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { // data - Log.d(Constants.TAG, "mInputUri=" + mCurrentInputUri + ", mOutputUri=" + mOutputUri); + Log.d(Constants.TAG, "mInputUri=" + mCurrentInputUri + ", mOutputUri=" + mCurrentOutputUri); - PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mCurrentInputUri, mOutputUri) - .setAllowSymmetricDecryption(true); + PgpDecryptVerifyInputParcel input = new PgpDecryptVerifyInputParcel(mCurrentInputUri, mCurrentOutputUri) + .setAllowSymmetricDecryption(true) + .setDecryptMetadataOnly(true); data.putParcelable(KeychainIntentService.DECRYPT_VERIFY_PARCEL, input); data.putParcelable(KeychainIntentService.EXTRA_CRYPTO_INPUT, cryptoInput); @@ -251,7 +310,7 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { case REQUEST_CODE_OUTPUT: { // This happens after output file was selected, so start our operation if (resultCode == Activity.RESULT_OK && data != null) { - mOutputUri = data.getData(); + // mCurrentOutputUri = data.getData(); // startDecrypt(); } return; @@ -271,6 +330,10 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { Context mContext; Uri mUri; DecryptVerifyResult mResult; + Drawable mIcon; + + OnClickListener mOnFileClickListener; + OnClickListener mOnKeyClickListener; int mProgress, mMax; String mProgressMsg; @@ -286,6 +349,15 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { mResult = result; } + void addIcon(Drawable icon) { + mIcon = icon; + } + + void setOnClickListeners(OnClickListener onFileClick, OnClickListener onKeyClick) { + mOnFileClickListener = onFileClick; + mOnKeyClickListener = onKeyClick; + } + boolean hasResult() { return mResult != null; } @@ -347,26 +419,28 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { holder.vAnimator.setDisplayedChild(1); } - OpenPgpSignatureResult signature = model.mResult.getSignatureResult(); - if (signature != null) { - KeyFormattingUtils.setStatusImage(mContext, holder.vStatusIcon, holder.vStatusText, - State.VERIFIED); - holder.vStatusText.setText("Yolo!"); - holder.vSignatureName.setText(signature.getPrimaryUserId()); - } else { - KeyFormattingUtils.setStatusImage(mContext, - holder.vStatusIcon, holder.vStatusText, State.UNAVAILABLE); - } + KeyFormattingUtils.setStatus(mContext, holder, model.mResult); OpenPgpMetadata metadata = model.mResult.getDecryptMetadata(); holder.vFilename.setText(metadata.getFilename()); long size = metadata.getOriginalSize(); - if (size == -1) { + if (size == -1 || size == 0) { holder.vFilesize.setText(""); } else { holder.vFilesize.setText(FileHelper.readableFileSize(size)); } + + // TODO thumbnail from OpenPgpMetadata + if (model.mIcon != null) { + holder.vThumbnail.setImageDrawable(model.mIcon); + } else { + holder.vThumbnail.setImageResource(R.drawable.ic_doc_generic_am); + } + + holder.vFile.setOnClickListener(model.mOnFileClickListener); + holder.vSignatureLayout.setOnClickListener(model.mOnKeyClickListener); + } else { if (holder.vAnimator.getDisplayedChild() != 0) { holder.vAnimator.setDisplayedChild(0); @@ -398,10 +472,19 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { notifyItemChanged(pos); } - public void addResult(Uri uri, DecryptVerifyResult result) { - ViewModel newModel = new ViewModel(mContext, uri); - int pos = mDataset.indexOf(newModel); - mDataset.get(pos).addResult(result); + public void addResult(Uri uri, DecryptVerifyResult result, Drawable icon, + OnClickListener onFileClick, OnClickListener onKeyClick) { + + ViewModel model = new ViewModel(mContext, uri); + int pos = mDataset.indexOf(model); + model = mDataset.get(pos); + + model.addResult(result); + if (icon != null) { + model.addIcon(icon); + } + model.setOnClickListeners(onFileClick, onKeyClick); + notifyItemChanged(pos); } @@ -411,21 +494,26 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder - public static class ViewHolder extends RecyclerView.ViewHolder { + public static class ViewHolder extends RecyclerView.ViewHolder implements StatusHolder { public ViewAnimator vAnimator; public ProgressBar vProgress; public TextView vProgressMsg; + public View vFile; public TextView vFilename; public TextView vFilesize; - public View vRemoveButton; public ImageView vThumbnail; - public ImageView vStatusIcon; - public TextView vStatusText; + public ImageView vEncStatusIcon; + public TextView vEncStatusText; + + public ImageView vSigStatusIcon; + public TextView vSigStatusText; + public View vSignatureLayout; public TextView vSignatureName; public TextView vSignatureMail; + public TextView vSignatureAction; public ViewHolder(View itemView) { super(itemView); @@ -435,18 +523,80 @@ public class DecryptFilesListFragment extends CryptoOperationFragment { vProgress = (ProgressBar) itemView.findViewById(R.id.progress); vProgressMsg = (TextView) itemView.findViewById(R.id.progress_msg); + vFile = itemView.findViewById(R.id.file); vFilename = (TextView) itemView.findViewById(R.id.filename); vFilesize = (TextView) itemView.findViewById(R.id.filesize); - vRemoveButton = itemView.findViewById(R.id.action_remove_file_from_list); vThumbnail = (ImageView) itemView.findViewById(R.id.thumbnail); - vStatusIcon = (ImageView) itemView.findViewById(R.id.result_signature_icon); - vStatusText = (TextView) itemView.findViewById(R.id.result_signature_text); + vEncStatusIcon = (ImageView) itemView.findViewById(R.id.result_encryption_icon); + vEncStatusText = (TextView) itemView.findViewById(R.id.result_encryption_text); + + vSigStatusIcon = (ImageView) itemView.findViewById(R.id.result_signature_icon); + vSigStatusText = (TextView) itemView.findViewById(R.id.result_signature_text); + vSignatureLayout = itemView.findViewById(R.id.result_signature_layout); vSignatureName = (TextView) itemView.findViewById(R.id.result_signature_name); vSignatureMail= (TextView) itemView.findViewById(R.id.result_signature_email); + vSignatureAction = (TextView) itemView.findViewById(R.id.result_signature_action); } + @Override + public ImageView getEncryptionStatusIcon() { + return vEncStatusIcon; + } + + @Override + public TextView getEncryptionStatusText() { + return vEncStatusText; + } + + @Override + public ImageView getSignatureStatusIcon() { + return vSigStatusIcon; + } + + @Override + public TextView getSignatureStatusText() { + return vSigStatusText; + } + + @Override + public View getSignatureLayout() { + return vSignatureLayout; + } + + @Override + public TextView getSignatureAction() { + return vSignatureAction; + } + + @Override + public TextView getSignatureUserName() { + return vSignatureName; + } + + @Override + public TextView getSignatureUserEmail() { + return vSignatureMail; + } + + @Override + public boolean hasEncrypt() { + return true; + } + } + + private Drawable loadIcon(String mimeType) { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setType(mimeType); + + final List matches = getActivity() + .getPackageManager().queryIntentActivities(intent, 0); + for (ResolveInfo match : matches) { + return match.loadIcon(getActivity().getPackageManager()); + } + return null; + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index dd85a6e46..11524aa08 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -24,9 +24,11 @@ import android.graphics.PorterDuff; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.style.ForegroundColorSpan; +import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import org.openintents.openpgp.OpenPgpSignatureResult; import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.nist.NISTNamedCurves; import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves; @@ -34,6 +36,8 @@ import org.spongycastle.bcpg.PublicKeyAlgorithmTags; import org.spongycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult; +import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm; import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Curve; import org.sufficientlysecure.keychain.util.Log; @@ -376,7 +380,6 @@ public class KeyFormattingUtils { /** * Converts the given bytes to a unique RGB color using SHA1 algorithm * - * @param bytes * @return an integer array containing 3 numeric color representations (Red, Green, Black) * @throws java.security.NoSuchAlgorithmException * @throws java.security.DigestException @@ -394,7 +397,7 @@ public class KeyFormattingUtils { public static final int DEFAULT_COLOR = -1; - public static enum State { + public enum State { REVOKED, EXPIRED, VERIFIED, @@ -420,9 +423,165 @@ public class KeyFormattingUtils { setStatusImage(context, statusIcon, statusText, state, color, false); } + public interface StatusHolder { + ImageView getEncryptionStatusIcon(); + TextView getEncryptionStatusText(); + + ImageView getSignatureStatusIcon(); + TextView getSignatureStatusText(); + + View getSignatureLayout(); + TextView getSignatureUserName(); + TextView getSignatureUserEmail(); + TextView getSignatureAction(); + + boolean hasEncrypt(); + + } + + @SuppressWarnings("deprecation") // context.getDrawable is api lvl 21, need to use deprecated + public static void setStatus(Context context, StatusHolder holder, DecryptVerifyResult result) { + + OpenPgpSignatureResult signatureResult = result.getSignatureResult(); + + if (holder.hasEncrypt()) { + int encText, encIcon, encColor; + if (signatureResult != null && signatureResult.isSignatureOnly()) { + encIcon = R.drawable.status_lock_open_24dp; + encText = R.string.decrypt_result_not_encrypted; + encColor = R.color.android_red_light; + } else { + encIcon = R.drawable.status_lock_closed_24dp; + encText = R.string.decrypt_result_encrypted; + encColor = R.color.android_green_light; + } + + int encColorRes = context.getResources().getColor(encColor); + holder.getEncryptionStatusIcon().setImageDrawable(context.getResources().getDrawable(encIcon)); + holder.getEncryptionStatusIcon().setColorFilter(encColorRes, PorterDuff.Mode.SRC_IN); + holder.getEncryptionStatusText().setText(encText); + holder.getEncryptionStatusText().setTextColor(encColorRes); + } + + int sigText, sigIcon, sigColor; + int sigActionText, sigActionIcon; + + if (signatureResult == null) { + + sigText = R.string.decrypt_result_no_signature; + sigIcon = R.drawable.status_signature_invalid_cutout_24dp; + sigColor = R.color.bg_gray; + + // won't be used, but makes compiler happy + sigActionText = 0; + sigActionIcon = 0; + + } else switch (signatureResult.getStatus()) { + + case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { + sigText = R.string.decrypt_result_signature_certified; + sigIcon = R.drawable.status_signature_verified_cutout_24dp; + sigColor = R.color.android_green_light; + + sigActionText = R.string.decrypt_result_action_show; + sigActionIcon = R.drawable.ic_vpn_key_grey_24dp; + break; + } + + case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { + sigText = R.string.decrypt_result_signature_uncertified; + sigIcon = R.drawable.status_signature_unverified_cutout_24dp; + sigColor = R.color.android_orange_light; + + sigActionText = R.string.decrypt_result_action_show; + sigActionIcon = R.drawable.ic_vpn_key_grey_24dp; + break; + } + + case OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED: { + sigText = R.string.decrypt_result_signature_revoked_key; + sigIcon = R.drawable.status_signature_revoked_cutout_24dp; + sigColor = R.color.android_red_light; + + sigActionText = R.string.decrypt_result_action_show; + sigActionIcon = R.drawable.ic_vpn_key_grey_24dp; + break; + } + + case OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED: { + sigText = R.string.decrypt_result_signature_expired_key; + sigIcon = R.drawable.status_signature_expired_cutout_24dp; + sigColor = R.color.android_red_light; + + sigActionText = R.string.decrypt_result_action_show; + sigActionIcon = R.drawable.ic_vpn_key_grey_24dp; + break; + } + + case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: { + sigText = R.string.decrypt_result_signature_missing_key; + sigIcon = R.drawable.status_signature_unknown_cutout_24dp; + sigColor = R.color.android_red_light; + + sigActionText = R.string.decrypt_result_action_Lookup; + sigActionIcon = R.drawable.ic_file_download_grey_24dp; + break; + } + + default: + case OpenPgpSignatureResult.SIGNATURE_ERROR: { + sigText = R.string.decrypt_result_invalid_signature; + sigIcon = R.drawable.status_signature_invalid_cutout_24dp; + sigColor = R.color.android_red_light; + + sigActionText = R.string.decrypt_result_action_show; + sigActionIcon = R.drawable.ic_vpn_key_grey_24dp; + break; + } + + } + + int sigColorRes = context.getResources().getColor(sigColor); + holder.getSignatureStatusIcon().setImageDrawable(context.getResources().getDrawable(sigIcon)); + holder.getSignatureStatusIcon().setColorFilter(sigColorRes, PorterDuff.Mode.SRC_IN); + holder.getSignatureStatusText().setText(sigText); + holder.getSignatureStatusText().setTextColor(sigColorRes); + + if (signatureResult != null) { + + holder.getSignatureLayout().setVisibility(View.VISIBLE); + + holder.getSignatureAction().setText(sigActionText); + holder.getSignatureAction().setCompoundDrawablesWithIntrinsicBounds( + 0, 0, sigActionIcon, 0); + + String userId = signatureResult.getPrimaryUserId(); + KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId); + if (userIdSplit.name != null) { + holder.getSignatureUserName().setText(userIdSplit.name); + } else { + holder.getSignatureUserName().setText(R.string.user_id_no_name); + } + if (userIdSplit.email != null) { + holder.getSignatureUserEmail().setVisibility(View.VISIBLE); + holder.getSignatureUserEmail().setText(userIdSplit.email); + } else { + holder.getSignatureUserEmail().setVisibility(View.GONE); + } + + } else { + + holder.getSignatureLayout().setVisibility(View.GONE); + + } + + + } + /** * Sets status image based on constant */ + @SuppressWarnings("deprecation") // context.getDrawable is api lvl 21 public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText, State state, int color, boolean big) { switch (state) { diff --git a/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml b/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml index 3bf4948f4..b95a087bb 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_list_entry.xml @@ -51,6 +51,30 @@ android:layout_height="wrap_content" android:orientation="vertical"> + + + + + + + - - - - - - -