Merge remote-tracking branch 'origin/master'

Conflicts:
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java
This commit is contained in:
Vincent Breitmoser 2014-09-24 01:42:17 +02:00
commit c871891f49
18 changed files with 335 additions and 204 deletions

View File

@ -96,7 +96,8 @@
<activity <activity
android:name=".ui.CreateKeyActivity" android:name=".ui.CreateKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_create_key"> android:label="@string/title_create_key"
android:parentActivityName=".ui.KeyListActivity">
<meta-data <meta-data
android:name="android.support.PARENT_ACTIVITY" android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.KeyListActivity" /> android:value=".ui.KeyListActivity" />
@ -198,7 +199,11 @@
android:name=".ui.DecryptTextActivity" android:name=".ui.DecryptTextActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_decrypt" android:label="@string/title_decrypt"
android:windowSoftInputMode="stateHidden"> android:windowSoftInputMode="stateHidden"
android:parentActivityName=".ui.DecryptActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.DecryptActivity" />
<!-- Keychain's own Actions --> <!-- Keychain's own Actions -->
<!-- DECRYPT with text as extra --> <!-- DECRYPT with text as extra -->
@ -221,7 +226,11 @@
android:name=".ui.DecryptFilesActivity" android:name=".ui.DecryptFilesActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard" android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_decrypt" android:label="@string/title_decrypt"
android:windowSoftInputMode="stateHidden"> android:windowSoftInputMode="stateHidden"
android:parentActivityName=".ui.DecryptActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.DecryptActivity" />
<!-- VIEW with mimeType application/octet-stream, application/pgp and text/pgp --> <!-- VIEW with mimeType application/octet-stream, application/pgp and text/pgp -->
<intent-filter android:label="@string/intent_send_decrypt"> <intent-filter android:label="@string/intent_send_decrypt">

View File

