mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-12 05:00:22 -05:00
Merge branch 'development' of github.com:open-keychain/open-keychain into development
This commit is contained in:
commit
e77f9a5351
@ -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 (
|
private PgpDecryptVerify.Builder builderWithFakePassphraseCache (
|
||||||
InputData data, OutputStream out,
|
InputData data, OutputStream out,
|
||||||
final String passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
|
final String passphrase, final Long checkMasterKeyId, final Long checkSubKeyId) {
|
||||||
|
@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
|
|||||||
import org.sufficientlysecure.keychain.keyimport.Keyserver;
|
import org.sufficientlysecure.keychain.keyimport.Keyserver;
|
||||||
import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException;
|
import org.sufficientlysecure.keychain.keyimport.Keyserver.AddKeyException;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.ConsolidateResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.ExportResult;
|
import org.sufficientlysecure.keychain.operations.results.ExportResult;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
|
import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
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.OperationResult.OperationLog;
|
||||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
|
import org.sufficientlysecure.keychain.operations.results.SaveKeyringResult;
|
||||||
|
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.util.FileHelper;
|
import org.sufficientlysecure.keychain.util.FileHelper;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
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 org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@ -58,6 +62,7 @@ import java.io.IOException;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/** An operation class which implements high level import and export
|
/** An operation class which implements high level import and export
|
||||||
@ -123,6 +128,35 @@ public class ImportExportOperation extends BaseOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImportKeyResult importKeyRings(List<ParcelableKeyRing> entries, String keyServerUri) {
|
||||||
|
|
||||||
|
Iterator<ParcelableKeyRing> it = entries.iterator();
|
||||||
|
int numEntries = entries.size();
|
||||||
|
|
||||||
|
return importKeyRings(it, numEntries, keyServerUri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportKeyResult importKeyRings(ParcelableFileCache<ParcelableKeyRing> cache, String keyServerUri) {
|
||||||
|
|
||||||
|
// get entries from cached file
|
||||||
|
try {
|
||||||
|
IteratorWithSize<ParcelableKeyRing> 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<ParcelableKeyRing> entries, int num, String keyServerUri) {
|
public ImportKeyResult importKeyRings(Iterator<ParcelableKeyRing> entries, int num, String keyServerUri) {
|
||||||
updateProgress(R.string.progress_importing, 0, 100);
|
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 there aren't even any keys, do nothing here.
|
||||||
if (entries == null || !entries.hasNext()) {
|
if (entries == null || !entries.hasNext()) {
|
||||||
return new ImportKeyResult(
|
return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, log);
|
||||||
ImportKeyResult.RESULT_FAIL_NOTHING, log, 0, 0, 0, 0,
|
|
||||||
new long[]{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int newKeys = 0, oldKeys = 0, badKeys = 0, secret = 0;
|
int newKeys = 0, oldKeys = 0, badKeys = 0, secret = 0;
|
||||||
@ -293,6 +325,16 @@ public class ImportExportOperation extends BaseOperation {
|
|||||||
position++;
|
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
|
// convert to long array
|
||||||
long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()];
|
long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()];
|
||||||
for (int i = 0; i < importedMasterKeyIds.size(); ++i) {
|
for (int i = 0; i < importedMasterKeyIds.size(); ++i) {
|
||||||
|
@ -41,6 +41,9 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
|
|
||||||
OpenPgpSignatureResult mSignatureResult;
|
OpenPgpSignatureResult mSignatureResult;
|
||||||
OpenPgpMetadata mDecryptMetadata;
|
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() {
|
public long getKeyIdPassphraseNeeded() {
|
||||||
return mKeyIdPassphraseNeeded;
|
return mKeyIdPassphraseNeeded;
|
||||||
@ -84,6 +87,14 @@ public class DecryptVerifyResult extends OperationResult {
|
|||||||
mDecryptMetadata = decryptMetadata;
|
mDecryptMetadata = decryptMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getCharset () {
|
||||||
|
return mCharset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCharset(String charset) {
|
||||||
|
mCharset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPending() {
|
public boolean isPending() {
|
||||||
return (mResult & RESULT_PENDING) == RESULT_PENDING;
|
return (mResult & RESULT_PENDING) == RESULT_PENDING;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,10 @@ public class ImportKeyResult extends OperationResult {
|
|||||||
mImportedMasterKeyIds = source.createLongArray();
|
mImportedMasterKeyIds = source.createLongArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImportKeyResult(int result, OperationLog log) {
|
||||||
|
this(result, log, 0, 0, 0, 0, new long[] { });
|
||||||
|
}
|
||||||
|
|
||||||
public ImportKeyResult(int result, OperationLog log,
|
public ImportKeyResult(int result, OperationLog log,
|
||||||
int newKeys, int updatedKeys, int badKeys, int secret,
|
int newKeys, int updatedKeys, int badKeys, int secret,
|
||||||
long[] importedMasterKeyIds) {
|
long[] importedMasterKeyIds) {
|
||||||
|
@ -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_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_ASKIP_NOT_ALLOWED (LogLevel.DEBUG, R.string.msg_dc_askip_not_allowed),
|
||||||
MSG_DC_ASYM (LogLevel.DEBUG, R.string.msg_dc_asym),
|
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_DATA (LogLevel.DEBUG, R.string.msg_dc_clear_data),
|
||||||
MSG_DC_CLEAR_DECOMPRESS (LogLevel.DEBUG, R.string.msg_dc_clear_decompress),
|
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),
|
MSG_DC_CLEAR_META_FILE (LogLevel.DEBUG, R.string.msg_dc_clear_meta_file),
|
||||||
@ -654,6 +655,7 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_IMPORT_FINGERPRINT_ERROR (LogLevel.ERROR, R.string.msg_import_fingerprint_error),
|
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_FINGERPRINT_OK (LogLevel.DEBUG, R.string.msg_import_fingerprint_ok),
|
||||||
MSG_IMPORT_ERROR (LogLevel.ERROR, R.string.msg_import_error),
|
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_PARTIAL (LogLevel.ERROR, R.string.msg_import_partial),
|
||||||
MSG_IMPORT_SUCCESS (LogLevel.OK, R.string.msg_import_success),
|
MSG_IMPORT_SUCCESS (LogLevel.OK, R.string.msg_import_success),
|
||||||
|
|
||||||
|
@ -234,6 +234,22 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
boolean symmetricPacketFound = false;
|
boolean symmetricPacketFound = false;
|
||||||
boolean anyPacketFound = 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
|
// go through all objects and find one we can decrypt
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Object obj = it.next();
|
Object obj = it.next();
|
||||||
@ -550,6 +566,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
log.add(LogType.MSG_DC_OK_META_ONLY, indent);
|
log.add(LogType.MSG_DC_OK_META_ONLY, indent);
|
||||||
DecryptVerifyResult result =
|
DecryptVerifyResult result =
|
||||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||||
|
result.setCharset(charset);
|
||||||
result.setDecryptMetadata(metadata);
|
result.setDecryptMetadata(metadata);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -647,6 +664,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
new DecryptVerifyResult(DecryptVerifyResult.RESULT_OK, log);
|
||||||
result.setDecryptMetadata(metadata);
|
result.setDecryptMetadata(metadata);
|
||||||
result.setSignatureResult(signatureResultBuilder.build());
|
result.setSignatureResult(signatureResultBuilder.build());
|
||||||
|
result.setCharset(charset);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -807,7 +825,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
while ((ch = fIn.read()) >= 0) {
|
while ((ch = fIn.read()) >= 0) {
|
||||||
bOut.write(ch);
|
bOut.write(ch);
|
||||||
if (ch == '\r' || ch == '\n') {
|
if (ch == '\r' || ch == '\n') {
|
||||||
lookAhead = readPassedEOL(bOut, ch, fIn);
|
lookAhead = readPastEOL(bOut, ch, fIn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -824,7 +842,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
do {
|
do {
|
||||||
bOut.write(ch);
|
bOut.write(ch);
|
||||||
if (ch == '\r' || ch == '\n') {
|
if (ch == '\r' || ch == '\n') {
|
||||||
lookAhead = readPassedEOL(bOut, ch, fIn);
|
lookAhead = readPastEOL(bOut, ch, fIn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while ((ch = fIn.read()) >= 0);
|
} while ((ch = fIn.read()) >= 0);
|
||||||
@ -836,7 +854,7 @@ public class PgpDecryptVerify extends BaseOperation {
|
|||||||
return lookAhead;
|
return lookAhead;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int readPassedEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
|
private static int readPastEOL(ByteArrayOutputStream bOut, int lastCh, InputStream fIn)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
int lookAhead = fIn.read();
|
int lookAhead = fIn.read();
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ public class PgpSignEncrypt extends BaseOperation {
|
|||||||
private boolean mCleartextInput;
|
private boolean mCleartextInput;
|
||||||
private String mOriginalFilename;
|
private String mOriginalFilename;
|
||||||
private boolean mFailOnMissingEncryptionKeyIds;
|
private boolean mFailOnMissingEncryptionKeyIds;
|
||||||
|
private String mCharset;
|
||||||
|
|
||||||
private byte[] mNfcSignedHash = null;
|
private byte[] mNfcSignedHash = null;
|
||||||
private Date mNfcCreationTimestamp = null;
|
private Date mNfcCreationTimestamp = null;
|
||||||
@ -118,6 +119,7 @@ public class PgpSignEncrypt extends BaseOperation {
|
|||||||
this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp;
|
this.mNfcCreationTimestamp = builder.mNfcCreationTimestamp;
|
||||||
this.mOriginalFilename = builder.mOriginalFilename;
|
this.mOriginalFilename = builder.mOriginalFilename;
|
||||||
this.mFailOnMissingEncryptionKeyIds = builder.mFailOnMissingEncryptionKeyIds;
|
this.mFailOnMissingEncryptionKeyIds = builder.mFailOnMissingEncryptionKeyIds;
|
||||||
|
this.mCharset = builder.mCharset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
@ -145,6 +147,7 @@ public class PgpSignEncrypt extends BaseOperation {
|
|||||||
private byte[] mNfcSignedHash = null;
|
private byte[] mNfcSignedHash = null;
|
||||||
private Date mNfcCreationTimestamp = null;
|
private Date mNfcCreationTimestamp = null;
|
||||||
private boolean mFailOnMissingEncryptionKeyIds = false;
|
private boolean mFailOnMissingEncryptionKeyIds = false;
|
||||||
|
private String mCharset = null;
|
||||||
|
|
||||||
public Builder(Context context, ProviderHelper providerHelper, Progressable progressable,
|
public Builder(Context context, ProviderHelper providerHelper, Progressable progressable,
|
||||||
InputData data, OutputStream outStream) {
|
InputData data, OutputStream outStream) {
|
||||||
@ -211,6 +214,11 @@ public class PgpSignEncrypt extends BaseOperation {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setCharset(String charset) {
|
||||||
|
mCharset = charset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Also encrypt with the signing keyring
|
* Also encrypt with the signing keyring
|
||||||
*
|
*
|
||||||
@ -283,6 +291,10 @@ public class PgpSignEncrypt extends BaseOperation {
|
|||||||
if (mVersionHeader != null) {
|
if (mVersionHeader != null) {
|
||||||
armorOut.setHeader("Version", mVersionHeader);
|
armorOut.setHeader("Version", mVersionHeader);
|
||||||
}
|
}
|
||||||
|
// if we have a charset, put it in the header
|
||||||
|
if (mCharset != null) {
|
||||||
|
armorOut.setHeader("Charset", mCharset);
|
||||||
|
}
|
||||||
out = armorOut;
|
out = armorOut;
|
||||||
} else {
|
} else {
|
||||||
out = mOutStream;
|
out = mOutStream;
|
||||||
|
@ -557,6 +557,12 @@ public class OpenPgpService extends RemoteService {
|
|||||||
result.putExtra(OpenPgpApi.RESULT_METADATA, metadata);
|
result.putExtra(OpenPgpApi.RESULT_METADATA, metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String charset = pgpResult.getCharset();
|
||||||
|
if (charset != null) {
|
||||||
|
result.putExtra(OpenPgpApi.RESULT_CHARSET, charset);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
|
LogEntryParcel errorMsg = pgpResult.getLog().getLast();
|
||||||
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
throw new Exception(getString(errorMsg.mType.getMsgId()));
|
||||||
|
@ -403,49 +403,28 @@ public class KeychainIntentService extends IntentService implements Progressable
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ACTION_IMPORT_KEYRING:
|
case ACTION_IMPORT_KEYRING: {
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
String keyServer = data.getString(IMPORT_KEY_SERVER);
|
String keyServer = data.getString(IMPORT_KEY_SERVER);
|
||||||
Iterator<ParcelableKeyRing> entries;
|
|
||||||
int numEntries;
|
|
||||||
if (data.containsKey(IMPORT_KEY_LIST)) {
|
|
||||||
// get entries from intent
|
|
||||||
ArrayList<ParcelableKeyRing> list = data.getParcelableArrayList(IMPORT_KEY_LIST);
|
ArrayList<ParcelableKeyRing> list = data.getParcelableArrayList(IMPORT_KEY_LIST);
|
||||||
entries = list.iterator();
|
|
||||||
numEntries = list.size();
|
|
||||||
} else {
|
|
||||||
// get entries from cached file
|
|
||||||
ParcelableFileCache<ParcelableKeyRing> cache =
|
ParcelableFileCache<ParcelableKeyRing> cache =
|
||||||
new ParcelableFileCache<>(this, "key_import.pcl");
|
new ParcelableFileCache<>(this, "key_import.pcl");
|
||||||
IteratorWithSize<ParcelableKeyRing> it = cache.readCache();
|
|
||||||
entries = it;
|
|
||||||
numEntries = it.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operation
|
// Operation
|
||||||
ImportExportOperation importExportOperation = new ImportExportOperation(
|
ImportExportOperation importExportOperation = new ImportExportOperation(
|
||||||
this, providerHelper, this, mActionCanceled);
|
this, providerHelper, this, mActionCanceled);
|
||||||
ImportKeyResult result = importExportOperation.importKeyRings(entries, numEntries, keyServer);
|
// Either list or cache must be null, no guarantees otherwise.
|
||||||
|
ImportKeyResult result = list != null
|
||||||
// Special: consolidate on secret key import (cannot be cancelled!)
|
? importExportOperation.importKeyRings(list, keyServer)
|
||||||
if (result.mSecret > 0) {
|
: importExportOperation.importKeyRings(cache, keyServer);
|
||||||
// TODO move this into the import operation
|
|
||||||
providerHelper.consolidateDatabaseStep1(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special: make sure new data is synced into contacts
|
|
||||||
ContactSyncAdapterService.requestSync();
|
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
|
sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, result);
|
||||||
} catch (Exception e) {
|
|
||||||
sendErrorToHandler(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
case ACTION_SIGN_ENCRYPT:
|
case ACTION_SIGN_ENCRYPT:
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -41,6 +41,8 @@ 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;
|
import org.sufficientlysecure.keychain.util.ShareHelper;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
public class DecryptTextFragment extends DecryptFragment {
|
public class DecryptTextFragment extends DecryptFragment {
|
||||||
public static final String ARG_CIPHERTEXT = "ciphertext";
|
public static final String ARG_CIPHERTEXT = "ciphertext";
|
||||||
|
|
||||||
@ -194,7 +196,18 @@ public class DecryptTextFragment extends DecryptFragment {
|
|||||||
|
|
||||||
byte[] decryptedMessage = returnData
|
byte[] decryptedMessage = returnData
|
||||||
.getByteArray(KeychainIntentService.RESULT_DECRYPTED_BYTES);
|
.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();
|
pgpResult.createNotify(getActivity()).show();
|
||||||
|
|
||||||
|
@ -39,18 +39,6 @@ import java.util.ArrayList;
|
|||||||
public class ImportKeysListLoader
|
public class ImportKeysListLoader
|
||||||
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
|
||||||
|
|
||||||
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 Context mContext;
|
||||||
final InputData mInputData;
|
final InputData mInputData;
|
||||||
|
|
||||||
|
@ -923,6 +923,7 @@
|
|||||||
<string name="msg_dc_askip_no_key">"Data not encrypted with known key, skipping…"</string>
|
<string name="msg_dc_askip_no_key">"Data not encrypted with known key, skipping…"</string>
|
||||||
<string name="msg_dc_askip_not_allowed">"Data not encrypted with allowed key, skipping…"</string>
|
<string name="msg_dc_askip_not_allowed">"Data not encrypted with allowed key, skipping…"</string>
|
||||||
<string name="msg_dc_asym">"Found block of asymmetrically encrypted data for key %s"</string>
|
<string name="msg_dc_asym">"Found block of asymmetrically encrypted data for key %s"</string>
|
||||||
|
<string name="msg_dc_charset">"Found charset header: '%s'"</string>
|
||||||
<string name="msg_dc_clear_data">"Processing literal data"</string>
|
<string name="msg_dc_clear_data">"Processing literal data"</string>
|
||||||
<string name="msg_dc_clear_decompress">"Unpacking compressed data"</string>
|
<string name="msg_dc_clear_decompress">"Unpacking compressed data"</string>
|
||||||
<string name="msg_dc_clear_meta_file">"Filename: %s"</string>
|
<string name="msg_dc_clear_meta_file">"Filename: %s"</string>
|
||||||
@ -1021,6 +1022,7 @@
|
|||||||
<string name="msg_import_fingerprint_ok">"Fingerprint check OK"</string>
|
<string name="msg_import_fingerprint_ok">"Fingerprint check OK"</string>
|
||||||
<string name="msg_import_merge">"Merging retrieved data"</string>
|
<string name="msg_import_merge">"Merging retrieved data"</string>
|
||||||
<string name="msg_import_error">"Import operation failed!"</string>
|
<string name="msg_import_error">"Import operation failed!"</string>
|
||||||
|
<string name="msg_import_error_io">"Import operation failed due to i/o error!"</string>
|
||||||
<string name="msg_import_partial">"Import operation successful, with errors!"</string>
|
<string name="msg_import_partial">"Import operation successful, with errors!"</string>
|
||||||
<string name="msg_import_success">"Import operation successful!"</string>
|
<string name="msg_import_success">"Import operation successful!"</string>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user