This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-mime4j.git
The following commit(s) were added to refs/heads/master by this push: new ff415b3a MIME4J-328 Fix DecoderUtil split point (#101) ff415b3a is described below commit ff415b3a664066818b7e9ed1ad65f36d9e1fd0f2 Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Mon Apr 29 14:29:19 2024 +0200 MIME4J-328 Fix DecoderUtil split point (#101) Huge thanks to Chung dae hyun --- .../org/apache/james/mime4j/codec/DecoderUtil.java | 62 ++++++++++++++++++---- .../apache/james/mime4j/codec/DecoderUtilTest.java | 7 +++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java b/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java index 14a981dd..5526b8fc 100644 --- a/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java +++ b/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java @@ -19,6 +19,7 @@ package org.apache.james.mime4j.codec; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.ref.SoftReference; @@ -28,7 +29,6 @@ import java.util.Map; import org.apache.james.mime4j.io.InputStreams; import org.apache.james.mime4j.util.BufferRecycler; -import org.apache.james.mime4j.util.ByteArrayBuffer; import org.apache.james.mime4j.util.CharsetUtil; import org.apache.james.mime4j.util.RecycledByteArrayBuffer; @@ -122,6 +122,10 @@ public class DecoderUtil { return new String(decodedBytes, charset); } + static byte[] decodeByteAryB(String encodedText, DecodeMonitor monitor) throws UnsupportedEncodingException { + return decodeBase64(encodedText, monitor); + } + /** * Decodes an encoded text encoded with the 'Q' encoding (described in * RFC 2047) found in a header field body. @@ -140,6 +144,10 @@ public class DecoderUtil { return new String(decodedBytes, charset); } + static byte[] decodeByteAryQ(String encodedText, DecodeMonitor monitor) throws UnsupportedEncodingException { + return decodeQuotedPrintable(replaceUnderscores(encodedText), monitor); + } + static String decodeEncodedWords(String body) { return decodeEncodedWords(body, DecodeMonitor.SILENT); } @@ -208,8 +216,11 @@ public class DecoderUtil { Map<Charset, Charset> charsetOverrides) throws IllegalArgumentException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); StringBuilder sb = new StringBuilder(); int position = 0; + String mimeCharset =""; + String encoding =""; while (position < body.length()) { int startPattern = body.indexOf("=?", position); @@ -217,6 +228,7 @@ public class DecoderUtil { if (position == 0) { return body; } + appendStringBuffer(fallback, charsetOverrides, out, sb, mimeCharset); sb.append(body, position, body.length()); break; } @@ -227,29 +239,48 @@ public class DecoderUtil { if (charsetEnd < 0 || encodingEnd < 0 || encodedTextEnd < 0) { // Invalid pattern + appendStringBuffer(fallback, charsetOverrides, out, sb, mimeCharset); sb.append(body, position, startPattern + 2); position = startPattern + 2; } else if (encodingEnd == encodedTextEnd) { + appendStringBuffer(fallback, charsetOverrides, out, sb, mimeCharset); sb.append(body, position, Math.min(encodedTextEnd + 2, body.length())); position = encodedTextEnd +2; } else { String separator = body.substring(position, startPattern); if ((!CharsetUtil.isWhitespace(separator) || position == 0) && !separator.isEmpty()) { + appendStringBuffer(fallback, charsetOverrides, out, sb, mimeCharset); sb.append(separator); } - String mimeCharset = body.substring(startPattern + 2, charsetEnd); - String encoding = body.substring(charsetEnd + 1, encodingEnd); + String mimeCurCharset = body.substring(startPattern + 2, charsetEnd); + String curEncoding = body.substring(charsetEnd + 1, encodingEnd); String encodedText = body.substring(encodingEnd + 1, encodedTextEnd); + if (!mimeCharset.isEmpty() && !mimeCurCharset.equals(mimeCharset)){ + appendStringBuffer(fallback, charsetOverrides, out, sb, mimeCharset); + } + + if (!encoding.isEmpty() && !curEncoding.equals(encoding)){ + appendStringBuffer(fallback, charsetOverrides, out, sb, mimeCharset); + } + + mimeCharset=mimeCurCharset; + encoding=curEncoding; + if (encodedText.isEmpty()) { position = encodedTextEnd + 2; continue; } - String decoded; - decoded = tryDecodeEncodedWord(mimeCharset, encoding, encodedText, monitor, fallback, charsetOverrides); + byte []decoded; + + decoded = tryDecodeEncodedWord(mimeCurCharset, curEncoding, encodedText, monitor, fallback, charsetOverrides); if (decoded != null) { - if (!CharsetUtil.isWhitespace(decoded) && !decoded.isEmpty()) { - sb.append(decoded); + if (0 < decoded.length) { + try { + out.write(decoded); + } catch (IOException e) { + throw new RuntimeException(e); + } } } else { sb.append(body, startPattern, encodedTextEnd + 2); @@ -257,11 +288,22 @@ public class DecoderUtil { position = encodedTextEnd + 2; } } + appendStringBuffer(fallback, charsetOverrides, out, sb,mimeCharset); + return sb.toString(); } + private static void appendStringBuffer(Charset fallback, Map<Charset, Charset> charsetOverrides, ByteArrayOutputStream out, StringBuilder sb, String mimeCharset) { + if (0 < out.size()) { + byte[] byTemp = out.toByteArray(); + Charset charset = lookupCharset(mimeCharset, fallback, charsetOverrides); + sb.append(new String(byTemp, charset)); + out.reset(); + } + } + // return null on error - private static String tryDecodeEncodedWord( + private static byte[] tryDecodeEncodedWord( final String mimeCharset, final String encoding, final String encodedText, @@ -283,9 +325,9 @@ public class DecoderUtil { try { if (encoding.equalsIgnoreCase("Q")) { - return DecoderUtil.decodeQ(encodedText, charset.name(), monitor); + return decodeByteAryQ(encodedText, monitor); } else if (encoding.equalsIgnoreCase("B")) { - return DecoderUtil.decodeB(encodedText, charset.name(), monitor); + return decodeByteAryB(encodedText, monitor); } else { monitor(monitor, mimeCharset, encoding, encodedText, "leaving word encoded", "Warning: Unknown encoding in encoded word"); diff --git a/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java b/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java index 6a76d99d..e4f5c644 100644 --- a/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java +++ b/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java @@ -35,6 +35,13 @@ public class DecoderUtilTest { Assert.assertEquals("This is the plain text message!", s); } + @Test + public void testDoubleLineBEncoding() { + String s = DecoderUtil.decodeEncodedWords("=?utf-8?B?W1NQQU1dIFJlOiBbbWNsb3VkLWJhcmlzdGFdIO2BtOudvOyasOuTnOuwlOumrOyKpO2DgCA37LCoIO2WieyCrC3rsJztkQ==?=\n" + + "=?utf-8?B?nOyekOujjCDtj6zrqacg6rO17Jyg?= ", DecodeMonitor.STRICT); + Assert.assertEquals("[SPAM] Re: [mcloud-barista] 클라우드바리스타 7차 행사-발표자료 포멧 공유 ", s); + } + @Test public void testDecodeQ() throws UnsupportedEncodingException { String s = DecoderUtil.decodeQ("=e1_=e2=09=E3_=E4_", "ISO8859-1", DecodeMonitor.STRICT); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org