@ -107,9 +107,8 @@ public class AccountSettingsActivity extends ActionBarActivity {
private void save() { private void save() {
new ProviderHelper(this).updateApiAccount(mAccountUri, mAccountSettingsFragment.getAccSettings()); new ProviderHelper(this).updateApiAccount(mAccountUri, mAccountSettingsFragment.getAccSettings());
// TODO: show "account saved" instead of "operation succeeded"
SingletonResult result = new SingletonResult( 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 intent = new Intent();
intent.putExtra(SingletonResult.EXTRA_RESULT, result); intent.putExtra(SingletonResult.EXTRA_RESULT, result);
setResult(RESULT_OK, intent); setResult(RESULT_OK, intent);

View File

@ -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_ENCRYPTION_KEYS_IDS = "encryption_keys_ids";
public static final String ENCRYPT_COMPRESSION_ID = "compression_id"; public static final String ENCRYPT_COMPRESSION_ID = "compression_id";
public static final String ENCRYPT_MESSAGE_BYTES = "message_bytes"; 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_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_OUTPUT_URIS = "output_uris";
public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase"; public static final String ENCRYPT_SYMMETRIC_PASSPHRASE = "passphrase";
// decrypt/verify // decrypt/verify
public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes"; public static final String DECRYPT_CIPHERTEXT_BYTES = "ciphertext_bytes";
public static final String DECRYPT_PASSPHRASE = "passphrase"; public static final String DECRYPT_PASSPHRASE = "passphrase";
public static final String DECRYPT_NFC_DECRYPTED_SESSION_KEY = "nfc_decrypted_session_key";
// save keyring // save keyring
public static final String EDIT_KEYRING_PARCEL = "save_parcel"; public static final String EDIT_KEYRING_PARCEL = "save_parcel";
@ -337,6 +338,7 @@ public class KeychainIntentService extends IntentService implements Progressable
try { try {
/* Input */ /* Input */
String passphrase = data.getString(DECRYPT_PASSPHRASE); String passphrase = data.getString(DECRYPT_PASSPHRASE);
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
InputData inputData = createDecryptInputData(data); InputData inputData = createDecryptInputData(data);
OutputStream outStream = createCryptOutputStream(data); OutputStream outStream = createCryptOutputStream(data);
@ -353,7 +355,8 @@ public class KeychainIntentService extends IntentService implements Progressable
); );
builder.setProgressable(this) builder.setProgressable(this)
.setAllowSymmetricDecryption(true) .setAllowSymmetricDecryption(true)
.setPassphrase(passphrase); .setPassphrase(passphrase)
.setNfcState(nfcDecryptedSessionKey);
DecryptVerifyResult decryptVerifyResult = builder.build().execute(); DecryptVerifyResult decryptVerifyResult = builder.build().execute();
@ -375,6 +378,7 @@ public class KeychainIntentService extends IntentService implements Progressable
try { try {
/* Input */ /* Input */
String passphrase = data.getString(DECRYPT_PASSPHRASE); String passphrase = data.getString(DECRYPT_PASSPHRASE);
byte[] nfcDecryptedSessionKey = data.getByteArray(DECRYPT_NFC_DECRYPTED_SESSION_KEY);
InputData inputData = createDecryptInputData(data); InputData inputData = createDecryptInputData(data);
@ -391,7 +395,8 @@ public class KeychainIntentService extends IntentService implements Progressable
builder.setProgressable(this) builder.setProgressable(this)
.setAllowSymmetricDecryption(true) .setAllowSymmetricDecryption(true)
.setPassphrase(passphrase) .setPassphrase(passphrase)
.setDecryptMetadataOnly(true); .setDecryptMetadataOnly(true)
.setNfcState(nfcDecryptedSessionKey);
DecryptVerifyResult decryptVerifyResult = builder.build().execute(); DecryptVerifyResult decryptVerifyResult = builder.build().execute();
@ -860,7 +865,7 @@ public class KeychainIntentService extends IntentService implements Progressable
return new InputData(new ByteArrayInputStream(bytes), bytes.length); return new InputData(new ByteArrayInputStream(bytes), bytes.length);
case IO_URI: /* encrypting content uri */ case IO_URI: /* encrypting content uri */
Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_INPUT_URI);
// InputStream // InputStream
return new InputData(getContentResolver().openInputStream(providerUri), FileHelper.getFileSize(this, providerUri, 0)); return new InputData(getContentResolver().openInputStream(providerUri), FileHelper.getFileSize(this, providerUri, 0));
@ -912,7 +917,7 @@ public class KeychainIntentService extends IntentService implements Progressable
return ""; return "";
case IO_URI: case IO_URI:
Uri providerUri = data.getParcelable(ENCRYPT_INPUT_URI); Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_INPUT_URI);
return FileHelper.getFilename(this, providerUri); return FileHelper.getFilename(this, providerUri);
@ -933,7 +938,7 @@ public class KeychainIntentService extends IntentService implements Progressable
return new ByteArrayOutputStream(); return new ByteArrayOutputStream();
case IO_URI: case IO_URI:
Uri providerUri = data.getParcelable(ENCRYPT_OUTPUT_URI); Uri providerUri = data.getParcelable(ENCRYPT_DECRYPT_OUTPUT_URI);
return getContentResolver().openOutputStream(providerUri); return getContentResolver().openOutputStream(providerUri);

View File

@ -519,7 +519,9 @@ public abstract class OperationResult implements Parcelable {
MSG_CRT_UPLOAD_SUCCESS (LogLevel.OK, R.string.msg_crt_upload_success), MSG_CRT_UPLOAD_SUCCESS (LogLevel.OK, R.string.msg_crt_upload_success),
MSG_CRT_SUCCESS (LogLevel.OK, R.string.msg_crt_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)
; ;

View File

@ -34,7 +34,7 @@ public class SingletonResult extends OperationResult {
super(source); super(source);
} }
public SingletonResult(int result, LogLevel level, LogType reason) { public SingletonResult(int result, LogType reason) {
super(result, new OperationLog()); super(result, new OperationLog());
// Prepare the log // Prepare the log
mLog.add(reason, 0); mLog.add(reason, 0);

View File

@ -330,7 +330,7 @@ public class CertifyKeyFragment extends LoaderFragment
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
SingletonResult result = new SingletonResult( 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 intent = new Intent();
intent.putExtra(SingletonResult.EXTRA_RESULT, result); intent.putExtra(SingletonResult.EXTRA_RESULT, result);
mActivity.setResult(CertifyKeyActivity.RESULT_OK, intent); mActivity.setResult(CertifyKeyActivity.RESULT_OK, intent);
@ -384,7 +384,7 @@ public class CertifyKeyFragment extends LoaderFragment
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
SingletonResult result = new SingletonResult(SingletonResult.RESULT_OK, SingletonResult result = new SingletonResult(SingletonResult.RESULT_OK,
LogLevel.OK, LogType.MSG_CRT_UPLOAD_SUCCESS); LogType.MSG_CRT_UPLOAD_SUCCESS);
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(SingletonResult.EXTRA_RESULT, result); intent.putExtra(SingletonResult.EXTRA_RESULT, result);
mActivity.setResult(CertifyKeyActivity.RESULT_OK, intent); mActivity.setResult(CertifyKeyActivity.RESULT_OK, intent);

View File

@ -22,6 +22,7 @@ import android.os.Bundle;
import android.view.View; import android.view.View;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.service.results.OperationResult;
public class DecryptActivity extends DrawerActivity { public class DecryptActivity extends DrawerActivity {
@ -50,8 +51,19 @@ public class DecryptActivity extends DrawerActivity {
public void onClick(View v) { public void onClick(View v) {
Intent clipboardDecrypt = new Intent(DecryptActivity.this, DecryptTextActivity.class); Intent clipboardDecrypt = new Intent(DecryptActivity.this, DecryptTextActivity.class);
clipboardDecrypt.setAction(DecryptTextActivity.ACTION_DECRYPT_FROM_CLIPBOARD); 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);
}
}
} }

View File

@ -23,7 +23,6 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.Messenger; import android.os.Messenger;
import android.text.TextUtils; import android.text.TextUtils;
@ -33,6 +32,7 @@ import android.view.ViewGroup;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.TextView; import android.widget.TextView;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.FileHelper; 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.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify;
@ -48,7 +47,6 @@ import java.io.File;
public class DecryptFilesFragment extends DecryptFragment { public class DecryptFilesFragment extends DecryptFragment {
public static final String ARG_URI = "uri"; 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"; public static final String ARG_OPEN_DIRECTLY = "open_directly";
private static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_INPUT = 0x00007003;
@ -71,7 +69,6 @@ public class DecryptFilesFragment extends DecryptFragment {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelable(ARG_URI, uri); args.putParcelable(ARG_URI, uri);
// args.putBoolean(ARG_FROM_VIEW_INTENT, fromViewIntent);
args.putBoolean(ARG_OPEN_DIRECTLY, openDirectly); args.putBoolean(ARG_OPEN_DIRECTLY, openDirectly);
frag.setArguments(args); frag.setArguments(args);
@ -143,7 +140,7 @@ public class DecryptFilesFragment extends DecryptFragment {
} }
// askForOutputFilename(); // askForOutputFilename();
decryptOriginalFilename(null); decryptOriginalFilename();
} }
private String removeEncryptedAppend(String name) { 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"); Log.d(Constants.TAG, "decryptOriginalFilename");
Intent intent = new Intent(getActivity(), KeychainIntentService.class); Intent intent = new Intent(getActivity(), KeychainIntentService.class);
@ -184,12 +181,13 @@ public class DecryptFilesFragment extends DecryptFragment {
Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri); Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);
data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); 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.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); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@ -210,13 +208,13 @@ public class DecryptFilesFragment extends DecryptFragment {
if (pgpResult.isPending()) { if (pgpResult.isPending()) {
if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
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) == } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
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) == } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
DecryptVerifyResult.RESULT_PENDING_NFC) { DecryptVerifyResult.RESULT_PENDING_NFC) {
// TODO startNfcDecrypt(pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());
} else { } else {
throw new RuntimeException("Unhandled pending result!"); throw new RuntimeException("Unhandled pending result!");
} }
@ -241,23 +239,8 @@ public class DecryptFilesFragment extends DecryptFragment {
getActivity().startService(intent); getActivity().startService(intent);
} }
protected void showPassphraseDialogForFilename(long keyId) {
PassphraseDialogFragment.show(getActivity(), keyId,
new Handler() {
@Override @Override
public void handleMessage(Message message) { protected void decryptStart() {
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
String passphrase =
message.getData().getString(PassphraseDialogFragment.MESSAGE_DATA_PASSPHRASE);
decryptOriginalFilename(passphrase);
}
}
}
);
}
@Override
protected void decryptStart(String passphrase) {
Log.d(Constants.TAG, "decryptStart"); Log.d(Constants.TAG, "decryptStart");
// Send all information needed to service to decrypt in other thread // 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); Log.d(Constants.TAG, "mInputUri=" + mInputUri + ", mOutputUri=" + mOutputUri);
data.putInt(KeychainIntentService.SOURCE, KeychainIntentService.IO_URI); 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.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); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@ -298,13 +282,13 @@ public class DecryptFilesFragment extends DecryptFragment {
if (pgpResult.isPending()) { if (pgpResult.isPending()) {
if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
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) == } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
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) == } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
DecryptVerifyResult.RESULT_PENDING_NFC) { DecryptVerifyResult.RESULT_PENDING_NFC) {
// TODO startNfcDecrypt(pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());
} else { } else {
throw new RuntimeException("Unhandled pending result!"); throw new RuntimeException("Unhandled pending result!");
} }
@ -350,25 +334,40 @@ public class DecryptFilesFragment extends DecryptFragment {
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) { 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: { case REQUEST_CODE_INPUT: {
if (resultCode == Activity.RESULT_OK && data != null) { if (resultCode == Activity.RESULT_OK && data != null) {
setInputUri(data.getData()); setInputUri(data.getData());
} }
return; return;
} }
case REQUEST_CODE_OUTPUT: { case REQUEST_CODE_OUTPUT: {
// This happens after output file was selected, so start our operation // This happens after output file was selected, so start our operation
if (resultCode == Activity.RESULT_OK && data != null) { if (resultCode == Activity.RESULT_OK && data != null) {
mOutputUri = data.getData(); mOutputUri = data.getData();
decryptStart(null); decryptStart();
} }
return; return;
} }
default: { default: {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
break;
} }
} }
} }

