diff options
| author | Dominik Schürmann <dominik@dominikschuermann.de> | 2015-01-27 09:46:42 +0100 | 
|---|---|---|
| committer | Dominik Schürmann <dominik@dominikschuermann.de> | 2015-01-27 09:46:42 +0100 | 
| commit | e8780b4410c4e4a45f08b4002722b32f0d22d279 (patch) | |
| tree | 431846d5aba6b86a7a7ed3afd99976b9201dd471 /OpenKeychain/src/main | |
| parent | fd29d27e61e531378f0c37c78028fb2e86989dea (diff) | |
| parent | e77f9a535119f25b0f3ad31ef8065db18ceddff7 (diff) | |
| download | open-keychain-e8780b4410c4e4a45f08b4002722b32f0d22d279.tar.gz open-keychain-e8780b4410c4e4a45f08b4002722b32f0d22d279.tar.bz2 open-keychain-e8780b4410c4e4a45f08b4002722b32f0d22d279.zip | |
Merge branch 'development' into detached-sigs-api
Conflicts:
	OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java
Diffstat (limited to 'OpenKeychain/src/main')
11 files changed, 133 insertions, 57 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<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) {          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/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/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..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), @@ -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_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/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 5282deca4..060db96b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncrypt.java @@ -83,6 +83,7 @@ public class PgpSignEncrypt extends BaseOperation {      private boolean mDetachedSignature;      private String mOriginalFilename;      private boolean mFailOnMissingEncryptionKeyIds; +    private String mCharset;      private byte[] mNfcSignedHash = null;      private Date mNfcCreationTimestamp = null; @@ -121,6 +122,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 { @@ -149,6 +151,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) { @@ -215,6 +218,11 @@ public class PgpSignEncrypt extends BaseOperation {              return this;          } +        public Builder setCharset(String charset) { +            mCharset = charset; +            return this; +        } +          /**           * Also encrypt with the signing keyring           * @@ -286,6 +294,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 6c36e1ab8..e1d15e2d3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/OpenPgpService.java @@ -563,6 +563,11 @@ public class OpenPgpService extends RemoteService {                          }                      } +                    String charset = pgpResult.getCharset(); +                    if (charset != null) { +                        result.putExtra(OpenPgpApi.RESULT_CHARSET, charset); +                    } +                      result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);                      return result;                  } else { 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 bcb5da277..515711d1f 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<ParcelableKeyRing> entries; -                    int numEntries; -                    if (data.containsKey(IMPORT_KEY_LIST)) { -                        // get entries from intent -                        ArrayList<ParcelableKeyRing> list = data.getParcelableArrayList(IMPORT_KEY_LIST); -                        entries = list.iterator(); -                        numEntries = list.size(); -                    } else { -                        // get entries from cached file -                        ParcelableFileCache<ParcelableKeyRing> cache = -                                new ParcelableFileCache<>(this, "key_import.pcl"); -                        IteratorWithSize<ParcelableKeyRing> 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<ParcelableKeyRing> list = data.getParcelableArrayList(IMPORT_KEY_LIST); +                ParcelableFileCache<ParcelableKeyRing> 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/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/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<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 InputData mInputData; diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 6c4ba7b08..dfb675a37 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -924,6 +924,7 @@      <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_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_decompress">"Unpacking compressed data"</string>      <string name="msg_dc_clear_meta_file">"Filename: %s"</string> @@ -1022,6 +1023,7 @@      <string name="msg_import_fingerprint_ok">"Fingerprint check OK"</string>      <string name="msg_import_merge">"Merging retrieved data"</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_success">"Import operation successful!"</string> | 
