aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2016-02-12 17:08:09 +0100
committerVincent Breitmoser <valodim@mugenguild.com>2016-02-22 17:03:24 +0100
commitbdae99c0847556dd8103f172fc1836eb83ae4c4a (patch)
tree9b3ada1bd23a546f477bd1e44ddc709e062e0c40 /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations
parent0784a0b4301b9bd15a80d135bdece19f44bc4258 (diff)
downloadopen-keychain-bdae99c0847556dd8103f172fc1836eb83ae4c4a.tar.gz
open-keychain-bdae99c0847556dd8103f172fc1836eb83ae4c4a.tar.bz2
open-keychain-bdae99c0847556dd8103f172fc1836eb83ae4c4a.zip
mime: try to decode with given charset or utf-8 while file is read
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java86
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/OperationResult.java4
2 files changed, 84 insertions, 6 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java
index bb8d6ad73..80f9d6368 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/InputDataOperation.java
@@ -23,6 +23,13 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import android.content.ClipDescription;
@@ -67,10 +74,15 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
*/
public class InputDataOperation extends BaseOperation<InputDataParcel> {
- final private byte[] buf = new byte[256];
+ private final byte[] buf = new byte[256];
+ private final ByteBuffer bufWrap;
+ private final CharBuffer dummyOutput;
public InputDataOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
super(context, providerHelper, progressable);
+
+ bufWrap = ByteBuffer.wrap(buf);
+ dummyOutput = CharBuffer.allocate(256);
}
Uri mSignedDataUri;
@@ -326,20 +338,82 @@ public class InputDataOperation extends BaseOperation<InputDataParcel> {
throw new IOException("Error getting file for writing!");
}
+ boolean isPossibleTextMimeType = ClipDescription.compareMimeTypes(mimeType, "application/octet-stream")
+ || ClipDescription.compareMimeTypes(mimeType, "application/x-download")
+ || ClipDescription.compareMimeTypes(mimeType, "text/*");
+
+ // If this data looks like text, we pipe the incoming data into a charset
+ // decoder, to see if the data is legal for the assumed charset.
+ String charset;
+ boolean charsetIsFaulty;
+ boolean charsetIsGuessed;
+ CharsetDecoder charsetDecoder = null;
+ if (isPossibleTextMimeType) {
+ charset = bd.getCharset();
+ // the charset defaults to us-ascii, but we want to default to utf-8
+ if (charset == null || "us-ascii".equals(charset)) {
+ charset = "utf-8";
+ charsetIsGuessed = true;
+ } else {
+ charsetIsGuessed = false;
+ }
+
+ try {
+ charsetDecoder = Charset.forName(charset).newDecoder();
+ charsetDecoder.onMalformedInput(CodingErrorAction.REPORT);
+ charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ charsetDecoder.reset();
+ charsetIsFaulty = false;
+ } catch (UnsupportedCharsetException e) {
+ charsetIsFaulty = true;
+ }
+ } else {
+ charsetIsFaulty = true;
+ charsetIsGuessed = false;
+ charset = null;
+ }
+
int totalLength = 0;
do {
totalLength += len;
out.write(buf, 0, len);
+
+ if (isPossibleTextMimeType && !charsetIsFaulty) {
+ bufWrap.rewind();
+ bufWrap.limit(len);
+ dummyOutput.rewind();
+ CoderResult result = charsetDecoder.decode(bufWrap, dummyOutput, false);
+ if (result.isError()) {
+ charsetIsFaulty = true;
+ }
+ }
} while ((len = is.read(buf)) > 0);
- log.add(LogType.MSG_DATA_MIME_LENGTH, 3, Long.toString(totalLength));
+ if (!charsetIsFaulty) {
+ bufWrap.rewind();
+ bufWrap.limit(0);
+ dummyOutput.rewind();
+ CoderResult result = charsetDecoder.decode(bufWrap, dummyOutput, true);
+ if (result.isError()) {
+ charsetIsFaulty = true;
+ }
+ }
- String charset = bd.getCharset();
- // the charset defaults to us-ascii, but we want to default to utf-8
- if ("us-ascii".equals(charset)) {
- charset = "utf-8";
+ if (isPossibleTextMimeType) {
+ if (charsetIsFaulty && charsetIsGuessed) {
+ log.add(LogType.MSG_DATA_MIME_CHARSET_UNKNOWN, 3, charset);
+ charset = null;
+ } else if (charsetIsFaulty) {
+ log.add(LogType.MSG_DATA_MIME_CHARSET_FAULTY, 3, charset);
+ } else if (charsetIsGuessed) {
+ log.add(LogType.MSG_DATA_MIME_CHARSET_GUESS, 3, charset);
+ } else {
+ log.add(LogType.MSG_DATA_MIME_CHARSET, 3, charset);
+ }
}
+ log.add(LogType.MSG_DATA_MIME_LENGTH, 3, Long.toString(totalLength));
+
OpenPgpMetadata metadata = new OpenPgpMetadata(mFilename, mimeType, 0L, totalLength, charset);
out.close();
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 f9c2db8e8..ec2fddbd0 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
@@ -860,6 +860,10 @@ public abstract class OperationResult implements Parcelable {
MSG_DATA_MIME_FROM_EXTENSION (LogLevel.DEBUG, R.string.msg_data_mime_from_extension),
MSG_DATA_MIME_FILENAME (LogLevel.DEBUG, R.string.msg_data_mime_filename),
MSG_DATA_MIME_LENGTH (LogLevel.DEBUG, R.string.msg_data_mime_length),
+ MSG_DATA_MIME_CHARSET (LogLevel.DEBUG, R.string.msg_data_mime_charset),
+ MSG_DATA_MIME_CHARSET_FAULTY (LogLevel.WARN, R.string.msg_data_mime_charset_faulty),
+ MSG_DATA_MIME_CHARSET_GUESS (LogLevel.DEBUG, R.string.msg_data_mime_charset_guess),
+ MSG_DATA_MIME_CHARSET_UNKNOWN (LogLevel.DEBUG, R.string.msg_data_mime_charset_unknown),
MSG_DATA_MIME (LogLevel.DEBUG, R.string.msg_data_mime),
MSG_DATA_MIME_OK (LogLevel.INFO, R.string.msg_data_mime_ok),
MSG_DATA_MIME_NONE (LogLevel.DEBUG, R.string.msg_data_mime_none),