View File

@ -17,11 +17,8 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
@ -33,14 +30,17 @@ import android.widget.TextView;
import org.openintents.openpgp.OpenPgpSignatureResult; import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.nfc.NfcActivity;
import org.sufficientlysecure.keychain.pgp.KeyRing; import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
public abstract class DecryptFragment extends Fragment { public abstract class DecryptFragment extends Fragment {
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006; 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 long mSignatureKeyId = 0;
protected LinearLayout mResultLayout; protected LinearLayout mResultLayout;
@ -53,6 +53,9 @@ public abstract class DecryptFragment extends Fragment {
protected Button mLookupKey; protected Button mLookupKey;
// State
protected String mPassphrase;
protected byte[] mNfcDecryptedSessionKey;
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
@ -81,23 +84,23 @@ public abstract class DecryptFragment extends Fragment {
startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY); startActivityForResult(intent, RESULT_CODE_LOOKUP_KEY);
} }
@Override protected void startPassphraseDialog(long subkeyId) {
public void onActivityResult(int requestCode, int resultCode, Intent data) { Intent intent = new Intent(getActivity(), PassphraseDialogActivity.class);
switch (requestCode) { 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;
} }
default: { protected void startNfcDecrypt(String pin, byte[] encryptedSessionKey) {
super.onActivityResult(requestCode, resultCode, data); // 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);
break; intent.putExtra(NfcActivity.EXTRA_NFC_ENC_SESSION_KEY, encryptedSessionKey);
} intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
}
startActivityForResult(intent, REQUEST_CODE_NFC_DECRYPT);
} }
protected void onResult(DecryptVerifyResult decryptVerifyResult) { 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 * Should be overridden by MessageFragment and FileFragment to start actual decryption
*
* @param passphrase
*/ */
protected abstract void decryptStart(String passphrase); protected abstract void decryptStart();
} }

