From 2bb7c3bcef695519c58d33253b74393caf7f14a0 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 25 Jan 2015 15:25:49 +0100 Subject: move last parts of import logic from kis into operation --- .../keychain/operations/ImportExportOperation.java | 48 +++++++++++++++++-- .../operations/results/ImportKeyResult.java | 4 ++ .../operations/results/OperationResult.java | 1 + .../keychain/service/KeychainIntentService.java | 55 +++++++--------------- OpenKeychain/src/main/res/values/strings.xml | 1 + 5 files changed, 68 insertions(+), 41 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java index cd8a33c20..3f3e0a432 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportExportOperation.java @@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver; import org.sufficientlysecure.keychain.keyimport.Keyserver; import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; +import org.sufficientlysecure.keychain.operations.results.ConsolidateResult; import org.sufficientlysecure.keychain.operations.results.ExportResult; import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing; import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; @@ -44,9 +45,12 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.LogTyp import org.sufficientlysecure.keychain.operations.results.OperationResult.OperationLog; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult; +import org.sufficientlysecure.keychain.service.ContactSyncAdapterService; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.util.FileHelper; import org.sufficientlysecure.keychain.util.Log; +import org.sufficientlysecure.keychain.util.ParcelableFileCache; +import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize; import org.sufficientlysecure.keychain.util.ProgressScaler; import java.io.BufferedOutputStream; @@ -58,6 +62,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; /** An operation class which implements high level import and export @@ -123,6 +128,35 @@ public class ImportExportOperation extends BaseOperation { } } + public ImportKeyResult importKeyRings(List entries, String keyServerUri) { + + Iterator it = entries.iterator(); + int numEntries = entries.size(); + + return importKeyRings(it, numEntries, keyServerUri); + + } + + public ImportKeyResult importKeyRings(ParcelableFileCache cache, String keyServerUri) { + + // get entries from cached file + try { + IteratorWithSize it = cache.readCache(); + int numEntries = it.getSize(); + + return importKeyRings(it, numEntries, keyServerUri); + } catch (IOException e) { + + // Special treatment here, we need a lot + OperationLog log = new OperationLog(); + log.add(LogType.MSG_IMPORT, 0, 0); + log.add(LogType.MSG_IMPORT_ERROR_IO, 0, 0); + + return new ImportKeyResult(ImportKeyResult.RESULT_ERROR, log); + } + + } + public ImportKeyResult importKeyRings(Iterator entries, int num, String keyServerUri) { updateProgress(R.string.progress_importing, 0, 100); @@ -131,9 +165,7 @@ public class ImportExportOperation extends BaseOperation { // If there aren't even any keys, do nothing here. if (entries == null || !entries.hasNext()) { - return new ImportKeyResult( - ImportKeyResult.RESULT_FAIL_NOTHING, log, 0, 0, 0, 0, - new long[]{}); + return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, log); } int newKeys = 0, oldKeys = 0, badKeys = 0, secret = 0; @@ -293,6 +325,16 @@ public class ImportExportOperation extends BaseOperation { position++; } + // Special: consolidate on secret key import (cannot be cancelled!) + if (secret > 0) { + setPreventCancel(); + ConsolidateResult result = mProviderHelper.consolidateDatabaseStep1(mProgressable); + log.add(result, 1); + } + + // Special: make sure new data is synced into contacts + ContactSyncAdapterService.requestSync(); + // convert to long array long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()]; for (int i = 0; i < importedMasterKeyIds.size(); ++i) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java index 1dd038a23..91b53fd78 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/ImportKeyResult.java @@ -83,6 +83,10 @@ public class ImportKeyResult extends OperationResult { mImportedMasterKeyIds = source.createLongArray(); } + public ImportKeyResult(int result, OperationLog log) { + this(result, log, 0, 0, 0, 0, new long[] { }); + } + public ImportKeyResult(int result, OperationLog log, int newKeys, int updatedKeys, int badKeys, int secret, long[] importedMasterKeyIds) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index d025727b5..eba8f13af 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -654,6 +654,7 @@ public abstract class OperationResult implements Parcelable { MSG_IMPORT_FINGERPRINT_ERROR (LogLevel.ERROR, R.string.msg_import_fingerprint_error), MSG_IMPORT_FINGERPRINT_OK (LogLevel.DEBUG, R.string.msg_import_fingerprint_ok), MSG_IMPORT_ERROR (LogLevel.ERROR, R.string.msg_import_error), + MSG_IMPORT_ERROR_IO (LogLevel.ERROR, R.string.msg_import_error_io), MSG_IMPORT_PARTIAL (LogLevel.ERROR, R.string.msg_import_partial), MSG_IMPORT_SUCCESS (LogLevel.OK, R.string.msg_import_success), 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 b96d8945c..c88e0bd8d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -403,49 +403,28 @@ public class KeychainIntentService extends IntentService implements Progressable break; } - case ACTION_IMPORT_KEYRING: + case ACTION_IMPORT_KEYRING: { - try { - - // Input - String keyServer = data.getString(IMPORT_KEY_SERVER); - Iterator entries; - int numEntries; - if (data.containsKey(IMPORT_KEY_LIST)) { - // get entries from intent - ArrayList list = data.getParcelableArrayList(IMPORT_KEY_LIST); - entries = list.iterator(); - numEntries = list.size(); - } else { - // get entries from cached file - ParcelableFileCache cache = - new ParcelableFileCache<>(this, "key_import.pcl"); - IteratorWithSize it = cache.readCache(); - entries = it; - numEntries = it.getSize(); - } - - // Operation - ImportExportOperation importExportOperation = new ImportExportOperation( - this, providerHelper, this, mActionCanceled); - ImportKeyResult result = importExportOperation.importKeyRings(entries, numEntries, keyServer); - - // Special: consolidate on secret key import (cannot be cancelled!) - if (result.mSecret > 0) { - // TODO move this into the import operation - providerHelper.consolidateDatabaseStep1(this); - } + // Input + String keyServer = data.getString(IMPORT_KEY_SERVER); + ArrayList list = data.getParcelableArrayList(IMPORT_KEY_LIST); + ParcelableFileCache cache = + new ParcelableFileCache<>(this, "key_import.pcl"); - // Special: make sure new data is synced into contacts - ContactSyncAdapterService.requestSync(); + // Operation + ImportExportOperation importExportOperation = new ImportExportOperation( + this, providerHelper, this, mActionCanceled); + // Either list or cache must be null, no guarantees otherwise. + ImportKeyResult result = list != null + ? importExportOperation.importKeyRings(list, keyServer) + : importExportOperation.importKeyRings(cache, keyServer); - // Result - sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); - } catch (Exception e) { - sendErrorToHandler(e); - } + // Result + sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result); break; + + } case ACTION_SIGN_ENCRYPT: try { diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 459bdf99c..b63ccec2d 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -1021,6 +1021,7 @@ "Fingerprint check OK" "Merging retrieved data" "Import operation failed!" + "Import operation failed due to i/o error!" "Import operation successful, with errors!" "Import operation successful!" -- cgit v1.2.3 From efe5c80b1cd4cecb313f399fb5d3b994e690a708 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 26 Jan 2015 16:32:23 +0100 Subject: remove unused NonPgpPartException --- .../keychain/ui/adapter/ImportKeysListLoader.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java index 9d1e8468c..144a16a48 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListLoader.java @@ -39,18 +39,6 @@ import java.util.ArrayList; public class ImportKeysListLoader extends AsyncTaskLoader>> { - public static class NonPgpPartException extends Exception { - private int mCount; - - public NonPgpPartException(int count) { - this.mCount = count; - } - - public int getCount() { - return mCount; - } - } - final Context mContext; final InputData mInputData; -- cgit v1.2.3 From 6c80025ead59b558ebb2d6a9f802ef046e673388 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 27 Jan 2015 09:17:23 +0100 Subject: backend support for charset in ascii-armored streams --- .../keychain/pgp/PgpEncryptDecryptTest.java | 54 ++++++++++++++++++++++ .../operations/results/DecryptVerifyResult.java | 11 +++++ .../operations/results/OperationResult.java | 1 + .../keychain/pgp/PgpDecryptVerify.java | 24 ++++++++-- .../keychain/pgp/PgpSignEncrypt.java | 12 +++++ .../keychain/remote/OpenPgpService.java | 6 +++ .../keychain/ui/DecryptTextFragment.java | 15 +++++- OpenKeychain/src/main/res/values/strings.xml | 1 + 8 files changed, 120 insertions(+), 4 deletions(-) diff --git a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java index 008edcda4..b8205a792 100644 --- a/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java +++ b/OpenKeychain-Test/src/test/java/org/sufficientlysecure/keychain/pgp/PgpEncryptDecryptTest.java @@ -438,6 +438,60 @@ public class PgpEncryptDecryptTest { } + @Test + public void testForeignEncoding () throws Exception { + String plaintext = "ウィキペディア"; + byte[] plaindata = plaintext.getBytes("iso-2022-jp"); + + { // some quick sanity checks + Assert.assertEquals(plaintext, new String(plaindata, "iso-2022-jp")); + Assert.assertNotEquals(plaintext, new String(plaindata, "utf-8")); + } + + byte[] ciphertext; + { // encrypt data with a given passphrase + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(plaindata); + + InputData data = new InputData(in, in.available()); + Builder b = new PgpSignEncrypt.Builder( + Robolectric.application, + new ProviderHelper(Robolectric.application), + null, // new DummyPassphraseCache(mPassphrase, 0L), + data, out); + + b.setEncryptionMasterKeyIds(new long[]{ mStaticRing1.getMasterKeyId() }); + b.setSymmetricEncryptionAlgorithm(PGPEncryptedData.AES_128); + // this only works with ascii armored output! + b.setEnableAsciiArmorOutput(true); + b.setCharset("iso-2022-jp"); + SignEncryptResult result = b.build().execute(); + Assert.assertTrue("encryption must succeed", result.success()); + + ciphertext = out.toByteArray(); + } + + { // decryption with provided passphrase should yield the same result + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(ciphertext); + InputData data = new InputData(in, in.available()); + + PgpDecryptVerify.Builder b = builderWithFakePassphraseCache(data, out, null, null, null); + b.setPassphrase(mKeyPhrase1); + DecryptVerifyResult result = b.build().execute(); + Assert.assertTrue("decryption with provided passphrase must succeed", result.success()); + Assert.assertArrayEquals("decrypted ciphertext should equal plaintext bytes", + out.toByteArray(), plaindata); + Assert.assertEquals("charset should be read correctly", + "iso-2022-jp", result.getCharset()); + Assert.assertEquals("decrypted ciphertext should equal plaintext", + new String(out.toByteArray(), result.getCharset()), plaintext); + Assert.assertNull("signature be empty", result.getSignatureResult()); + } + + } + private PgpDecryptVerify.Builder builderWithFakePassphraseCache ( InputData data, OutputStream out, final String passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java index d81577102..86b37fea6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/DecryptVerifyResult.java @@ -41,6 +41,9 @@ public class DecryptVerifyResult extends OperationResult { OpenPgpSignatureResult mSignatureResult; OpenPgpMetadata mDecryptMetadata; + // This holds the charset which was specified in the ascii armor, if specified + // https://tools.ietf.org/html/rfc4880#page56 + String mCharset; public long getKeyIdPassphraseNeeded() { return mKeyIdPassphraseNeeded; @@ -84,6 +87,14 @@ public class DecryptVerifyResult extends OperationResult { mDecryptMetadata = decryptMetadata; } + public String getCharset () { + return mCharset; + } + + public void setCharset(String charset) { + mCharset = charset; + } + public boolean isPending() { return (mResult & RESULT_PENDING) == RESULT_PENDING; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java index eba8f13af..5b28f0f5a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java @@ -564,6 +564,7 @@ public abstract class OperationResult implements Parcelable { MSG_DC_ASKIP_NO_KEY (LogLevel.DEBUG, R.string.msg_dc_askip_no_key), MSG_DC_ASKIP_NOT_ALLOWED (LogLevel.DEBUG, R.string.msg_dc_askip_not_allowed), MSG_DC_ASYM (LogLevel.DEBUG, R.string.msg_dc_asym), + MSG_DC_CHARSET (LogLevel.DEBUG, R.string.msg_dc_charset), MSG_DC_CLEAR_DATA (LogLevel.DEBUG, R.string.msg_dc_clear_data), MSG_DC_CLEAR_DECOMPRESS (LogLevel.DEBUG, R.string.msg_dc_clear_decompress), MSG_DC_CLEAR_META_FILE (LogLevel.DEBUG, R.string.msg_dc_clear_meta_file), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java index b58df085f..6c987f484 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java @@ -234,6 +234,22 @@ public class PgpDecryptVerify extends BaseOperation { boolean symmetricPacketFound = false; boolean anyPacketFound = false; + // If the input stream is armored, and there is a charset specified, take a note for later + // https://tools.ietf.org/html/rfc4880#page56 + String charset = null; + if (in instanceof ArmoredInputStream) { + for (String header : ((ArmoredInputStream) in).getArmorHeaders()) { + String[] pieces = header.split(":", 2); + if (pieces.length == 2 && "charset".equalsIgnoreCase(pieces[0])) { + charset = pieces[1].trim(); + break; + } + } + if (charset != null) { + log.add(LogType.MSG_DC_CHARSET, indent, charset); + } + } + // go through all objects and find one we can decrypt while (it.hasNext()) { Object obj = it.next(); @@ -550,6 +566,7 @@ public class PgpDecryptVerify extends BaseOperation { log.add(LogType.MSG_DC_OK_META_ONLY, indent); DecryptVerifyResult result = new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); + result.setCharset(charset); result.setDecryptMetadata(metadata); return result; } @@ -647,6 +664,7 @@ public class PgpDecryptVerify extends BaseOperation { new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log); result.setDecryptMetadata(metadata); result.setSignatureResult(signatureResultBuilder.build()); + result.setCharset(charset); return result; } @@ -807,7 +825,7 @@ public class PgpDecryptVerify extends BaseOperation { while ((ch = fIn.read()) >= 0) { bOut.write(ch); if (ch == '\r' || ch == '\n') { - lookAhead = readPassedEOL(bOut, ch, fIn); + lookAhead = readPastEOL(bOut, ch, fIn); break; } } @@ -824,7 +842,7 @@ public class PgpDecryptVerify extends BaseOperation { do { bOut.write(ch); if (ch == '\r' || ch == '\n') { - lookAhead = readPassedEOL(bOut, ch, fIn); + lookAhead = readPastEOL(bOut, ch, fIn); break; } } while ((ch = fIn.read()) >= 0); @@ -836,7 +854,7 @@ public class PgpDecryptVerify extends BaseOperation { return lookAhead; } - private static int readPassedEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn) + private static int readPastEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn) throws IOException { int lookAhead = fIn.read(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java index 3c3bcc890..c2fa811bd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -81,6 +81,7 @@ public class PgpSignEncrypt extends BaseOperation { private boolean mCleartextInput; private String mOriginalFilename; private boolean mFailOnMissingEncryptionKeyIds; + private String mCharset; private byte[] mNfcSignedHash = null; private Date mNfcCreationTimestamp = null; @@ -118,6 +119,7 @@ public class PgpSignEncrypt extends BaseOperation { this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp; this.mOriginalFilename = builder.mOriginalFilename; this.mFailOnMissingEncryptionKeyIds = builder.mFailOnMissingEncryptionKeyIds; + this.mCharset = builder.mCharset; } public static class Builder { @@ -145,6 +147,7 @@ public class PgpSignEncrypt extends BaseOperation { private byte[] mNfcSignedHash = null; private Date mNfcCreationTimestamp = null; private boolean mFailOnMissingEncryptionKeyIds = false; + private String mCharset = null; public Builder(Context context, ProviderHelper providerHelper, Progressable progressable, InputData data, OutputStream outStream) { @@ -211,6 +214,11 @@ public class PgpSignEncrypt extends BaseOperation { return this; } + public Builder setCharset(String charset) { + mCharset = charset; + return this; + } + /** * Also encrypt with the signing keyring * @@ -283,6 +291,10 @@ public class PgpSignEncrypt extends BaseOperation { if (mVersionHeader != null) { armorOut.setHeader("Version", mVersionHeader); } + // if we have a charset, put it in the header + if (mCharset != null) { + armorOut.setHeader("Charset", mCharset); + } out = armorOut; } else { out = mOutStream; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java index 9534cc49d..68677fb9c 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -557,6 +557,12 @@ public class OpenPgpService extends RemoteService { result.putExtra(OpenPgpApi.RESULT_METADATA, metadata); } } + + String charset = pgpResult.getCharset(); + if (charset != null) { + result.putExtra(OpenPgpApi.RESULT_CHARSET, charset); + } + } else { LogEntryParcel errorMsg = pgpResult.getLog().getLast(); throw new Exception(getString(errorMsg.mType.getMsgId())); 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 83ba64ce2..78333a8d8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -41,6 +41,8 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ShareHelper; +import java.io.UnsupportedEncodingException; + public class DecryptTextFragment extends DecryptFragment { public static final String ARG_CIPHERTEXT = "ciphertext"; @@ -194,7 +196,18 @@ public class DecryptTextFragment extends DecryptFragment { byte[] decryptedMessage = returnData .getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES); - mText.setText(new String(decryptedMessage)); + String displayMessage; + if (pgpResult.getCharset() != null) { + try { + displayMessage = new String(decryptedMessage, pgpResult.getCharset()); + } catch (UnsupportedEncodingException e) { + // if we can't decode properly, just fall back to utf-8 + displayMessage = new String(decryptedMessage); + } + } else { + displayMessage = new String(decryptedMessage); + } + mText.setText(displayMessage); pgpResult.createNotify(getActivity()).show(); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index b63ccec2d..a51420ba1 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -923,6 +923,7 @@ "Data not encrypted with known key, skipping…" "Data not encrypted with allowed key, skipping…" "Found block of asymmetrically encrypted data for key %s" + "Found charset header: '%s'" "Processing literal data" "Unpacking compressed data" "Filename: %s" -- cgit v1.2.3