Relaxed QP decoder

This commit is contained in:
M66B 2020-04-08 11:05:43 +02:00
parent 2711459f7b
commit 500fc5486e
2 changed files with 64 additions and 9 deletions

View File

@ -32,7 +32,6 @@ import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.BASE64DecoderStream; import com.sun.mail.util.BASE64DecoderStream;
import com.sun.mail.util.FolderClosedIOException; import com.sun.mail.util.FolderClosedIOException;
import com.sun.mail.util.MessageRemovedIOException; import com.sun.mail.util.MessageRemovedIOException;
import com.sun.mail.util.QDecoderStream;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
@ -1315,8 +1314,8 @@ public class MessageHelper {
if (p1.charset != null && p1.charset.equalsIgnoreCase(p2.charset) && if (p1.charset != null && p1.charset.equalsIgnoreCase(p2.charset) &&
p1.encoding != null && p1.encoding.equalsIgnoreCase(p2.encoding)) { p1.encoding != null && p1.encoding.equalsIgnoreCase(p2.encoding)) {
try { try {
byte[] b1 = decodeWord(p1.text, p1.encoding); byte[] b1 = decodeWord(p1.text, p1.encoding, p1.charset);
byte[] b2 = decodeWord(p2.text, p2.encoding); byte[] b2 = decodeWord(p2.text, p2.encoding, p2.charset);
byte[] b = new byte[b1.length + b2.length]; byte[] b = new byte[b1.length + b2.length];
System.arraycopy(b1, 0, b, 0, b1.length); System.arraycopy(b1, 0, b, 0, b1.length);
System.arraycopy(b2, 0, b, b1.length, b2.length); System.arraycopy(b2, 0, b, b1.length, b2.length);
@ -1340,16 +1339,18 @@ public class MessageHelper {
return sb.toString(); return sb.toString();
} }
static byte[] decodeWord(String word, String encoding) throws IOException { static byte[] decodeWord(String word, String encoding, String charset) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(ASCIIUtility.getBytes(word)); ByteArrayInputStream bis = new ByteArrayInputStream(ASCIIUtility.getBytes(word));
InputStream is; InputStream is;
if (encoding.equalsIgnoreCase("B")) if (encoding.equalsIgnoreCase("B"))
is = new BASE64DecoderStream(bis); is = new BASE64DecoderStream(bis);
else if (encoding.equalsIgnoreCase("Q")) else if (encoding.equalsIgnoreCase("Q"))
is = new QDecoderStream(bis); is = new QDecoderStreamEx(bis);
else else {
throw new UnsupportedEncodingException("Encoding=" + encoding); Log.e(new UnsupportedEncodingException("Encoding=" + encoding));
return word.getBytes(charset);
}
int count = bis.available(); int count = bis.available();
byte[] bytes = new byte[count]; byte[] bytes = new byte[count];
@ -1379,10 +1380,10 @@ public class MessageHelper {
return text; return text;
try { try {
return decodeMime(new String(decodeWord(text, encoding), charset)); return decodeMime(new String(decodeWord(text, encoding, charset), charset));
} catch (Throwable ex) { } catch (Throwable ex) {
String word = "=?" + charset + "?" + encoding + "?" + text + "?="; String word = "=?" + charset + "?" + encoding + "?" + text + "?=";
Log.w(new IllegalArgumentException(word, ex)); Log.e(new IllegalArgumentException(word, ex));
return word; return word;
} }
} }

View File

@ -0,0 +1,54 @@
package eu.faircode.email;
/*
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright 2018-2020 by Marcel Bokhorst (M66B)
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.QPDecoderStream;
import java.io.IOException;
import java.io.InputStream;
public class QDecoderStreamEx extends QPDecoderStream {
private Byte pushed = null;
public QDecoderStreamEx(InputStream in) {
super(in);
}
@Override
public int read() throws IOException {
int c = (pushed == null ? in.read() : pushed);
pushed = null;
if (c == '_')
return ' ';
else if (c == '=') {
ba[0] = (byte) in.read();
ba[1] = (byte) in.read();
try {
return ASCIIUtility.parseInt(ba, 0, 2, 16);
} catch (NumberFormatException ex) {
Log.w(ex);
pushed = ba[1];
return ba[0];
}
} else
return c;
}
}