diff options
Diffstat (limited to 'OpenKeychain/src/main/java/org')
14 files changed, 264 insertions, 180 deletions
| diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java index 26063fc66..b43dec2f1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/AccountSettingsActivity.java @@ -107,9 +107,8 @@ public class AccountSettingsActivity extends ActionBarActivity {      private void save() {          new ProviderHelper(this).updateApiAccount(mAccountUri, mAccountSettingsFragment.getAccSettings()); -        // TODO: show "account saved" instead of "operation succeeded"          SingletonResult result = new SingletonResult( -                SingletonResult.RESULT_OK, LogLevel.OK, LogType.MSG_ACC_SAVED); +                SingletonResult.RESULT_OK, LogType.MSG_ACC_SAVED);          Intent intent = new Intent();          intent.putExtra(SingletonResult.EXTRA_RESULT, result);          setResult(RESULT_OK, intent); 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 dc0d59e86..971df8ea2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -140,15 +140,16 @@ public class KeychainIntentService extends IntentService implements Progressable      public static final String ENCRYPT_ENCRYPTION_KEYS_IDS = "encryption_keys_ids";      public static final String ENCRYPT_COMPRESSION_ID = "compression_id";      public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes"; -    public static final String ENCRYPT_INPUT_URI = "input_uri"; +    public static final String ENCRYPT_DECRYPT_INPUT_URI = "input_uri";      public static final String ENCRYPT_INPUT_URIS = "input_uris"; -    public static final String ENCRYPT_OUTPUT_URI = "output_uri"; +    public static final String ENCRYPT_DECRYPT_OUTPUT_URI = "output_uri";      public static final String ENCRYPT_OUTPUT_URIS = "output_uris";      public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase";      // decrypt/verify      public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes";      public static final String DECRYPT_PASSPHRASE = "passphrase"; +    public static final String DECRYPT_NFC_DECRYPTED_SESSION_KEY = "nfc_decrypted_session_key";      // save keyring      public static final String EDIT_KEYRING_PARCEL = "save_parcel"; @@ -337,6 +338,7 @@ public class KeychainIntentService extends IntentService implements Progressable              try {                  /* Input */                  String passphrase = data.getString(DECRYPT_PASSPHRASE); +                byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);                  InputData inputData = createDecryptInputData(data);                  OutputStream outStream = createCryptOutputStream(data); @@ -353,7 +355,8 @@ public class KeychainIntentService extends IntentService implements Progressable                  );                  builder.setProgressable(this)                          .setAllowSymmetricDecryption(true) -                        .setPassphrase(passphrase); +                        .setPassphrase(passphrase) +                        .setNfcState(nfcDecryptedSessionKey);                  DecryptVerifyResult decryptVerifyResult = builder.build().execute(); @@ -375,6 +378,7 @@ public class KeychainIntentService extends IntentService implements Progressable              try {                  /* Input */                  String passphrase = data.getString(DECRYPT_PASSPHRASE); +                byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);                  InputData inputData = createDecryptInputData(data); @@ -391,7 +395,8 @@ public class KeychainIntentService extends IntentService implements Progressable                  builder.setProgressable(this)                          .setAllowSymmetricDecryption(true)                          .setPassphrase(passphrase) -                        .setDecryptMetadataOnly(true); +                        .setDecryptMetadataOnly(true) +                        .setNfcState(nfcDecryptedSessionKey);                  DecryptVerifyResult decryptVerifyResult = builder.build().execute(); @@ -860,7 +865,7 @@ public class KeychainIntentService extends IntentService implements Progressable                  return new InputData(new ByteArrayInputStream(bytes), bytes.length);              case IO_URI: /* encrypting content uri */ -                Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); +                Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_INPUT_URI);                  // InputStream                  return new InputData(getContentResolver().openInputStream(providerUri), FileHelper.getFileSize(this, providerUri, 0)); @@ -912,7 +917,7 @@ public class KeychainIntentService extends IntentService implements Progressable                  return "";              case IO_URI: -                Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); +                Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_INPUT_URI);                  return FileHelper.getFilename(this, providerUri); @@ -933,7 +938,7 @@ public class KeychainIntentService extends IntentService implements Progressable                  return new ByteArrayOutputStream();              case IO_URI: -                Uri providerUri = data.getParcelable(ENCRYPT_OUTPUT_URI); +                Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_OUTPUT_URI);                  return getContentResolver().openOutputStream(providerUri); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResult.java index beaa6f2ba..b0a255162 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/OperationResult.java @@ -519,7 +519,9 @@ public abstract class OperationResult implements Parcelable {          MSG_CRT_UPLOAD_SUCCESS (LogLevel.OK, R.string.msg_crt_upload_success),          MSG_CRT_SUCCESS (LogLevel.OK, R.string.msg_crt_success), -        MSG_ACC_SAVED (LogLevel.INFO, R.string.api_settings_save) +        MSG_ACC_SAVED (LogLevel.INFO, R.string.api_settings_save_msg), + +        MSG_NO_VALID_ENC (LogLevel.ERROR, R.string.error_invalid_data)          ; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/SingletonResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/SingletonResult.java index 642e81246..430c739d9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/SingletonResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/results/SingletonResult.java @@ -34,7 +34,7 @@ public class SingletonResult extends OperationResult {          super(source);      } -    public SingletonResult(int result, LogLevel level, LogType reason) { +    public SingletonResult(int result, LogType reason) {          super(result, new OperationLog());          // Prepare the log          mLog.add(reason, 0); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java index 438b56eb0..5eec8454a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java @@ -330,7 +330,7 @@ public class CertifyKeyFragment extends LoaderFragment                  if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {                      SingletonResult result = new SingletonResult( -                            SingletonResult.RESULT_OK, LogLevel.OK, LogType.MSG_CRT_SUCCESS); +                            SingletonResult.RESULT_OK, LogType.MSG_CRT_SUCCESS);                      Intent intent = new Intent();                      intent.putExtra(SingletonResult.EXTRA_RESULT, result);                      mActivity.setResult(CertifyKeyActivity.RESULT_OK, intent); @@ -384,7 +384,7 @@ public class CertifyKeyFragment extends LoaderFragment                  if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {                      SingletonResult result = new SingletonResult(SingletonResult.RESULT_OK, -                            LogLevel.OK, LogType.MSG_CRT_UPLOAD_SUCCESS); +                            LogType.MSG_CRT_UPLOAD_SUCCESS);                      Intent intent = new Intent();                      intent.putExtra(SingletonResult.EXTRA_RESULT, result);                      mActivity.setResult(CertifyKeyActivity.RESULT_OK, intent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java index 37382051b..2f3978dad 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptActivity.java @@ -22,6 +22,7 @@ import android.os.Bundle;  import android.view.View;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.service.results.OperationResult;  public class DecryptActivity extends DrawerActivity { @@ -50,8 +51,19 @@ public class DecryptActivity extends DrawerActivity {              public void onClick(View v) {                  Intent clipboardDecrypt = new Intent(DecryptActivity.this, DecryptTextActivity.class);                  clipboardDecrypt.setAction(DecryptTextActivity.ACTION_DECRYPT_FROM_CLIPBOARD); -                startActivity(clipboardDecrypt); +                startActivityForResult(clipboardDecrypt, 0);              }          });      } + +    @Override +    protected void onActivityResult(int requestCode, int resultCode, Intent data) { +        // if a result has been returned, display a notify +        if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) { +            OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT); +            result.createNotify(this).show(); +        } else { +            super.onActivityResult(requestCode, resultCode, data); +        } +    }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index deb994808..0ace8e82a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -23,7 +23,6 @@ import android.content.Intent;  import android.net.Uri;  import android.os.Build;  import android.os.Bundle; -import android.os.Handler;  import android.os.Message;  import android.os.Messenger;  import android.text.TextUtils; @@ -33,6 +32,7 @@ import android.view.ViewGroup;  import android.widget.CheckBox;  import android.widget.TextView; +import org.openintents.openpgp.util.OpenPgpApi;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.util.FileHelper; @@ -40,7 +40,6 @@ import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;  import org.sufficientlysecure.keychain.service.KeychainIntentService;  import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;  import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;  import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.ui.util.Notify; @@ -48,7 +47,6 @@ import java.io.File;  public class DecryptFilesFragment extends DecryptFragment {      public static final String ARG_URI = "uri"; -    //    public static final String ARG_FROM_VIEW_INTENT = "view_intent";      public static final String ARG_OPEN_DIRECTLY = "open_directly";      private static final int REQUEST_CODE_INPUT = 0x00007003; @@ -71,7 +69,6 @@ public class DecryptFilesFragment extends DecryptFragment {          Bundle args = new Bundle();          args.putParcelable(ARG_URI, uri); -//        args.putBoolean(ARG_FROM_VIEW_INTENT, fromViewIntent);          args.putBoolean(ARG_OPEN_DIRECTLY, openDirectly);          frag.setArguments(args); @@ -143,7 +140,7 @@ public class DecryptFilesFragment extends DecryptFragment {          }  //        askForOutputFilename(); -        decryptOriginalFilename(null); +        decryptOriginalFilename();      }      private String removeEncryptedAppend(String name) { @@ -171,7 +168,7 @@ public class DecryptFilesFragment extends DecryptFragment {          }      } -    private void decryptOriginalFilename(String passphrase) { +    private void decryptOriginalFilename() {          Log.d(Constants.TAG, "decryptOriginalFilename");          Intent intent = new Intent(getActivity(), KeychainIntentService.class); @@ -184,12 +181,13 @@ public class DecryptFilesFragment extends DecryptFragment {          Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);          data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); -        data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); +        data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_INPUT_URI, mInputUri);          data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); -        data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); +        data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri); -        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); +        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); +        data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);          intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -210,13 +208,13 @@ public class DecryptFilesFragment extends DecryptFragment {                      if (pgpResult.isPending()) {                          if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==                                  DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { -                            showPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); +                            startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());                          } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==                                  DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { -                            showPassphraseDialog(Constants.key.symmetric); +                            startPassphraseDialog(Constants.key.symmetric);                          } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==                                  DecryptVerifyResult.RESULT_PENDING_NFC) { -                            // TODO +                            startNfcDecrypt(pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());                          } else {                              throw new RuntimeException("Unhandled pending result!");                          } @@ -241,23 +239,8 @@ public class DecryptFilesFragment extends DecryptFragment {          getActivity().startService(intent);      } -    protected void showPassphraseDialogForFilename(long keyId) { -        PassphraseDialogFragment.show(getActivity(), keyId, -                new Handler() { -                    @Override -                    public void handleMessage(Message message) { -                        if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) { -                            String passphrase = -                                    message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE); -                            decryptOriginalFilename(passphrase); -                        } -                    } -                } -        ); -    } -      @Override -    protected void decryptStart(String passphrase) { +    protected void decryptStart() {          Log.d(Constants.TAG, "decryptStart");          // Send all information needed to service to decrypt in other thread @@ -272,12 +255,13 @@ public class DecryptFilesFragment extends DecryptFragment {          Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);          data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); -        data.putParcelable(KeychainIntentService.ENCRYPT_INPUT_URI, mInputUri); +        data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_INPUT_URI, mInputUri);          data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_URI); -        data.putParcelable(KeychainIntentService.ENCRYPT_OUTPUT_URI, mOutputUri); +        data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri); -        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); +        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); +        data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);          intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -298,13 +282,13 @@ public class DecryptFilesFragment extends DecryptFragment {                      if (pgpResult.isPending()) {                          if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==                                  DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { -                            showPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); +                            startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());                          } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==                                  DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { -                            showPassphraseDialog(Constants.key.symmetric); +                            startPassphraseDialog(Constants.key.symmetric);                          } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==                                  DecryptVerifyResult.RESULT_PENDING_NFC) { -                            // TODO +                            startNfcDecrypt(pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());                          } else {                              throw new RuntimeException("Unhandled pending result!");                          } @@ -350,25 +334,40 @@ public class DecryptFilesFragment extends DecryptFragment {      @Override      public void onActivityResult(int requestCode, int resultCode, Intent data) {          switch (requestCode) { +            case REQUEST_CODE_PASSPHRASE: { +                if (resultCode == Activity.RESULT_OK && data != null) { +                    mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); +                    decryptOriginalFilename(); +                } +                return; +            } + +            case REQUEST_CODE_NFC_DECRYPT: { +                if (resultCode == Activity.RESULT_OK && data != null) { +                    mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); +                    decryptOriginalFilename(); +                } +                return; +            } +              case REQUEST_CODE_INPUT: {                  if (resultCode == Activity.RESULT_OK && data != null) {                      setInputUri(data.getData());                  }                  return;              } +              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(); -                    decryptStart(null); +                    decryptStart();                  }                  return;              }              default: {                  super.onActivityResult(requestCode, resultCode, data); - -                break;              }          }      } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 7298ff6d7..c9cfb9e0c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -17,11 +17,8 @@  package org.sufficientlysecure.keychain.ui; -import android.app.Activity;  import android.content.Intent;  import android.os.Bundle; -import android.os.Handler; -import android.os.Message;  import android.support.v4.app.Fragment;  import android.view.View;  import android.view.View.OnClickListener; @@ -33,14 +30,17 @@ import android.widget.TextView;  import org.openintents.openpgp.OpenPgpSignatureResult;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.nfc.NfcActivity;  import org.sufficientlysecure.keychain.pgp.KeyRing;  import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;  import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;  public abstract class DecryptFragment extends Fragment {      private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006; +    public static final int REQUEST_CODE_PASSPHRASE = 0x00008001; +    public static final int REQUEST_CODE_NFC_DECRYPT = 0x00008002; +      protected long mSignatureKeyId = 0;      protected LinearLayout mResultLayout; @@ -53,6 +53,9 @@ public abstract class DecryptFragment extends Fragment {      protected Button mLookupKey; +    // State +    protected String mPassphrase; +    protected byte[] mNfcDecryptedSessionKey;      @Override      public void onActivityCreated(Bundle savedInstanceState) { @@ -81,23 +84,23 @@ public abstract class DecryptFragment extends Fragment {          startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY);      } -    @Override -    public void onActivityResult(int requestCode, int resultCode, Intent data) { -        switch (requestCode) { +    protected void startPassphraseDialog(long subkeyId) { +        Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class); +        intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId); +        startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); +    } -            case RESULT_CODE_LOOKUP_KEY: { -                if (resultCode == Activity.RESULT_OK) { -                    // TODO: generate new OpenPgpSignatureResult and display it -                } -                return; -            } +    protected void startNfcDecrypt(String pin, byte[] encryptedSessionKey) { +        // build PendingIntent for Yubikey NFC operations +        Intent intent = new Intent(getActivity(), NfcActivity.class); +        intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY); +        intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService +        intent.putExtra(NfcActivity.EXTRA_PIN, pin); -            default: { -                super.onActivityResult(requestCode, resultCode, data); +        intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey); +        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); -                break; -            } -        } +        startActivityForResult(intent, REQUEST_CODE_NFC_DECRYPT);      }      protected void onResult(DecryptVerifyResult decryptVerifyResult) { @@ -197,26 +200,9 @@ public abstract class DecryptFragment extends Fragment {          }      } -    protected void showPassphraseDialog(long keyId) { -        PassphraseDialogFragment.show(getActivity(), keyId, -                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); -                        } -                    } -                } -        ); -    } -      /**       * Should be overridden by MessageFragment and FileFragment to start actual decryption -     * -     * @param passphrase       */ -    protected abstract void decryptStart(String passphrase); +    protected abstract void decryptStart();  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java index 1bbe58f07..582c988df 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextActivity.java @@ -27,6 +27,8 @@ import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.api.OpenKeychainIntents;  import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;  import org.sufficientlysecure.keychain.pgp.PgpHelper; +import org.sufficientlysecure.keychain.service.results.OperationResult; +import org.sufficientlysecure.keychain.service.results.SingletonResult;  import org.sufficientlysecure.keychain.util.Log;  import org.sufficientlysecure.keychain.ui.util.Notify; @@ -54,6 +56,48 @@ public class DecryptTextActivity extends ActionBarActivity {      }      /** +     * Fix the message a bit, trailing spaces and newlines break stuff, +     * because GMail sends as HTML and such things break ASCII Armor +     * TODO: things like "<" and ">" also make problems +     * <p/> +     * NOTE: Do not use on cleartext signatures, only on ASCII-armored ciphertext, +     * it would change the signed message +     */ +    private String fixAsciiArmoredCiphertext(String message) { +        message = message.replaceAll(" +\n", "\n"); +        message = message.replaceAll("\n\n+", "\n\n"); +        message = message.replaceFirst("^\n+", ""); +        // make sure there'll be exactly one newline at the end +        message = message.replaceFirst("\n*$", "\n"); +        // replace non breakable spaces +        message = message.replaceAll("\\xa0", " "); + +        return message; +    } + +    private String getPgpContent(String input) { +        // only decrypt if clipboard content is available and a pgp message or cleartext signature +        if (input != null) { +            Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(input); +            if (matcher.matches()) { +                String message = matcher.group(1); +                message = fixAsciiArmoredCiphertext(message); +                return message; +            } else { +                matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(input); +                if (matcher.matches()) { +                    // return cleartext signature +                    return matcher.group(1); +                } else { +                    return null; +                } +            } +        } else { +            return null; +        } +    } + +    /**       * Handles all actions with this intent       *       * @param intent @@ -67,73 +111,58 @@ public class DecryptTextActivity extends ActionBarActivity {              extras = new Bundle();          } -        String textData = null; - -        /* -         * Android's Action -         */          if (Intent.ACTION_SEND.equals(action) && type != null) { +            // Android action +              // When sending to Keychain Decrypt via share menu              if ("text/plain".equals(type)) { -                // Plain text                  String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); +                sharedText = getPgpContent(sharedText); +                  if (sharedText != null) { -                    // handle like normal text decryption, override action and extras to later -                    // executeServiceMethod ACTION_DECRYPT_TEXT in main actions -                    textData = sharedText; +                    loadFragment(savedInstanceState, sharedText); +                } else { +                    Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR);                  } +            } else { +                Log.e(Constants.TAG, "ACTION_SEND received non-plaintext, this should not happen in this activity!");              } -        } +        } else if (ACTION_DECRYPT_TEXT.equals(action)) { +            Log.d(Constants.TAG, "ACTION_DECRYPT_TEXT textData not null, matching text..."); -        /** -         * Main Actions -         */ -        textData = extras.getString(EXTRA_TEXT); -        if (ACTION_DECRYPT_TEXT.equals(action) && textData != null) { -            Log.d(Constants.TAG, "textData not null, matching text ..."); -            Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(textData); -            if (matcher.matches()) { -                Log.d(Constants.TAG, "PGP_MESSAGE matched"); -                textData = matcher.group(1); -                // replace non breakable spaces -                textData = textData.replaceAll("\\xa0", " "); +            String extraText = extras.getString(EXTRA_TEXT); +            extraText = getPgpContent(extraText); + +            if (extraText != null) { +                loadFragment(savedInstanceState, extraText);              } else { -                matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(textData); -                if (matcher.matches()) { -                    Log.d(Constants.TAG, "PGP_CLEARTEXT_SIGNATURE matched"); -                    textData = matcher.group(1); -                    // replace non breakable spaces -                    textData = textData.replaceAll("\\xa0", " "); -                } else { -                    Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR); -                    Log.d(Constants.TAG, "Nothing matched!"); -                } +                Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR);              }          } else if (ACTION_DECRYPT_FROM_CLIPBOARD.equals(action)) { -            CharSequence clipboardText = ClipboardReflection.getClipboardText(this); +            Log.d(Constants.TAG, "ACTION_DECRYPT_FROM_CLIPBOARD"); + +            String clipboardText = ClipboardReflection.getClipboardText(this).toString(); +            clipboardText = getPgpContent(clipboardText); -            // only decrypt if clipboard content is available and a pgp message or cleartext signature              if (clipboardText != null) { -                Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText); -                if (!matcher.matches()) { -                    matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText); -                } -                if (matcher.matches()) { -                    textData = matcher.group(1); -                } else { -                    Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR); -                } +                loadFragment(savedInstanceState, clipboardText);              } else { -                Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR); +                returnInvalidResult();              }          } else if (ACTION_DECRYPT_TEXT.equals(action)) { -            Log.e(Constants.TAG, -                    "Include the extra 'text' in your Intent!"); +            Log.e(Constants.TAG, "Include the extra 'text' in your Intent!"); +            finish();          } - -        loadFragment(savedInstanceState, textData);      } +    private void returnInvalidResult() { +        SingletonResult result = new SingletonResult( +                SingletonResult.RESULT_ERROR, OperationResult.LogType.MSG_NO_VALID_ENC); +        Intent intent = new Intent(); +        intent.putExtra(SingletonResult.EXTRA_RESULT, result); +        setResult(RESULT_OK, intent); +        finish(); +    }      private void loadFragment(Bundle savedInstanceState, String ciphertext) {          // However, if we're being restored from a previous state, diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index a7bd0825a..d69778fa0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -17,6 +17,7 @@  package org.sufficientlysecure.keychain.ui; +import android.app.Activity;  import android.app.ProgressDialog;  import android.content.Intent;  import android.os.Bundle; @@ -27,22 +28,26 @@ import android.view.View;  import android.view.ViewGroup;  import android.widget.TextView; +import org.openintents.openpgp.util.OpenPgpApi;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;  import org.sufficientlysecure.keychain.service.KeychainIntentService;  import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;  import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; +import org.sufficientlysecure.keychain.ui.util.Notify;  import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ShareHelper;  public class DecryptTextFragment extends DecryptFragment {      public static final String ARG_CIPHERTEXT = "ciphertext"; -//    // view -    private TextView mMessage; -//    private View mDecryptButton; -//    private View mDecryptFromCLipboardButton; -// -//    // model +    // view +    private TextView mText; +    private View mShareButton; +    private View mCopyButton; + +    // model      private String mCiphertext;      /** @@ -66,25 +71,53 @@ public class DecryptTextFragment extends DecryptFragment {      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {          View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false); -        mMessage = (TextView) view.findViewById(R.id.decrypt_text_plaintext); -//        mDecryptButton = view.findViewById(R.id.action_decrypt); -//        mDecryptFromCLipboardButton = view.findViewById(R.id.action_decrypt_from_clipboard); -//        mDecryptButton.setOnClickListener(new OnClickListener() { -//            @Override -//            public void onClick(View v) { -//                decryptClicked(); -//            } -//        }); -//        mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() { -//            @Override -//            public void onClick(View v) { -//                decryptFromClipboardClicked(); -//            } -//        }); +        mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); +        mShareButton = view.findViewById(R.id.action_decrypt_share_plaintext); +        mCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext); +        mShareButton.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString())); +            } +        }); +        mCopyButton.setOnClickListener(new View.OnClickListener() { +            @Override +            public void onClick(View v) { +                copyToClipboard(mText.getText().toString()); +            } +        });          return view;      } +    /** +     * Create Intent Chooser but exclude decrypt activites +     */ +    private Intent sendWithChooserExcludingEncrypt(String text) { +        Intent prototype = createSendIntent(text); +        String title = getString(R.string.title_share_file); + +        // we don't want to decrypt the decypted, no inception ;) +        String[] blacklist = new String[]{ +                Constants.PACKAGE_NAME + ".ui.DecryptTextActivity", +                "org.thialfihar.android.apg.ui.DecryptActivity" +        }; + +        return new ShareHelper(getActivity()).createChooserExcluding(prototype, title, blacklist); +    } + +    private Intent createSendIntent(String text) { +        Intent sendIntent = new Intent(Intent.ACTION_SEND); +        sendIntent.putExtra(Intent.EXTRA_TEXT, text); +        sendIntent.setType("text/plain"); +        return sendIntent; +    } + +    private void copyToClipboard(String text) { +        ClipboardReflection.copyToClipboard(getActivity(), text); +        Notify.showNotify(getActivity(), R.string.text_copied_to_clipboard, Notify.Style.INFO); +    } +      @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState); @@ -92,12 +125,12 @@ public class DecryptTextFragment extends DecryptFragment {          String ciphertext = getArguments().getString(ARG_CIPHERTEXT);          if (ciphertext != null) {              mCiphertext = ciphertext; -            decryptStart(null); +            decryptStart();          }      }      @Override -    protected void decryptStart(String passphrase) { +    protected void decryptStart() {          Log.d(Constants.TAG, "decryptStart");          // Send all information needed to service to decrypt in other thread @@ -111,7 +144,8 @@ public class DecryptTextFragment extends DecryptFragment {          // data          data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES);          data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes()); -        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, passphrase); +        data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase); +        data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);          intent.putExtra(KeychainIntentService.EXTRA_DATA, data); @@ -132,13 +166,13 @@ public class DecryptTextFragment extends DecryptFragment {                      if (pgpResult.isPending()) {                          if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==                                  DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) { -                            showPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded()); +                            startPassphraseDialog(pgpResult.getKeyIdPassphraseNeeded());                          } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==                                  DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) { -                            showPassphraseDialog(Constants.key.symmetric); +                            startPassphraseDialog(Constants.key.symmetric);                          } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==                                  DecryptVerifyResult.RESULT_PENDING_NFC) { -                            // TODO +                            startNfcDecrypt(pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());                          } else {                              throw new RuntimeException("Unhandled pending result!");                          } @@ -146,8 +180,8 @@ public class DecryptTextFragment extends DecryptFragment {                          byte[] decryptedMessage = returnData                                  .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); -                        mMessage.setText(new String(decryptedMessage)); -                        mMessage.setHorizontallyScrolling(false); +                        mText.setText(new String(decryptedMessage)); +                        mText.setHorizontallyScrolling(false);                          pgpResult.createNotify(getActivity()).show(); @@ -171,4 +205,34 @@ public class DecryptTextFragment extends DecryptFragment {          getActivity().startService(intent);      } +    @Override +    public void onActivityResult(int requestCode, int resultCode, Intent data) { +        switch (requestCode) { + +            case REQUEST_CODE_PASSPHRASE: { +                if (resultCode == Activity.RESULT_OK && data != null) { +                    mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE); +                    decryptStart(); +                } else { +                    getActivity().finish(); +                } +                return; +            } + +            case REQUEST_CODE_NFC_DECRYPT: { +                if (resultCode == Activity.RESULT_OK && data != null) { +                    mNfcDecryptedSessionKey = data.getByteArrayExtra(OpenPgpApi.EXTRA_NFC_DECRYPTED_SESSION_KEY); +                    decryptStart(); +                } else { +                    getActivity().finish(); +                } +                return; +            } + +            default: { +                super.onActivityResult(requestCode, resultCode, data); +            } +        } +    } +  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java index a7db73a0a..57c2cac5c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java @@ -654,7 +654,7 @@ public class EditKeyFragment extends LoaderFragment implements          // Prepare an intent with an EXTRA_RESULT          Intent intent = new Intent();          intent.putExtra(OperationResult.EXTRA_RESULT, -                new SingletonResult(SingletonResult.RESULT_ERROR, LogLevel.ERROR, reason)); +                new SingletonResult(SingletonResult.RESULT_ERROR, reason));          // Finish with result          getActivity().setResult(EditKeyActivity.RESULT_OK, intent); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java index cde31abdc..17d4865fd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java @@ -12,27 +12,18 @@ public class EncryptActivity extends DrawerActivity {      public static final int REQUEST_CODE_NFC = 0x00008002;      protected void startPassphraseDialog(long subkeyId) { -        Intent data = new Intent(); - -        // build PendingIntent for Yubikey NFC operations          Intent intent = new Intent(this, PassphraseDialogActivity.class); -        // pass params through to activity that it can be returned again later to repeat pgp operation          intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId); - -//        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); -          startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);      }      protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) { -        Intent data = new Intent(); -          // build PendingIntent for Yubikey NFC operations          Intent intent = new Intent(this, NfcActivity.class);          intent.setAction(NfcActivity.ACTION_SIGN_HASH);          // pass params through to activity that it can be returned again later to repeat pgp operation -        intent.putExtra(NfcActivity.EXTRA_DATA, data); +        intent.putExtra(NfcActivity.EXTRA_DATA, new Intent()); // not used, only relevant to OpenPgpService          intent.putExtra(NfcActivity.EXTRA_PIN, pin);          intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign);          intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java index a508472d6..54877f676 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptAsymmetricFragment.java @@ -135,7 +135,7 @@ public class EncryptAsymmetricFragment extends Fragment implements EncryptActivi              try {                  CachedPublicKeyRing keyring = mProviderHelper.getCachedPublicKeyRing(                          KeyRings.buildUnifiedKeyRingUri(signatureKey)); -                if(keyring.hasAnySecret()) { +                if (keyring.hasAnySecret()) {                      setSignatureKeyId(keyring.getMasterKeyId());                      mSign.setSelectedKeyId(mEncryptInterface.getSignatureKey());                  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index 9b97b6693..28fcb0b10 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -191,8 +191,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi                  super.handleMessage(message);                  if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { -                    Notify.showNotify(EncryptFilesActivity.this, R.string.encrypt_sign_successful, Notify.Style.INFO); -                      SignEncryptResult pgpResult =                              message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); @@ -224,8 +222,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi                              startActivity(sendWithChooserExcludingEncrypt(message));                          } else {                              // Save encrypted file -                            Notify.showNotify(EncryptFilesActivity.this, -                                    R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO); +                            pgpResult.createNotify(EncryptFilesActivity.this).show();                          }                      } else {                          pgpResult.createNotify(EncryptFilesActivity.this).show(); | 