View File

@ -27,6 +27,8 @@ import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.api.OpenKeychainIntents; import org.sufficientlysecure.keychain.api.OpenKeychainIntents;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.pgp.PgpHelper; 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.util.Log;
import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify;
@ -53,6 +55,48 @@ public class DecryptTextActivity extends ActionBarActivity {
handleActions(savedInstanceState, getIntent()); handleActions(savedInstanceState, getIntent());
} }
/**
* 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 * Handles all actions with this intent
* *
@ -67,74 +111,59 @@ public class DecryptTextActivity extends ActionBarActivity {
extras = new Bundle(); extras = new Bundle();
} }
String textData = null;
/*
* Android's Action
*/
if (Intent.ACTION_SEND.equals(action) && type != null) { if (Intent.ACTION_SEND.equals(action) && type != null) {
// Android action
// When sending to Keychain Decrypt via share menu // When sending to Keychain Decrypt via share menu
if ("text/plain".equals(type)) { if ("text/plain".equals(type)) {
// Plain text
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
sharedText = getPgpContent(sharedText);
if (sharedText != null) { if (sharedText != null) {
// handle like normal text decryption, override action and extras to later loadFragment(savedInstanceState, sharedText);
// executeServiceMethod ACTION_DECRYPT_TEXT in main actions
textData = sharedText;
}
}
}
/**
* 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", " ");
} 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!");
}
}
} else if (ACTION_DECRYPT_FROM_CLIPBOARD.equals(action)) {
CharSequence clipboardText = ClipboardReflection.getClipboardText(this);
// 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 { } else {
Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR); Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR);
} }
} else { } else {
Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR); Log.e(Constants.TAG, "ACTION_SEND received non-plaintext, this should not happen in this activity!");
} }
} else if (ACTION_DECRYPT_TEXT.equals(action)) { } else if (ACTION_DECRYPT_TEXT.equals(action)) {
Log.e(Constants.TAG, Log.d(Constants.TAG, "ACTION_DECRYPT_TEXT textData not null, matching text...");
"Include the extra 'text' in your Intent!");
String extraText = extras.getString(EXTRA_TEXT);
extraText = getPgpContent(extraText);
if (extraText != null) {
loadFragment(savedInstanceState, extraText);
} else {
Notify.showNotify(this, R.string.error_invalid_data, Notify.Style.ERROR);
}
} else if (ACTION_DECRYPT_FROM_CLIPBOARD.equals(action)) {
Log.d(Constants.TAG, "ACTION_DECRYPT_FROM_CLIPBOARD");
String clipboardText = ClipboardReflection.getClipboardText(this).toString();
clipboardText = getPgpContent(clipboardText);
if (clipboardText != null) {
loadFragment(savedInstanceState, clipboardText);
} else {
returnInvalidResult();
}
} else if (ACTION_DECRYPT_TEXT.equals(action)) {
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) { private void loadFragment(Bundle savedInstanceState, String ciphertext) {
// However, if we're being restored from a previous state, // However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else // then we don't need to do anything and should return or else

View File

@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui; package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@ -27,22 +28,26 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult; 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.Log;
import org.sufficientlysecure.keychain.util.ShareHelper;
public class DecryptTextFragment extends DecryptFragment { public class DecryptTextFragment extends DecryptFragment {
public static final String ARG_CIPHERTEXT = "ciphertext"; public static final String ARG_CIPHERTEXT = "ciphertext";
// // view // view
private TextView mMessage; private TextView mText;
// private View mDecryptButton; private View mShareButton;
// private View mDecryptFromCLipboardButton; private View mCopyButton;
//
// // model // model
private String mCiphertext; private String mCiphertext;
/** /**
@ -66,25 +71,53 @@ public class DecryptTextFragment extends DecryptFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false); View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false);
mMessage = (TextView) view.findViewById(R.id.decrypt_text_plaintext); mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext);
// mDecryptButton = view.findViewById(R.id.action_decrypt); mShareButton = view.findViewById(R.id.action_decrypt_share_plaintext);
// mDecryptFromCLipboardButton = view.findViewById(R.id.action_decrypt_from_clipboard); mCopyButton = view.findViewById(R.id.action_decrypt_copy_plaintext);
// mDecryptButton.setOnClickListener(new OnClickListener() { mShareButton.setOnClickListener(new View.OnClickListener() {
// @Override @Override
// public void onClick(View v) { public void onClick(View v) {
// decryptClicked(); startActivity(sendWithChooserExcludingEncrypt(mText.getText().toString()));
// } }
// }); });
// mDecryptFromCLipboardButton.setOnClickListener(new OnClickListener() { mCopyButton.setOnClickListener(new View.OnClickListener() {
// @Override @Override
// public void onClick(View v) { public void onClick(View v) {
// decryptFromClipboardClicked(); copyToClipboard(mText.getText().toString());
// } }
// }); });
return view; 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 @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -92,12 +125,12 @@ public class DecryptTextFragment extends DecryptFragment {
String ciphertext = getArguments().getString(ARG_CIPHERTEXT); String ciphertext = getArguments().getString(ARG_CIPHERTEXT);
if (ciphertext != null) { if (ciphertext != null) {
mCiphertext = ciphertext; mCiphertext = ciphertext;
decryptStart(null); decryptStart();
} }
} }
@Override @Override
protected void decryptStart(String passphrase) { protected void decryptStart() {
Log.d(Constants.TAG, "decryptStart"); Log.d(Constants.TAG, "decryptStart");
// Send all information needed to service to decrypt in other thread // Send all information needed to service to decrypt in other thread
@ -111,7 +144,8 @@ public class DecryptTextFragment extends DecryptFragment {
// data // data
data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES); data.putInt(KeychainIntentService.TARGET, KeychainIntentService.IO_BYTES);
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes()); 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); intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
@ -132,13 +166,13 @@ public class DecryptTextFragment extends DecryptFragment {
if (pgpResult.isPending()) { if (pgpResult.isPending()) {
if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) == if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_ASYM_PASSPHRASE) ==
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) == } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_SYM_PASSPHRASE) ==
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) == } else if ((pgpResult.getResult() & DecryptVerifyResult.RESULT_PENDING_NFC) ==
DecryptVerifyResult.RESULT_PENDING_NFC) { DecryptVerifyResult.RESULT_PENDING_NFC) {
// TODO startNfcDecrypt(pgpResult.getNfcPassphrase(), pgpResult.getNfcEncryptedSessionKey());
} else { } else {
throw new RuntimeException("Unhandled pending result!"); throw new RuntimeException("Unhandled pending result!");
} }
@ -146,8 +180,8 @@ public class DecryptTextFragment extends DecryptFragment {
byte[] decryptedMessage = returnData byte[] decryptedMessage = returnData
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
mMessage.setText(new String(decryptedMessage)); mText.setText(new String(decryptedMessage));
mMessage.setHorizontallyScrolling(false); mText.setHorizontallyScrolling(false);
pgpResult.createNotify(getActivity()).show(); pgpResult.createNotify(getActivity()).show();
@ -171,4 +205,34 @@ public class DecryptTextFragment extends DecryptFragment {
getActivity().startService(intent); 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);
}
}
}
} }

View File

@ -654,7 +654,7 @@ public class EditKeyFragment extends LoaderFragment implements
// Prepare an intent with an EXTRA_RESULT // Prepare an intent with an EXTRA_RESULT
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra(OperationResult.EXTRA_RESULT, intent.putExtra(OperationResult.EXTRA_RESULT,
new SingletonResult(SingletonResult.RESULT_ERROR, LogLevel.ERROR, reason)); new SingletonResult(SingletonResult.RESULT_ERROR, reason));
// Finish with result // Finish with result
getActivity().setResult(EditKeyActivity.RESULT_OK, intent); getActivity().setResult(EditKeyActivity.RESULT_OK, intent);

View File

@ -12,27 +12,18 @@ public class EncryptActivity extends DrawerActivity {
public static final int REQUEST_CODE_NFC = 0x00008002; public static final int REQUEST_CODE_NFC = 0x00008002;
protected void startPassphraseDialog(long subkeyId) { protected void startPassphraseDialog(long subkeyId) {
Intent data = new Intent();
// build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(this, PassphraseDialogActivity.class); 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.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, subkeyId);
// intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE); startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
} }
protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) { protected void startNfcSign(String pin, byte[] hashToSign, int hashAlgo) {
Intent data = new Intent();
// build PendingIntent for Yubikey NFC operations // build PendingIntent for Yubikey NFC operations
Intent intent = new Intent(this, NfcActivity.class); Intent intent = new Intent(this, NfcActivity.class);
intent.setAction(NfcActivity.ACTION_SIGN_HASH); intent.setAction(NfcActivity.ACTION_SIGN_HASH);
// pass params through to activity that it can be returned again later to repeat pgp operation // 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_PIN, pin);
intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign); intent.putExtra(NfcActivity.EXTRA_NFC_HASH_TO_SIGN, hashToSign);
intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo); intent.putExtra(NfcActivity.EXTRA_NFC_HASH_ALGO, hashAlgo);

View File

@ -191,8 +191,6 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
super.handleMessage(message); super.handleMessage(message);
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
Notify.showNotify(EncryptFilesActivity.this, R.string.encrypt_sign_successful, Notify.Style.INFO);
SignEncryptResult pgpResult = SignEncryptResult pgpResult =
message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT); message.getData().getParcelable(SignEncryptResult.EXTRA_RESULT);
@ -224,8 +222,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
startActivity(sendWithChooserExcludingEncrypt(message)); startActivity(sendWithChooserExcludingEncrypt(message));
} else { } else {
// Save encrypted file // Save encrypted file
Notify.showNotify(EncryptFilesActivity.this, pgpResult.createNotify(EncryptFilesActivity.this).show();
R.string.encrypt_sign_clipboard_successful, Notify.Style.INFO);
} }
} else { } else {
pgpResult.createNotify(EncryptFilesActivity.this).show(); pgpResult.createNotify(EncryptFilesActivity.this).show();

View File

@ -21,7 +21,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="Files" /> android:text="@string/section_decrypt_files" />
<TextView <TextView
@ -34,7 +34,7 @@
android:minHeight="?android:attr/listPreferredItemHeight" android:minHeight="?android:attr/listPreferredItemHeight"
android:clickable="true" android:clickable="true"
style="@style/SelectableItem" style="@style/SelectableItem"
android:text="Decrypt files" android:text="@string/btn_decrypt_files"
android:drawableRight="@drawable/ic_action_collection" android:drawableRight="@drawable/ic_action_collection"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:gravity="center_vertical" /> android:gravity="center_vertical" />
@ -50,23 +50,52 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="32dp" android:layout_marginTop="32dp"
android:text="Text" /> android:text="@string/section_decrypt_text" />
<LinearLayout
android:id="@+id/decrypt_from_clipboard"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:clickable="true"
android:paddingRight="4dp"
style="@style/SelectableItem"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingRight="4dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView <TextView
android:id="@+id/decrypt_from_clipboard"
android:paddingLeft="8dp" android:paddingLeft="8dp"
android:paddingRight="8dp"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight" android:text="@string/btn_decrypt_clipboard" />
android:clickable="true"
style="@style/SelectableItem" <TextView
android:text="Decrypt from clipboard" android:paddingLeft="8dp"
android:drawableRight="@drawable/ic_action_paste" android:textAppearance="?android:attr/textAppearanceSmall"
android:drawablePadding="8dp" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/tertiary_text_light"
android:text="@string/btn_decrypt_and_verify"
android:gravity="center_vertical" /> android:gravity="center_vertical" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="8dp"
android:src="@drawable/ic_action_paste"
android:layout_gravity="center_vertical" />
</LinearLayout>
<View <View
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dip" android:layout_height="1dip"
@ -75,4 +104,5 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -43,7 +43,7 @@
<LinearLayout <LinearLayout
android:id="@+id/action_encrypt_share_plaintext" android:id="@+id/action_decrypt_share_plaintext"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
@ -57,7 +57,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight" android:minHeight="?android:attr/listPreferredItemHeight"
android:text="Share plaintext" android:text="@string/btn_add_share_decrypted_text"
android:drawableRight="@drawable/ic_action_share" android:drawableRight="@drawable/ic_action_share"
android:drawablePadding="8dp" android:drawablePadding="8dp"
android:gravity="center_vertical" android:gravity="center_vertical"
@ -72,7 +72,7 @@
android:background="?android:attr/listDivider" /> android:background="?android:attr/listDivider" />
<ImageButton <ImageButton
android:id="@+id/action_copy_plaintext" android:id="@+id/action_decrypt_copy_plaintext"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="8dp" android:padding="8dp"

View File

@ -51,6 +51,8 @@
<string name="section_key_server">"Keyserver"</string> <string name="section_key_server">"Keyserver"</string>
<string name="section_fingerprint">"Fingerprint"</string> <string name="section_fingerprint">"Fingerprint"</string>
<string name="section_key_to_certify">"Key to be certified"</string> <string name="section_key_to_certify">"Key to be certified"</string>
<string name="section_decrypt_files">"Files"</string>
<string name="section_decrypt_text">"Text"</string>
<!-- button --> <!-- button -->
<string name="btn_decrypt_verify_file">"Decrypt, verify, and save file"</string> <string name="btn_decrypt_verify_file">"Decrypt, verify, and save file"</string>
@ -70,6 +72,10 @@
<string name="btn_view_cert_key">"View certification key"</string> <string name="btn_view_cert_key">"View certification key"</string>
<string name="btn_create_key">"Create key"</string> <string name="btn_create_key">"Create key"</string>
<string name="btn_add_files">"Add file(s)"</string> <string name="btn_add_files">"Add file(s)"</string>
<string name="btn_add_share_decrypted_text">"Share decrypted text"</string>
<string name="btn_decrypt_clipboard">"Decrypt from clipboard"</string>
<string name="btn_decrypt_and_verify">"and verify signatures"</string>
<string name="btn_decrypt_files">"Decrypt files"</string>
<!-- menu --> <!-- menu -->
<string name="menu_preferences">"Settings"</string> <string name="menu_preferences">"Settings"</string>
@ -225,6 +231,7 @@
<string name="fingerprint_copied_to_clipboard">"Fingerprint has been copied to the clipboard!"</string> <string name="fingerprint_copied_to_clipboard">"Fingerprint has been copied to the clipboard!"</string>
<string name="select_key_to_certify">"Please select a key to be used for certification!"</string> <string name="select_key_to_certify">"Please select a key to be used for certification!"</string>
<string name="key_too_big_for_sharing">"Key is too big to be shared this way!"</string> <string name="key_too_big_for_sharing">"Key is too big to be shared this way!"</string>
<string name="text_copied_to_clipboard">"Text has been copied to the clipboard!"</string>
<!-- <!--
errors errors
@ -241,7 +248,7 @@
<string name="error_key_needs_a_user_id">"need at least one identity"</string> <string name="error_key_needs_a_user_id">"need at least one identity"</string>
<string name="error_no_signature_passphrase">"no passphrase given"</string> <string name="error_no_signature_passphrase">"no passphrase given"</string>
<string name="error_no_signature_key">"no signature key given"</string> <string name="error_no_signature_key">"no signature key given"</string>
<string name="error_invalid_data">"not valid encryption data"</string> <string name="error_invalid_data">"No valid encrypted or signed OpenPGP content!"</string>
<string name="error_integrity_check_failed">"integrity check failed! Data has been modified!"</string> <string name="error_integrity_check_failed">"integrity check failed! Data has been modified!"</string>
<string name="error_wrong_passphrase">"wrong passphrase"</string> <string name="error_wrong_passphrase">"wrong passphrase"</string>
<string name="error_could_not_extract_private_key">"could not extract private key"</string> <string name="error_could_not_extract_private_key">"could not extract private key"</string>
@ -424,6 +431,7 @@
<string name="api_settings_select_key">"Select key"</string> <string name="api_settings_select_key">"Select key"</string>
<string name="api_settings_create_key">"Create new key for this account"</string> <string name="api_settings_create_key">"Create new key for this account"</string>
<string name="api_settings_save">"Save"</string> <string name="api_settings_save">"Save"</string>
<string name="api_settings_save_msg">"Account has been saved"</string>
<string name="api_settings_cancel">"Cancel"</string> <string name="api_settings_cancel">"Cancel"</string>
<string name="api_settings_revoke">"Revoke access"</string> <string name="api_settings_revoke">"Revoke access"</string>
<string name="api_settings_start">"Start application"</string> <string name="api_settings_start">"Start application"</string>