diff options
| author | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-03-30 18:37:32 +0200 | 
|---|---|---|
| committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2014-03-30 19:32:05 +0200 | 
| commit | 2947ab7e483e90d054f88ed267ea1160fd5b2f1d (patch) | |
| tree | 5add118788e7144c2a4d603eb46211ac376733d7 /OpenPGP-Keychain/src | |
| parent | 4cec2194e01b7213271fa1fb0d50e5ae386fb16e (diff) | |
| download | open-keychain-2947ab7e483e90d054f88ed267ea1160fd5b2f1d.tar.gz open-keychain-2947ab7e483e90d054f88ed267ea1160fd5b2f1d.tar.bz2 open-keychain-2947ab7e483e90d054f88ed267ea1160fd5b2f1d.zip | |
More experimental work on decrypt fragments
Diffstat (limited to 'OpenPGP-Keychain/src')
14 files changed, 831 insertions, 516 deletions
| diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index 571729bc5..d06898c89 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -75,7 +75,7 @@ public class PgpDecryptVerify {          // optional          private ProgressDialogUpdater mProgressDialogUpdater = null;          private boolean mAssumeSymmetric = false; -        private String mPassphrase = ""; +        private String mPassphrase = null;          private long mEnforcedKeyId = 0;          public Builder(Context context, InputData data, OutputStream outStream) { @@ -253,8 +253,6 @@ public class PgpDecryptVerify {              encryptedData = pbe;              currentProgress += 5;          } else { -            updateProgress(R.string.progress_finding_key, currentProgress, 100); -              PGPPublicKeyEncryptedData pbe = null;              PGPSecretKey secretKey = null;              Iterator<?> it = enc.getEncryptedDataObjects(); @@ -262,6 +260,8 @@ public class PgpDecryptVerify {              while (it.hasNext()) {                  Object obj = it.next();                  if (obj instanceof PGPPublicKeyEncryptedData) { +                    updateProgress(R.string.progress_finding_key, currentProgress, 100); +                      PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) obj;                      secretKey = ProviderHelper.getPGPSecretKeyByKeyId(mContext, encData.getKeyID());                      if (secretKey != null) { @@ -294,14 +294,15 @@ public class PgpDecryptVerify {                              // if passphrase was not cached, return here                              // indicating that a passphrase is missing!                              if (mPassphrase == null) { -                                returnData.setKeyPassphraseNeeded(true); +                                returnData.setKeyIdPassphraseNeeded(encData.getKeyID()); +                                returnData.setStatus(PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED);                                  return returnData;                              }                          }                          break;                      } - +                } else if (obj instanceof PGPPBEEncryptedData) {                  }              } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java index d4a4f6075..ad240e834 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerifyResult.java @@ -19,27 +19,33 @@ package org.sufficientlysecure.keychain.pgp;  import android.os.Parcel;  import android.os.Parcelable; +  import org.openintents.openpgp.OpenPgpSignatureResult;  public class PgpDecryptVerifyResult implements Parcelable { -    boolean mSymmetricPassphraseNeeded; -    boolean mKeyPassphraseNeeded; +    public static final int SUCCESS = 1; +    public static final int KEY_PASSHRASE_NEEDED = 2; +    public static final int SYMMETRIC_PASSHRASE_NEEDED = 3; + +    int mStatus; +    long mKeyIdPassphraseNeeded; +      OpenPgpSignatureResult mSignatureResult; -    public boolean isSymmetricPassphraseNeeded() { -        return mSymmetricPassphraseNeeded; +    public int getStatus() { +        return mStatus;      } -    public void setSymmetricPassphraseNeeded(boolean symmetricPassphraseNeeded) { -        this.mSymmetricPassphraseNeeded = symmetricPassphraseNeeded; +    public void setStatus(int mStatus) { +        this.mStatus = mStatus;      } -    public boolean isKeyPassphraseNeeded() { -        return mKeyPassphraseNeeded; +    public long getKeyIdPassphraseNeeded() { +        return mKeyIdPassphraseNeeded;      } -    public void setKeyPassphraseNeeded(boolean keyPassphraseNeeded) { -        this.mKeyPassphraseNeeded = keyPassphraseNeeded; +    public void setKeyIdPassphraseNeeded(long mKeyIdPassphraseNeeded) { +        this.mKeyIdPassphraseNeeded = mKeyIdPassphraseNeeded;      }      public OpenPgpSignatureResult getSignatureResult() { @@ -55,8 +61,8 @@ public class PgpDecryptVerifyResult implements Parcelable {      }      public PgpDecryptVerifyResult(PgpDecryptVerifyResult b) { -        this.mSymmetricPassphraseNeeded = b.mSymmetricPassphraseNeeded; -        this.mKeyPassphraseNeeded = b.mKeyPassphraseNeeded; +        this.mStatus = b.mStatus; +        this.mKeyIdPassphraseNeeded = b.mKeyIdPassphraseNeeded;          this.mSignatureResult = b.mSignatureResult;      } @@ -66,16 +72,16 @@ public class PgpDecryptVerifyResult implements Parcelable {      }      public void writeToParcel(Parcel dest, int flags) { -        dest.writeByte((byte) (mSymmetricPassphraseNeeded ? 1 : 0)); -        dest.writeByte((byte) (mKeyPassphraseNeeded ? 1 : 0)); +        dest.writeInt(mStatus); +        dest.writeLong(mKeyIdPassphraseNeeded);          dest.writeParcelable(mSignatureResult, 0);      }      public static final Creator<PgpDecryptVerifyResult> CREATOR = new Creator<PgpDecryptVerifyResult>() {          public PgpDecryptVerifyResult createFromParcel(final Parcel source) {              PgpDecryptVerifyResult vr = new PgpDecryptVerifyResult(); -            vr.mSymmetricPassphraseNeeded = source.readByte() == 1; -            vr.mKeyPassphraseNeeded = source.readByte() == 1; +            vr.mStatus = source.readInt(); +            vr.mKeyIdPassphraseNeeded = source.readLong();              vr.mSignatureResult = source.readParcelable(OpenPgpSignatureResult.class.getClassLoader());              return vr;          } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index 2680d77af..cc40afbac 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.pgp;  import android.content.Context;  import android.content.pm.PackageInfo;  import android.content.pm.PackageManager.NameNotFoundException; +  import org.spongycastle.openpgp.*;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.Id; @@ -43,7 +44,7 @@ public class PgpHelper {      public static final Pattern PGP_MESSAGE = Pattern.compile(              ".*?(-----BEGIN PGP MESSAGE-----.*?-----END PGP MESSAGE-----).*", Pattern.DOTALL); -    public static final Pattern PGP_SIGNED_MESSAGE = Pattern +    public static final Pattern PGP_CLEARTEXT_SIGNATURE = Pattern              .compile(                      ".*?(-----BEGIN PGP SIGNED MESSAGE-----.*?-----BEGIN PGP SIGNATURE-----.*?-----END PGP SIGNATURE-----).*",                      Pattern.DOTALL); diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index f85e342d8..1d3bb88df 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -298,11 +298,11 @@ public class OpenPgpService extends RemoteService {                  // TODO: currently does not support binary signed-only content                  PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); -                if (decryptVerifyResult.isKeyPassphraseNeeded()) { +                if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {                      // get PendingIntent for passphrase input, add it to given params and return to client                      Intent passphraseBundle = getPassphraseBundleIntent(data, accSettings.getKeyId());                      return passphraseBundle; -                } else if (decryptVerifyResult.isSymmetricPassphraseNeeded()) { +                } else if (PgpDecryptVerifyResult.SYMMETRIC_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) {                      throw new PgpGeneralException("Decryption of symmetric content not supported by API!");                  } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 846eb8cf9..2cc3798e0 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -100,9 +100,9 @@ public class KeychainIntentService extends IntentService      public static final String ENCRYPT_PROVIDER_URI = "provider_uri";      // decrypt/verify -    public static final String DECRYPT_RETURN_BYTES = "return_binary";      public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes";      public static final String DECRYPT_ASSUME_SYMMETRIC = "assume_symmetric"; +    public static final String DECRYPT_PASSPHRASE = "passphrase";      // save keyring      public static final String SAVE_KEYRING_PARCEL = "save_parcel"; @@ -155,7 +155,6 @@ public class KeychainIntentService extends IntentService      public static final String RESULT_URI = "result_uri";      // decrypt/verify -    public static final String RESULT_DECRYPTED_STRING = "decrypted_message";      public static final String RESULT_DECRYPTED_BYTES = "decrypted_data";      public static final String RESULT_DECRYPT_VERIFY_RESULT = "signature"; @@ -387,15 +386,14 @@ public class KeychainIntentService extends IntentService                  /* Input */                  int target = data.getInt(TARGET); -                long secretKeyId = data.getLong(ENCRYPT_SECRET_KEY_ID);                  byte[] bytes = data.getByteArray(DECRYPT_CIPHERTEXT_BYTES); -                boolean returnBytes = data.getBoolean(DECRYPT_RETURN_BYTES);                  boolean assumeSymmetricEncryption = data.getBoolean(DECRYPT_ASSUME_SYMMETRIC); +                String passphrase = data.getString(DECRYPT_PASSPHRASE); -                InputStream inStream = null; -                long inLength = -1; -                InputData inputData = null; -                OutputStream outStream = null; +                InputStream inStream; +                long inLength; +                InputData inputData; +                OutputStream outStream;                  String streamFilename = null;                  switch (target) {                      case TARGET_BYTES: /* decrypting bytes directly */ @@ -469,7 +467,7 @@ public class KeychainIntentService extends IntentService                  builder.progressDialogUpdater(this);                  builder.assumeSymmetric(assumeSymmetricEncryption) -                        .passphrase(PassphraseCacheService.getCachedPassphrase(this, secretKeyId)); +                        .passphrase(passphrase);                  PgpDecryptVerifyResult decryptVerifyResult = builder.build().execute(); @@ -481,15 +479,8 @@ public class KeychainIntentService extends IntentService                  switch (target) {                      case TARGET_BYTES: -                        if (returnBytes) { -                            byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); -                            resultData.putByteArray(RESULT_DECRYPTED_BYTES, output); -                        } else { -                            String output = new String( -                                    ((ByteArrayOutputStream) outStream).toByteArray()); -                            resultData.putString(RESULT_DECRYPTED_STRING, output); -                        } - +                        byte output[] = ((ByteArrayOutputStream) outStream).toByteArray(); +                        resultData.putByteArray(RESULT_DECRYPTED_BYTES, output);                          break;                      case TARGET_URI:                          // nothing, file was written, just send okay and verification bundle diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index 24a8854af..21e51dcd9 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -17,8 +17,6 @@  package org.sufficientlysecure.keychain.ui; -import android.annotation.SuppressLint; -import android.app.ProgressDialog;  import android.content.Intent;  import android.net.Uri;  import android.os.Bundle; @@ -30,7 +28,6 @@ import android.support.v4.view.PagerTabStrip;  import android.support.v4.view.ViewPager;  import android.view.View;  import android.view.View.OnClickListener; -import android.view.animation.AnimationUtils;  import android.widget.*;  import com.beardedhen.androidbootstrap.BootstrapButton; @@ -41,21 +38,16 @@ import org.spongycastle.openpgp.PGPPublicKeyRing;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.Id;  import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;  import org.sufficientlysecure.keychain.helper.ActionBarHelper;  import org.sufficientlysecure.keychain.helper.FileHelper;  import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify; -import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;  import org.sufficientlysecure.keychain.pgp.PgpHelper;  import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;  import org.sufficientlysecure.keychain.pgp.exception.NoAsymmetricEncryptionException;  import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;  import org.sufficientlysecure.keychain.provider.ProviderHelper; -import org.sufficientlysecure.keychain.service.KeychainIntentService; -import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;  import org.sufficientlysecure.keychain.service.PassphraseCacheService;  import org.sufficientlysecure.keychain.ui.adapter.PageTabStripAdapter; -import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;  import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;  import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;  import org.sufficientlysecure.keychain.util.Log; @@ -64,7 +56,8 @@ import java.io.*;  import java.util.regex.Matcher;  //@SuppressLint("NewApi") -public class DecryptActivity extends DrawerActivity { +public class DecryptActivity extends DrawerActivity implements DecryptSignatureResultDisplay { +      /* Intents */      // without permission @@ -122,43 +115,13 @@ public class DecryptActivity extends DrawerActivity {      ViewPager mViewPager;      PagerTabStrip mPagerTabStrip;      PageTabStripAdapter mTabsAdapter; -    DecryptMessageFragment mMessageFragment; -    DecryptFileFragment mFileFragment; -    private void initView() { -//        mSource = (ViewFlipper) findViewById(R.id.source); -//        mSourceLabel = (TextView) findViewById(R.id.sourceLabel); -//        mSourcePrevious = (ImageView) findViewById(R.id.sourcePrevious); -//        mSourceNext = (ImageView) findViewById(R.id.sourceNext); -// -//        mSourcePrevious.setClickable(true); -//        mSourcePrevious.setOnClickListener(new OnClickListener() { -//            public void onClick(View v) { -//                mSource.setInAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, -//                        R.anim.push_right_in)); -//                mSource.setOutAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, -//                        R.anim.push_right_out)); -//                mSource.showPrevious(); -//                updateSource(); -//            } -//        }); -// -//        mSourceNext.setClickable(true); -//        OnClickListener nextSourceClickListener = new OnClickListener() { -//            public void onClick(View v) { -//                mSource.setInAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, -//                        R.anim.push_left_in)); -//                mSource.setOutAnimation(AnimationUtils.loadAnimation(DecryptActivity.this, -//                        R.anim.push_left_out)); -//                mSource.showNext(); -//                updateSource(); -//            } -//        }; -//        mSourceNext.setOnClickListener(nextSourceClickListener); -// -//        mSourceLabel.setClickable(true); -//        mSourceLabel.setOnClickListener(nextSourceClickListener); +    private static final int PAGER_TAB_MESSAGE = 0; +    private static final int PAGER_TAB_FILE = 1; + + +    private void initView() {          mSignatureLayout = (RelativeLayout) findViewById(R.id.signature);          mSignatureStatusImage = (ImageView) findViewById(R.id.ic_signature_status);          mUserId = (TextView) findViewById(R.id.mainUserId); @@ -171,24 +134,24 @@ public class DecryptActivity extends DrawerActivity {  //        int height = tmp.getMeasuredHeight();  //        mMessage.setMinimumHeight(height); -        mFilename = (EditText) findViewById(R.id.filename); -        mBrowse = (BootstrapButton) findViewById(R.id.btn_browse); -        mBrowse.setOnClickListener(new View.OnClickListener() { -            public void onClick(View v) { -                FileHelper.openFile(DecryptActivity.this, mFilename.getText().toString(), "*/*", -                        RESULT_CODE_FILE); -            } -        }); - -        mLookupKey = (BootstrapButton) findViewById(R.id.lookup_key); -        mLookupKey.setOnClickListener(new OnClickListener() { -            @Override -            public void onClick(View v) { -                lookupUnknownKey(mSignatureKeyId); -            } -        }); - -        mDeleteAfter = (CheckBox) findViewById(R.id.deleteAfterDecryption); +//        mFilename = (EditText) findViewById(R.id.filename); +//        mBrowse = (BootstrapButton) findViewById(R.id.btn_browse); +//        mBrowse.setOnClickListener(new View.OnClickListener() { +//            public void onClick(View v) { +//                FileHelper.openFile(DecryptActivity.this, mFilename.getText().toString(), "*/*", +//                        RESULT_CODE_FILE); +//            } +//        }); +// +//        mLookupKey = (BootstrapButton) findViewById(R.id.lookup_key); +//        mLookupKey.setOnClickListener(new OnClickListener() { +//            @Override +//            public void onClick(View v) { +//                lookupUnknownKey(mSignatureKeyId); +//            } +//        }); +// +//        mDeleteAfter = (CheckBox) findViewById(R.id.deleteAfterDecryption);          // default: message source  //        mSource.setInAnimation(null); @@ -197,23 +160,19 @@ public class DecryptActivity extends DrawerActivity {  //            mSource.showNext();  //        } -        mDecryptButton = (BootstrapButton) findViewById(R.id.action_decrypt); -        mDecryptButton.setOnClickListener(new OnClickListener() { -            @Override -            public void onClick(View v) { -                decryptClicked(); -            } -        }); +//        mDecryptButton = (BootstrapButton) findViewById(R.id.action_decrypt); +//        mDecryptButton.setOnClickListener(new OnClickListener() { +//            @Override +//            public void onClick(View v) { +//                decryptClicked(); +//            } +//        }); + +        // Pager          mViewPager = (ViewPager) findViewById(R.id.decrypt_pager);          mPagerTabStrip = (PagerTabStrip) findViewById(R.id.decrypt_pager_tab_strip); -        initPager(); -    } -    private static final int PAGER_TAB_MESSAGE = 0; -    private static final int PAGER_TAB_FILE = 1; - -    private void initPager() {          mTabsAdapter = new PageTabStripAdapter(this);          mViewPager.setAdapter(mTabsAdapter); @@ -222,20 +181,9 @@ public class DecryptActivity extends DrawerActivity {          Bundle fileBundle = new Bundle();          mTabsAdapter.addTab(DecryptFileFragment.class, fileBundle, getString(R.string.label_file)); - -//        mPagerTabStrip. -        getSupportFragmentManager().executePendingTransactions(); -//        for (Fragment f : getSupportFragmentManager().getFragments()) { -//            Log.d(Constants.TAG, "f: "+f.getTag()); -//        } - -        DecryptMessageFragment messageFragment = (DecryptMessageFragment) getFragmentByPosition(PAGER_TAB_MESSAGE); -//        mFileFragment = (DecryptFileFragment) getFragmentByPosition(PAGER_TAB_FILE); - -//        Log.d(Constants.TAG, fr.getTag()); -//      } +      /**       * find fragment       * @@ -265,26 +213,6 @@ public class DecryptActivity extends DrawerActivity {          // Handle intent actions          handleActions(getIntent()); -//        if (mSource.getCurrentView().getId() == R.id.sourceMessage -//                && mMessage.getText().length() == 0) { -// -//            CharSequence clipboardText = ClipboardReflection.getClipboardText(this); -// -//            String data = ""; -//            if (clipboardText != null) { -//                Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText); -//                if (!matcher.matches()) { -//                    matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(clipboardText); -//                } -//                if (matcher.matches()) { -//                    data = matcher.group(1); -//                    mMessage.setText(data); -//                    AppMsg.makeText(this, R.string.using_clipboard_content, AppMsg.STYLE_INFO) -//                            .show(); -//                } -//            } -//        } -          mSignatureLayout.setVisibility(View.GONE);          mSignatureLayout.setOnClickListener(new OnClickListener() {              public void onClick(View v) { @@ -301,27 +229,6 @@ public class DecryptActivity extends DrawerActivity {                  }              }          }); - -//        if (mReturnResult) { -//            mSourcePrevious.setClickable(false); -//            mSourcePrevious.setEnabled(false); -//            mSourcePrevious.setVisibility(View.INVISIBLE); -// -//            mSourceNext.setClickable(false); -//            mSourceNext.setEnabled(false); -//            mSourceNext.setVisibility(View.INVISIBLE); -// -//            mSourceLabel.setClickable(false); -//            mSourceLabel.setEnabled(false); -//        } -// -//        updateSource(); - -//        if (mDecryptImmediately -//                || (mSource.getCurrentView().getId() == R.id.sourceMessage && (mMessage.getText() -//                .length() > 0 || mContentUri != null))) { -//            decryptClicked(); -//        }      } @@ -381,20 +288,20 @@ public class DecryptActivity extends DrawerActivity {                  // replace non breakable spaces                  textData = textData.replaceAll("\\xa0", " "); -                mViewPager.setCurrentItem(PAGER_TAB_MESSAGE, false); -                mMessageFragment.setText(textData); +//                mViewPager.setCurrentItem(PAGER_TAB_MESSAGE, false); +//                mMessageFragment.setText(textData);  //                mMessage.setText(textData);              } else { -                matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(textData); +                matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(textData);                  if (matcher.matches()) { -                    Log.d(Constants.TAG, "PGP_SIGNED_MESSAGE matched"); +                    Log.d(Constants.TAG, "PGP_CLEARTEXT_SIGNATURE matched");                      textData = matcher.group(1);                      // replace non breakable spaces                      textData = textData.replaceAll("\\xa0", " ");  //                    mMessage.setText(textData); -                    mViewPager.setCurrentItem(PAGER_TAB_MESSAGE, false); -                    mMessageFragment = (DecryptMessageFragment) getFragmentByPosition(mViewPager.getCurrentItem()); -                    mMessageFragment.setText(textData); +//                    mViewPager.setCurrentItem(PAGER_TAB_MESSAGE, false); +//                    mMessageFragment = (DecryptMessageFragment) getFragmentByPosition(mViewPager.getCurrentItem()); +//                    mMessageFragment.setText(textData);                  } else {                      Log.d(Constants.TAG, "Nothing matched!");                  } @@ -426,34 +333,14 @@ public class DecryptActivity extends DrawerActivity {          }      } -    private void guessOutputFilename() { -        mInputFilename = mFilename.getText().toString(); -        File file = new File(mInputFilename); -        String filename = file.getName(); -        if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) { -            filename = filename.substring(0, filename.length() - 4); -        } -        mOutputFilename = Constants.Path.APP_DIR + "/" + filename; -    } - -//    private void updateSource() { -//        switch (mSource.getCurrentView().getId()) { -//            case R.id.sourceFile: { -//                mSourceLabel.setText(R.string.label_file); -//                mDecryptButton.setText(getString(R.string.btn_decrypt)); -//                break; -//            } -// -//            case R.id.sourceMessage: { -//                mSourceLabel.setText(R.string.label_message); -//                mDecryptButton.setText(getString(R.string.btn_decrypt)); -//                break; -//            } -// -//            default: { -//                break; -//            } +//    private void guessOutputFilename() { +//        mInputFilename = mFilename.getText().toString(); +//        File file = new File(mInputFilename); +//        String filename = file.getName(); +//        if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) { +//            filename = filename.substring(0, filename.length() - 4);  //        } +//        mOutputFilename = Constants.Path.APP_DIR + "/" + filename;  //    }      private void decryptClicked() { @@ -492,7 +379,7 @@ public class DecryptActivity extends DrawerActivity {          if (mDecryptTarget == Id.target.message) {  //            String messageData = mMessage.getText().toString(); -//            Matcher matcher = PgpHelper.PGP_SIGNED_MESSAGE.matcher(messageData); +//            Matcher matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(messageData);  //            if (matcher.matches()) {  //                mSignedOnly = true;  //                decryptStart(); @@ -512,7 +399,7 @@ public class DecryptActivity extends DrawerActivity {              if (mDecryptTarget == Id.target.file) {                  askForOutputFilename();              } else { // mDecryptTarget == Id.target.message -                decryptStart(); +//                decryptStart();              }          }      } @@ -531,7 +418,7 @@ public class DecryptActivity extends DrawerActivity {                      if (mDecryptTarget == Id.target.file) {                          askForOutputFilename();                      } else { -                        decryptStart(); +//                        decryptStart();                      }                  }              } @@ -623,7 +510,7 @@ public class DecryptActivity extends DrawerActivity {                  if (message.what == FileDialogFragment.MESSAGE_OKAY) {                      Bundle data = message.getData();                      mOutputFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); -                    decryptStart(); +//                    decryptStart();                  }              }          }; @@ -645,156 +532,156 @@ public class DecryptActivity extends DrawerActivity {          startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY);      } -    private void decryptStart() { -        Log.d(Constants.TAG, "decryptStart"); - -        // Send all information needed to service to decrypt in other thread -        Intent intent = new Intent(this, KeychainIntentService.class); - -        // fill values for this action -        Bundle data = new Bundle(); - -        intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY); - -        // choose action based on input: decrypt stream, file or bytes -        if (mContentUri != null) { -            data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_STREAM); - -            data.putParcelable(KeychainIntentService.ENCRYPT_PROVIDER_URI, mContentUri); -        } else if (mDecryptTarget == Id.target.file) { -            data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_URI); - -            Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename=" -                    + mOutputFilename); - -            data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename); -            data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename); -        } else { -            data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES); - -//            String message = mMessage.getText().toString(); -//            data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, message.getBytes()); -        } - -        data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyId); - -        data.putBoolean(KeychainIntentService.DECRYPT_RETURN_BYTES, mReturnBinary); -        data.putBoolean(KeychainIntentService.DECRYPT_ASSUME_SYMMETRIC, mAssumeSymmetricEncryption); - -        intent.putExtra(KeychainIntentService.EXTRA_DATA, data); - -        // Message is received after encrypting is done in KeychainIntentService -        KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, -                getString(R.string.progress_decrypting), ProgressDialog.STYLE_HORIZONTAL) { -            public void handleMessage(Message message) { -                // handle messages by standard KeychainIntentServiceHandler first -                super.handleMessage(message); - -                if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { -                    // get returned data bundle -                    Bundle returnData = message.getData(); - -                    mSignatureKeyId = 0; -                    mSignatureLayout.setVisibility(View.GONE); - -                    AppMsg.makeText(DecryptActivity.this, R.string.decryption_successful, -                            AppMsg.STYLE_INFO).show(); -//                    if (mReturnResult) { -//                        Intent intent = new Intent(); -//                        intent.putExtras(returnData); -//                        setResult(RESULT_OK, intent); -//                        finish(); -//                        return; +//    private void decryptStart() { +//        Log.d(Constants.TAG, "decryptStart"); +// +//        // Send all information needed to service to decrypt in other thread +//        Intent intent = new Intent(this, KeychainIntentService.class); +// +//        // fill values for this action +//        Bundle data = new Bundle(); +// +//        intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY); +// +//        // choose action based on input: decrypt stream, file or bytes +//        if (mContentUri != null) { +//            data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_STREAM); +// +//            data.putParcelable(KeychainIntentService.ENCRYPT_PROVIDER_URI, mContentUri); +//        } else if (mDecryptTarget == Id.target.file) { +//            data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_URI); +// +//            Log.d(Constants.TAG, "mInputFilename=" + mInputFilename + ", mOutputFilename=" +//                    + mOutputFilename); +// +//            data.putString(KeychainIntentService.ENCRYPT_INPUT_FILE, mInputFilename); +//            data.putString(KeychainIntentService.ENCRYPT_OUTPUT_FILE, mOutputFilename); +//        } else { +//            data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES); +// +////            String message = mMessage.getText().toString(); +////            data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, message.getBytes()); +//        } +// +//        data.putLong(KeychainIntentService.ENCRYPT_SECRET_KEY_ID, mSecretKeyId); +// +//        data.putBoolean(KeychainIntentService.DECRYPT_RETURN_BYTES, mReturnBinary); +//        data.putBoolean(KeychainIntentService.DECRYPT_ASSUME_SYMMETRIC, mAssumeSymmetricEncryption); +// +//        intent.putExtra(KeychainIntentService.EXTRA_DATA, data); +// +//        // Message is received after encrypting is done in KeychainIntentService +//        KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this, +//                getString(R.string.progress_decrypting), ProgressDialog.STYLE_HORIZONTAL) { +//            public void handleMessage(Message message) { +//                // handle messages by standard KeychainIntentServiceHandler first +//                super.handleMessage(message); +// +//                if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { +//                    // get returned data bundle +//                    Bundle returnData = message.getData(); +// +//                    mSignatureKeyId = 0; +//                    mSignatureLayout.setVisibility(View.GONE); +// +//                    AppMsg.makeText(DecryptActivity.this, R.string.decryption_successful, +//                            AppMsg.STYLE_INFO).show(); +////                    if (mReturnResult) { +////                        Intent intent = new Intent(); +////                        intent.putExtras(returnData); +////                        setResult(RESULT_OK, intent); +////                        finish(); +////                        return; +////                    } +// +//                    switch (mDecryptTarget) { +//                        case Id.target.message: +//                            String decryptedMessage = returnData +//                                    .getString(KeychainIntentService.RESULT_DECRYPTED_STRING); +////                            mMessage.setText(decryptedMessage); +////                            mMessage.setHorizontallyScrolling(false); +// +//                            break; +// +//                        case Id.target.file: +//                            if (mDeleteAfter.isChecked()) { +//                                // Create and show dialog to delete original file +//                                DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment +//                                        .newInstance(mInputFilename); +//                                deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); +//                            } +//                            break; +// +//                        default: +//                            // shouldn't happen +//                            break; +//  //                    } - -                    switch (mDecryptTarget) { -                        case Id.target.message: -                            String decryptedMessage = returnData -                                    .getString(KeychainIntentService.RESULT_DECRYPTED_STRING); -//                            mMessage.setText(decryptedMessage); -//                            mMessage.setHorizontallyScrolling(false); - -                            break; - -                        case Id.target.file: -                            if (mDeleteAfter.isChecked()) { -                                // Create and show dialog to delete original file -                                DeleteFileDialogFragment deleteFileDialog = DeleteFileDialogFragment -                                        .newInstance(mInputFilename); -                                deleteFileDialog.show(getSupportFragmentManager(), "deleteDialog"); -                            } -                            break; - -                        default: -                            // shouldn't happen -                            break; - -                    } - -                    PgpDecryptVerifyResult decryptVerifyResult = -                            returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); - -                    OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); - -                    if (signatureResult != null) { - -                        String userId = signatureResult.getUserId(); -                        mSignatureKeyId = signatureResult.getKeyId(); -                        mUserIdRest.setText("id: " -                                + PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId)); -                        if (userId == null) { -                            userId = getResources().getString(R.string.user_id_no_name); -                        } -                        String chunks[] = userId.split(" <", 2); -                        userId = chunks[0]; -                        if (chunks.length > 1) { -                            mUserIdRest.setText("<" + chunks[1]); -                        } -                        mUserId.setText(userId); - -                        switch (signatureResult.getStatus()) { -                            case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { -                                mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); -                                mLookupKey.setVisibility(View.GONE); -                                break; -                            } - -                            // TODO! -//                            case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { +// +//                    PgpDecryptVerifyResult decryptVerifyResult = +//                            returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); +// +//                    OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); +// +//                    if (signatureResult != null) { +// +//                        String userId = signatureResult.getUserId(); +//                        mSignatureKeyId = signatureResult.getKeyId(); +//                        mUserIdRest.setText("id: " +//                                + PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId)); +//                        if (userId == null) { +//                            userId = getResources().getString(R.string.user_id_no_name); +//                        } +//                        String chunks[] = userId.split(" <", 2); +//                        userId = chunks[0]; +//                        if (chunks.length > 1) { +//                            mUserIdRest.setText("<" + chunks[1]); +//                        } +//                        mUserId.setText(userId); +// +//                        switch (signatureResult.getStatus()) { +//                            case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { +//                                mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); +//                                mLookupKey.setVisibility(View.GONE);  //                                break;  //                            } - -                            case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: { -                                mSignatureStatusImage.setImageResource(R.drawable.overlay_error); -                                mLookupKey.setVisibility(View.VISIBLE); -                                AppMsg.makeText(DecryptActivity.this, -                                        R.string.unknown_signature, -                                        AppMsg.STYLE_ALERT).show(); -                                break; -                            } - -                            default: { -                                mSignatureStatusImage.setImageResource(R.drawable.overlay_error); -                                mLookupKey.setVisibility(View.GONE); -                                break; -                            } -                        } -                        mSignatureLayout.setVisibility(View.VISIBLE); -                    } -                } -            } -        }; - -        // Create a new Messenger for the communication back -        Messenger messenger = new Messenger(saveHandler); -        intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); - -        // show progress dialog -        saveHandler.showProgressDialog(this); - -        // start service with intent -        startService(intent); -    } +// +//                            // TODO! +////                            case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { +////                                break; +////                            } +// +//                            case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: { +//                                mSignatureStatusImage.setImageResource(R.drawable.overlay_error); +//                                mLookupKey.setVisibility(View.VISIBLE); +//                                AppMsg.makeText(DecryptActivity.this, +//                                        R.string.unknown_signature, +//                                        AppMsg.STYLE_ALERT).show(); +//                                break; +//                            } +// +//                            default: { +//                                mSignatureStatusImage.setImageResource(R.drawable.overlay_error); +//                                mLookupKey.setVisibility(View.GONE); +//                                break; +//                            } +//                        } +//                        mSignatureLayout.setVisibility(View.VISIBLE); +//                    } +//                } +//            } +//        }; +// +//        // Create a new Messenger for the communication back +//        Messenger messenger = new Messenger(saveHandler); +//        intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); +// +//        // show progress dialog +//        saveHandler.showProgressDialog(this); +// +//        // start service with intent +//        startService(intent); +//    }      @Override      protected void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -819,7 +706,7 @@ public class DecryptActivity extends DrawerActivity {                  Log.d(Constants.TAG, "Returning from Lookup Key...");                  if (resultCode == RESULT_OK) {                      // decrypt again -                    decryptStart(); +//                    decryptStart();                  }                  return;              } @@ -832,4 +719,55 @@ public class DecryptActivity extends DrawerActivity {          }      } +    @Override +    public void onSignatureResult(OpenPgpSignatureResult signatureResult) { + +        mSignatureKeyId = 0; +        mSignatureLayout.setVisibility(View.GONE); +        if (signatureResult != null) { + +            String userId = signatureResult.getUserId(); +            mSignatureKeyId = signatureResult.getKeyId(); +            mUserIdRest.setText("id: " +                    + PgpKeyHelper.convertKeyIdToHex(mSignatureKeyId)); +            if (userId == null) { +                userId = getResources().getString(R.string.user_id_no_name); +            } +            String chunks[] = userId.split(" <", 2); +            userId = chunks[0]; +            if (chunks.length > 1) { +                mUserIdRest.setText("<" + chunks[1]); +            } +            mUserId.setText(userId); + +            switch (signatureResult.getStatus()) { +                case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: { +                    mSignatureStatusImage.setImageResource(R.drawable.overlay_ok); +                    mLookupKey.setVisibility(View.GONE); +                    break; +                } + +                // TODO! +//                            case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: { +//                                break; +//                            } + +                case OpenPgpSignatureResult.SIGNATURE_UNKNOWN_PUB_KEY: { +                    mSignatureStatusImage.setImageResource(R.drawable.overlay_error); +                    mLookupKey.setVisibility(View.VISIBLE); +                    AppMsg.makeText(DecryptActivity.this, +                            R.string.unknown_signature, +                            AppMsg.STYLE_ALERT).show(); +                    break; +                } + +                default: { +                    mSignatureStatusImage.setImageResource(R.drawable.overlay_error); +                    mLookupKey.setVisibility(View.GONE); +                    break; +                } +            } +            mSignatureLayout.setVisibility(View.VISIBLE); +        } +    }  } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java index 0c8fd8c83..3d40eaf09 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFileFragment.java @@ -18,17 +18,39 @@  package org.sufficientlysecure.keychain.ui;  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.CheckBox;  import android.widget.EditText; +import com.beardedhen.androidbootstrap.BootstrapButton; +import com.devspark.appmsg.AppMsg; + +import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.helper.FileHelper; +import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment; + +import java.io.File;  public class DecryptFileFragment extends Fragment { -    private EditText mMessage; +    private EditText mFilename; +    private CheckBox mDeleteAfter; +    private BootstrapButton mBrowse; +    private BootstrapButton mDecryptButton; + + +    private String mInputFilename = null; +    private String mOutputFilename = null; + +    private static final int RESULT_CODE_FILE = 0x00007003; +      /**       * Creates new instance of this fragment @@ -49,14 +71,88 @@ public class DecryptFileFragment extends Fragment {      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {          View view = inflater.inflate(R.layout.decrypt_file_fragment, container, false); -        mMessage = (EditText) view.findViewById(R.id.message); +        mFilename = (EditText) findViewById(R.id.filename); +        mBrowse = (BootstrapButton) findViewById(R.id.btn_browse); +        mBrowse.setOnClickListener(new View.OnClickListener() { +            public void onClick(View v) { +                FileHelper.openFile(DecryptActivity.this, mFilename.getText().toString(), "*/*", +                        RESULT_CODE_FILE); +            } +        }); +        mDeleteAfter = (CheckBox) findViewById(R.id.deleteAfterDecryption); +        mDecryptButton = (BootstrapButton) view.findViewById(R.id.action_decrypt); +        mDecryptButton.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                decryptAction(); +            } +        });          return view;      } +    private void guessOutputFilename() { +        mInputFilename = mFilename.getText().toString(); +        File file = new File(mInputFilename); +        String filename = file.getName(); +        if (filename.endsWith(".asc") || filename.endsWith(".gpg") || filename.endsWith(".pgp")) { +            filename = filename.substring(0, filename.length() - 4); +        } +        mOutputFilename = Constants.Path.APP_DIR + "/" + filename; +    } +      @Override      public void onActivityCreated(Bundle savedInstanceState) {          super.onActivityCreated(savedInstanceState);      } +    private void decryptAction() { +        String currentFilename = mFilename.getText().toString(); +        if (mInputFilename == null || !mInputFilename.equals(currentFilename)) { +            guessOutputFilename(); +        } + +        if (mInputFilename.equals("")) { +            AppMsg.makeText(getActivity(), R.string.no_file_selected, AppMsg.STYLE_ALERT).show(); +            return; +        } + +        if (mInputFilename.startsWith("file")) { +            File file = new File(mInputFilename); +            if (!file.exists() || !file.isFile()) { +                AppMsg.makeText( +                        getActivity(), +                        getString(R.string.error_message, +                                getString(R.string.error_file_not_found)), AppMsg.STYLE_ALERT) +                        .show(); +                return; +            } +        } + +        askForOutputFilename(); +    } + +    private void askForOutputFilename() { +        // Message is received after passphrase is cached +        Handler returnHandler = new Handler() { +            @Override +            public void handleMessage(Message message) { +                if (message.what == FileDialogFragment.MESSAGE_OKAY) { +                    Bundle data = message.getData(); +                    mOutputFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME); +//                    decryptStart(); +                } +            } +        }; + +        // Create a new Messenger for the communication back +        Messenger messenger = new Messenger(returnHandler); + +        mFileDialog = FileDialogFragment.newInstance(messenger, +                getString(R.string.title_decrypt_to_file), +                getString(R.string.specify_file_to_decrypt_to), mOutputFilename, null); + +        mFileDialog.show(getSupportFragmentManager(), "fileDialog"); +    } +  } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java index 3fa7e89ba..c6724f6d1 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptMessageFragment.java @@ -17,7 +17,13 @@  package org.sufficientlysecure.keychain.ui; +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Intent;  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; @@ -26,27 +32,30 @@ import android.view.ViewGroup;  import android.widget.EditText;  import com.beardedhen.androidbootstrap.BootstrapButton; +import com.devspark.appmsg.AppMsg; +import org.openintents.openpgp.OpenPgpSignatureResult;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; +import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult; +import org.sufficientlysecure.keychain.pgp.PgpHelper; +import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException; +import org.sufficientlysecure.keychain.service.KeychainIntentService; +import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; +import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;  import org.sufficientlysecure.keychain.util.Log; +import java.util.regex.Matcher; +  public class DecryptMessageFragment extends Fragment { +    DecryptSignatureResultDisplay mSignatureResultDisplay;      private EditText mMessage; +    private BootstrapButton mDecryptButton; +    private BootstrapButton mDecryptFromCLipboardButton; -    /** -     * Creates new instance of this fragment -     */ -    public static DecryptMessageFragment newInstance() { -        DecryptMessageFragment frag = new DecryptMessageFragment(); - -        Bundle args = new Bundle(); -        frag.setArguments(args); - -        return frag; -    } +    public static final String EXTRA_CIPHERTEXT = "ciphertext";      /**       * Inflate the layout for this fragment @@ -56,23 +65,175 @@ public class DecryptMessageFragment extends Fragment {          View view = inflater.inflate(R.layout.decrypt_message_fragment, container, false);          mMessage = (EditText) view.findViewById(R.id.message); +        mDecryptButton = (BootstrapButton) view.findViewById(R.id.action_decrypt); +        mDecryptFromCLipboardButton = (BootstrapButton) view.findViewById(R.id.action_decrypt_from_clipboard); + +        String ciphertext = getArguments().getString(EXTRA_CIPHERTEXT); +        if (ciphertext != null) { +            mMessage.setText(ciphertext); +        } + +        mDecryptButton.setOnClickListener(new OnClickListener() { +            @Override +            public void onClick(View v) { +                decryptAction(); +            } +        }); + +        mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() { +            @Override +            public void onClick(View v) { +                decryptFromClipboard(); +            } +        });          return view;      }      @Override +    public void onAttach(Activity activity) { +        super.onAttach(activity); +        try { +            mSignatureResultDisplay = (DecryptSignatureResultDisplay) activity; +        } catch (ClassCastException e) { +            throw new ClassCastException(activity.toString() + " must implement DecryptSignatureResultDisplay"); +        } +    } + + +    @Override      public void onActivityCreated(Bundle savedInstanceState) {          super.onActivityCreated(savedInstanceState); -        Log.d(Constants.TAG, "tag: " + getTag()); +        Log.d(Constants.TAG, "onActivityCreated tag: " + getTag()); + +      } -    public String getText() { -        return mMessage.getText().toString(); +    private void decryptFromClipboard() { +        CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity()); + +        if (clipboardText != null) { +            Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText); +            if (!matcher.matches()) { +                matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText); +            } +            if (matcher.matches()) { +                String data = matcher.group(1); +                mMessage.setText(data); +                decryptStart(null); +            } else { +                AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_INFO) +                        .show(); +            } +        } else { +            AppMsg.makeText(getActivity(), R.string.error_invalid_data, AppMsg.STYLE_INFO) +                    .show(); +        }      } -    public void setText(String message) { -        mMessage.setText(message); +    private void decryptAction() { +        decryptStart(null);      } +    private void decryptStart(String passphrase) { +        Log.d(Constants.TAG, "decryptStart"); + +        // Send all information needed to service to decrypt in other thread +        Intent intent = new Intent(getActivity(), KeychainIntentService.class); + +        // fill values for this action +        Bundle data = new Bundle(); + +        intent.setAction(KeychainIntentService.ACTION_DECRYPT_VERIFY); + +        // data +        data.putInt(KeychainIntentService.TARGET, KeychainIntentService.TARGET_BYTES); +        String message = mMessage.getText().toString(); +        data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, message.getBytes()); +        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); + +        // TODO +        data.putBoolean(KeychainIntentService.DECRYPT_ASSUME_SYMMETRIC, false); + +        intent.putExtra(KeychainIntentService.EXTRA_DATA, data); + +        // Message is received after encrypting is done in KeychainIntentService +        KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(getActivity(), +                getString(R.string.progress_decrypting), ProgressDialog.STYLE_HORIZONTAL) { +            public void handleMessage(Message message) { +                // handle messages by standard KeychainIntentServiceHandler first +                super.handleMessage(message); + +                if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { +                    // get returned data bundle +                    Bundle returnData = message.getData(); + + +                    PgpDecryptVerifyResult decryptVerifyResult = +                            returnData.getParcelable(KeychainIntentService.RESULT_DECRYPT_VERIFY_RESULT); + +                    if (PgpDecryptVerifyResult.KEY_PASSHRASE_NEEDED == decryptVerifyResult.getStatus()) { +                        showPassphraseDialog(decryptVerifyResult.getKeyIdPassphraseNeeded()); +                    } else { + +                        AppMsg.makeText(getActivity(), R.string.decryption_successful, +                                AppMsg.STYLE_INFO).show(); + +                        byte[] decryptedMessage = returnData +                                .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); +                        mMessage.setText(new String(decryptedMessage)); +                        mMessage.setHorizontallyScrolling(false); + + +                        OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult(); + +                        // display signature result in activity +                        mSignatureResultDisplay.onSignatureResult(signatureResult); +                    } + +                } +            } +        }; + +        // 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); +    } + +    private void showPassphraseDialog(long keyId) { +        // Message is received after passphrase is cached +        Handler returnHandler = new Handler() { +            @Override +            public void handleMessage(Message message) { +                if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { +                    String passphrase = +                            message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); +                    decryptStart(passphrase); +                } +            } +        }; + +        // Create a new Messenger for the communication back +        Messenger messenger = new Messenger(returnHandler); + +        try { +            PassphraseDialogFragment passphraseDialog = PassphraseDialogFragment.newInstance(getActivity(), +                    messenger, keyId); + +            passphraseDialog.show(getActivity().getSupportFragmentManager(), "passphraseDialog"); +        } catch (PgpGeneralException e) { +            Log.d(Constants.TAG, "No passphrase for this secret key, encrypt directly!"); +            // send message to handler to start encryption directly +            returnHandler.sendEmptyMessage(PassphraseDialogFragment.MESSAGE_OKAY); +        } +    } + +  } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptSignatureResultDisplay.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptSignatureResultDisplay.java new file mode 100644 index 000000000..e167064ec --- /dev/null +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptSignatureResultDisplay.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +package org.sufficientlysecure.keychain.ui; + +import org.openintents.openpgp.OpenPgpSignatureResult; + +public interface DecryptSignatureResultDisplay { + +    public void onSignatureResult(OpenPgpSignatureResult result); + +} + diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java index 271219fa3..3c8b872b0 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java @@ -59,6 +59,8 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor      public static final int MESSAGE_OKAY = 1;      public static final int MESSAGE_CANCEL = 2; +    public static final String MESSAGE_DATA_PASSPHRASE = "passphrase"; +      private Messenger mMessenger;      private EditText mPassphraseEditText;      private boolean mCanKB; @@ -209,7 +211,11 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor                              passphrase);                  } -                sendMessageToHandler(MESSAGE_OKAY); +                // also return passphrase back to activity +                Bundle data = new Bundle(); +                data.putString(MESSAGE_DATA_PASSPHRASE, passphrase); + +                sendMessageToHandler(MESSAGE_OKAY, data);              }          }); @@ -278,4 +284,25 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor          }      } +    /** +     * Send message back to handler which is initialized in a activity +     * +     * @param what Message integer you want to send +     */ +    private void sendMessageToHandler(Integer what, Bundle data) { +        Message msg = Message.obtain(); +        msg.what = what; +        if (data != null) { +            msg.setData(data); +        } + +        try { +            mMessenger.send(msg); +        } catch (RemoteException e) { +            Log.w(Constants.TAG, "Exception sending message, Is handler present?", e); +        } catch (NullPointerException e) { +            Log.w(Constants.TAG, "Messenger is null!", e); +        } +    } +  } diff --git a/OpenPGP-Keychain/src/main/res/layout/decrypt_content.xml b/OpenPGP-Keychain/src/main/res/layout/decrypt_content.xml index f48d4401b..4ba379c2e 100644 --- a/OpenPGP-Keychain/src/main/res/layout/decrypt_content.xml +++ b/OpenPGP-Keychain/src/main/res/layout/decrypt_content.xml @@ -8,7 +8,7 @@      <android.support.v4.view.ViewPager          android:id="@+id/decrypt_pager"          android:layout_width="match_parent" -        android:layout_height="220dp"> +        android:layout_height="match_parent">          <android.support.v4.view.PagerTabStrip              android:id="@+id/decrypt_pager_tab_strip" @@ -38,128 +38,107 @@              <include layout="@layout/decrypt_signature_include" /> -            <LinearLayout -                android:layout_width="match_parent" -                android:layout_height="wrap_content" -                android:orientation="horizontal"> - -                <ImageView -                    android:id="@+id/sourcePrevious" -                    android:layout_width="wrap_content" -                    android:layout_height="wrap_content" -                    android:src="@drawable/ic_previous" /> - -                <TextView -                    android:id="@+id/sourceLabel" -                    style="@style/SectionHeader" -                    android:layout_width="0dip" -                    android:layout_height="match_parent" -                    android:layout_weight="1" -                    android:gravity="center_horizontal|center_vertical" -                    android:text="@string/label_message" -                    android:textAppearance="?android:attr/textAppearanceMedium" /> - -                <ImageView -                    android:id="@+id/sourceNext" -                    android:layout_width="wrap_content" -                    android:layout_height="wrap_content" -                    android:src="@drawable/ic_next" /> -            </LinearLayout> - -            <ViewFlipper -                android:id="@+id/source" -                android:layout_width="match_parent" -                android:layout_height="0dip" -                android:layout_weight="1"> - -                <LinearLayout -                    android:id="@+id/sourceMessage" -                    android:layout_width="match_parent" -                    android:layout_height="match_parent" -                    android:orientation="vertical" -                    android:padding="4dp"> - -                    <EditText -                        android:id="@+id/message" -                        android:layout_width="match_parent" -                        android:layout_height="match_parent" -                        android:gravity="top" -                        android:inputType="text|textCapSentences|textMultiLine|textLongMessage" -                        android:scrollHorizontally="true" /> -                </LinearLayout> - -                <LinearLayout -                    android:id="@+id/sourceFile" -                    android:layout_width="match_parent" -                    android:layout_height="match_parent" -                    android:orientation="vertical" -                    android:padding="4dp"> - -                    <LinearLayout -                        android:layout_width="match_parent" -                        android:layout_height="wrap_content" -                        android:orientation="horizontal"> - -                        <EditText -                            android:id="@+id/filename" -                            android:layout_width="0dip" -                            android:layout_height="wrap_content" -                            android:layout_weight="1" -                            android:gravity="top|left" -                            android:inputType="textMultiLine|textUri" -                            android:lines="4" -                            android:maxLines="10" -                            android:minLines="2" -                            android:scrollbars="vertical" /> - -                        <com.beardedhen.androidbootstrap.BootstrapButton -                            android:id="@+id/btn_browse" -                            android:layout_width="wrap_content" -                            android:layout_height="wrap_content" -                            android:layout_margin="4dp" -                            bootstrapbutton:bb_icon_left="fa-folder-open" -                            bootstrapbutton:bb_roundedCorners="true" -                            bootstrapbutton:bb_size="default" -                            bootstrapbutton:bb_type="default" /> -                    </LinearLayout> - -                    <LinearLayout -                        android:layout_width="match_parent" -                        android:layout_height="wrap_content" -                        android:orientation="horizontal"> - -                        <CheckBox -                            android:id="@+id/deleteAfterDecryption" -                            android:layout_width="wrap_content" -                            android:layout_height="wrap_content" -                            android:layout_gravity="center_vertical" -                            android:text="@string/label_delete_after_decryption" /> -                    </LinearLayout> -                </LinearLayout> -            </ViewFlipper> - -            <TextView -                style="@style/SectionHeader" -                android:layout_width="wrap_content" -                android:layout_height="wrap_content" -                android:layout_marginBottom="4dp" -                android:text="@string/section_decrypt_verify" /> - -            <LinearLayout -                android:layout_width="match_parent" -                android:layout_height="wrap_content" -                android:orientation="horizontal" -                android:padding="4dp"> - -                <com.beardedhen.androidbootstrap.BootstrapButton -                    android:id="@+id/action_decrypt" -                    android:layout_width="match_parent" -                    android:layout_height="60dp" -                    android:padding="4dp" -                    android:text="@string/btn_decrypt_verify" -                    bootstrapbutton:bb_icon_left="fa-unlock" -                    bootstrapbutton:bb_type="info" /> -            </LinearLayout> +            <!--<LinearLayout--> +                <!--android:layout_width="match_parent"--> +                <!--android:layout_height="wrap_content"--> +                <!--android:orientation="horizontal">--> + +                <!--<ImageView--> +                    <!--android:id="@+id/sourcePrevious"--> +                    <!--android:layout_width="wrap_content"--> +                    <!--android:layout_height="wrap_content"--> +                    <!--android:src="@drawable/ic_previous" />--> + +                <!--<TextView--> +                    <!--android:id="@+id/sourceLabel"--> +                    <!--style="@style/SectionHeader"--> +                    <!--android:layout_width="0dip"--> +                    <!--android:layout_height="match_parent"--> +                    <!--android:layout_weight="1"--> +                    <!--android:gravity="center_horizontal|center_vertical"--> +                    <!--android:text="@string/label_message"--> +                    <!--android:textAppearance="?android:attr/textAppearanceMedium" />--> + +                <!--<ImageView--> +                    <!--android:id="@+id/sourceNext"--> +                    <!--android:layout_width="wrap_content"--> +                    <!--android:layout_height="wrap_content"--> +                    <!--android:src="@drawable/ic_next" />--> +            <!--</LinearLayout>--> + +            <!--<ViewFlipper--> +                <!--android:id="@+id/source"--> +                <!--android:layout_width="match_parent"--> +                <!--android:layout_height="0dip"--> +                <!--android:layout_weight="1">--> + +                <!--<LinearLayout--> +                    <!--android:id="@+id/sourceMessage"--> +                    <!--android:layout_width="match_parent"--> +                    <!--android:layout_height="match_parent"--> +                    <!--android:orientation="vertical"--> +                    <!--android:padding="4dp">--> + +                    <!--<EditText--> +                        <!--android:id="@+id/message"--> +                        <!--android:layout_width="match_parent"--> +                        <!--android:layout_height="match_parent"--> +                        <!--android:gravity="top"--> +                        <!--android:inputType="text|textCapSentences|textMultiLine|textLongMessage"--> +                        <!--android:scrollHorizontally="true" />--> +                <!--</LinearLayout>--> + +                <!--<LinearLayout--> +                    <!--android:id="@+id/sourceFile"--> +                    <!--android:layout_width="match_parent"--> +                    <!--android:layout_height="match_parent"--> +                    <!--android:orientation="vertical"--> +                    <!--android:padding="4dp">--> + +                    <!--<LinearLayout--> +                        <!--android:layout_width="match_parent"--> +                        <!--android:layout_height="wrap_content"--> +                        <!--android:orientation="horizontal">--> + +                        <!--<EditText--> +                            <!--android:id="@+id/filename"--> +                            <!--android:layout_width="0dip"--> +                            <!--android:layout_height="wrap_content"--> +                            <!--android:layout_weight="1"--> +                            <!--android:gravity="top|left"--> +                            <!--android:inputType="textMultiLine|textUri"--> +                            <!--android:lines="4"--> +                            <!--android:maxLines="10"--> +                            <!--android:minLines="2"--> +                            <!--android:scrollbars="vertical" />--> + +                        <!--<com.beardedhen.androidbootstrap.BootstrapButton--> +                            <!--android:id="@+id/btn_browse"--> +                            <!--android:layout_width="wrap_content"--> +                            <!--android:layout_height="wrap_content"--> +                            <!--android:layout_margin="4dp"--> +                            <!--bootstrapbutton:bb_icon_left="fa-folder-open"--> +                            <!--bootstrapbutton:bb_roundedCorners="true"--> +                            <!--bootstrapbutton:bb_size="default"--> +                            <!--bootstrapbutton:bb_type="default" />--> +                    <!--</LinearLayout>--> + +                    <!--<LinearLayout--> +                        <!--android:layout_width="match_parent"--> +                        <!--android:layout_height="wrap_content"--> +                        <!--android:orientation="horizontal">--> + +                        <!--<CheckBox--> +                            <!--android:id="@+id/deleteAfterDecryption"--> +                            <!--android:layout_width="wrap_content"--> +                            <!--android:layout_height="wrap_content"--> +                            <!--android:layout_gravity="center_vertical"--> +                            <!--android:text="@string/label_delete_after_decryption" />--> +                    <!--</LinearLayout>--> +                <!--</LinearLayout>--> +            <!--</ViewFlipper>--> + +          </LinearLayout>      </ScrollView>  </LinearLayout>
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml index f221ff8de..7347d222c 100644 --- a/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml +++ b/OpenPGP-Keychain/src/main/res/layout/decrypt_file_fragment.xml @@ -1,14 +1,19 @@  <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"      android:layout_width="match_parent"      android:layout_height="wrap_content" +    android:paddingTop="4dp" +    android:paddingLeft="10dp" +    android:paddingRight="10dp"      android:orientation="vertical">      <LinearLayout          android:layout_width="match_parent"          android:layout_height="wrap_content" -        android:orientation="horizontal"> +        android:orientation="horizontal" +        android:layout_alignParentTop="true" +        android:id="@+id/linearLayout">          <EditText              android:id="@+id/filename" @@ -38,11 +43,44 @@          android:layout_height="wrap_content"          android:orientation="horizontal"> -        <CheckBox -            android:id="@+id/deleteAfterDecryption" -            android:layout_width="wrap_content" -            android:layout_height="wrap_content" -            android:layout_gravity="center_vertical" -            android:text="@string/label_delete_after_decryption" />      </LinearLayout> -</LinearLayout>
\ No newline at end of file + +    <TextView +        style="@style/SectionHeader" +        android:layout_width="wrap_content" +        android:layout_height="wrap_content" +        android:text="@string/section_decrypt_verify" +        android:layout_above="@+id/action_decrypt" +        android:layout_alignParentLeft="true" +        android:layout_alignParentStart="true" /> + +    <LinearLayout +        android:layout_width="match_parent" +        android:layout_height="wrap_content" +        android:orientation="horizontal" +        android:padding="4dp"> + +    </LinearLayout> + +    <com.beardedhen.androidbootstrap.BootstrapButton +        android:id="@+id/action_decrypt" +        android:layout_width="match_parent" +        android:layout_height="60dp" +        android:padding="4dp" +        android:text="@string/btn_decrypt_verify" +        bootstrapbutton:bb_icon_left="fa-unlock" +        bootstrapbutton:bb_type="info" +        android:layout_alignParentBottom="true" +        android:layout_alignParentLeft="true" +        android:layout_alignParentStart="true" /> + +    <CheckBox +        android:id="@+id/deleteAfterDecryption" +        android:layout_width="wrap_content" +        android:layout_height="wrap_content" +        android:layout_gravity="center_vertical" +        android:text="@string/label_delete_after_decryption" +        android:layout_below="@+id/linearLayout" +        android:layout_alignParentLeft="true" +        android:layout_alignParentStart="true" /> +</RelativeLayout>
\ No newline at end of file diff --git a/OpenPGP-Keychain/src/main/res/layout/decrypt_message_fragment.xml b/OpenPGP-Keychain/src/main/res/layout/decrypt_message_fragment.xml index 3deee0eca..f11f79c1e 100644 --- a/OpenPGP-Keychain/src/main/res/layout/decrypt_message_fragment.xml +++ b/OpenPGP-Keychain/src/main/res/layout/decrypt_message_fragment.xml @@ -1,15 +1,64 @@  <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"      xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"      android:layout_width="match_parent" -    android:layout_height="wrap_content" -    android:orientation="vertical"> +    android:layout_height="match_parent" +    android:fillViewport="true"> -    <EditText -        android:id="@+id/message" +    <RelativeLayout          android:layout_width="match_parent"          android:layout_height="match_parent" -        android:gravity="top" -        android:inputType="text|textCapSentences|textMultiLine|textLongMessage" -        android:scrollHorizontally="true" /> -</LinearLayout> +        android:paddingTop="4dp" +        android:paddingLeft="10dp" +        android:paddingRight="10dp" +        android:orientation="vertical"> + +        <EditText +            android:id="@+id/message" +            android:layout_width="match_parent" +            android:layout_height="match_parent" +            android:gravity="top" +            android:inputType="text|textCapSentences|textMultiLine|textLongMessage" +            android:scrollHorizontally="true" +            android:layout_above="@+id/decrypt_message_section" +            android:layout_alignParentStart="true" /> + +        <TextView +            style="@style/SectionHeader" +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="@string/section_decrypt_verify" +            android:layout_above="@+id/decrypt_buttons" +            android:layout_alignParentEnd="true" +            android:id="@+id/decrypt_message_section" /> + +        <LinearLayout +            android:id="@+id/decrypt_buttons" +            android:layout_width="match_parent" +            android:layout_height="wrap_content" +            android:orientation="horizontal" +            android:padding="4dp" +            android:layout_alignParentBottom="true"> + +            <com.beardedhen.androidbootstrap.BootstrapButton +                android:id="@+id/action_decrypt" +                android:layout_width="match_parent" +                android:layout_height="60dp" +                android:layout_weight="1" +                android:padding="4dp" +                android:text="@string/btn_decrypt_verify" +                bootstrapbutton:bb_icon_left="fa-unlock" +                bootstrapbutton:bb_type="info" /> + +            <com.beardedhen.androidbootstrap.BootstrapButton +                android:id="@+id/action_decrypt_from_clipboard" +                android:layout_width="match_parent" +                android:layout_height="60dp" +                android:layout_weight="1" +                android:padding="4dp" +                android:text="@string/btn_decrypt_verify_clipboard" +                bootstrapbutton:bb_icon_left="fa-unlock" +                bootstrapbutton:bb_type="info" /> +        </LinearLayout> +    </RelativeLayout> +</ScrollView> diff --git a/OpenPGP-Keychain/src/main/res/values/strings.xml b/OpenPGP-Keychain/src/main/res/values/strings.xml index 2e88062b7..5d325d5ec 100644 --- a/OpenPGP-Keychain/src/main/res/values/strings.xml +++ b/OpenPGP-Keychain/src/main/res/values/strings.xml @@ -51,6 +51,7 @@      <string name="btn_certify">Certify</string>      <string name="btn_decrypt">Decrypt</string>      <string name="btn_decrypt_verify">Decrypt and Verify</string> +    <string name="btn_decrypt_verify_clipboard">From Clipboard</string>      <string name="btn_select_encrypt_keys">Select Recipients</string>      <string name="btn_encrypt_file">Encrypt File</string>      <string name="btn_save">Save</string> | 
