[Git][java-team/apache-mime4j][master] 4 commits: New upstream version 0.8.12

Tony Mancill (@tmancill) gitlab at salsa.debian.org
Sun Dec 29 20:58:51 GMT 2024



Tony Mancill pushed to branch master at Debian Java Maintainers / apache-mime4j


Commits:
45594b1f by tony mancill at 2024-12-29T10:55:15-08:00
New upstream version 0.8.12
- - - - -
aedbe6d1 by tony mancill at 2024-12-29T10:55:15-08:00
Update upstream source from tag 'upstream/0.8.12'

Update to upstream version '0.8.12'
with Debian dir 0403fcf04741cee0ae520459f2763ec0c4db8234
- - - - -
964d22b6 by tony mancill at 2024-12-29T10:56:21-08:00
Bump Standards-Version to 4.7.0

- - - - -
cb092a92 by tony mancill at 2024-12-29T10:56:49-08:00
Prepare changelog for upload

- - - - -


28 changed files:

- CHANGELOG.md
- README.adoc
- assemble/pom.xml
- benchmark/pom.xml
- core/pom.xml
- core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java
- core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
- core/src/main/java/org/apache/james/mime4j/util/CharsetUtil.java
- core/src/main/java/org/apache/james/mime4j/util/ContentUtil.java
- core/src/main/java/org/apache/james/mime4j/util/MimeUtil.java
- core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java
- core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
- core/src/test/java/org/apache/james/mime4j/util/MimeUtilTest.java
- debian/changelog
- debian/control
- doap_James_Mime4j.rdf
- dom/pom.xml
- dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressParser.java
- dom/src/test/java/org/apache/james/mime4j/field/FieldsTest.java
- dom/src/test/java/org/apache/james/mime4j/field/LenientContentDispositionFieldTest.java
- dom/src/test/java/org/apache/james/mime4j/field/UnstructuredFieldTest.java
- dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
- examples/pom.xml
- + james-logo.png
- james-utils/pom.xml
- mbox/pom.xml
- pom.xml
- storage/pom.xml


Changes:

=====================================
CHANGELOG.md
=====================================
@@ -3,7 +3,9 @@ All notable changes to this project will be documented in this file.
 
 The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
 
-## [0.8.10] - 2024-01-09
+## [0.8.11] - 2024-03-05
+
+ - MIME4J-326 SILENT monitor for header decoding
 
 ## [0.8.10] - 2024-02-22
 


=====================================
README.adoc
=====================================
@@ -5,7 +5,7 @@ image:https://img.shields.io/badge/Join%20us-Mailing%20lists-purple.svg[link="ht
 link:https://gitter.im/apache/james-project[image:https://badges.gitter.im/apache/james-project.svg[Join the chat at link:https://gitter.im/apache/james-project]]
 image:https://img.shields.io/badge/CI-Jenkins-blue.svg[link="https://ci-builds.apache.org/job/james/job/ApacheJames-Mime4J/"]
 image:https://img.shields.io/badge/Documentation-green.svg[link="https://james.apache.org/mime4j/index.html"]
-image:https://img.shields.io/badge/Downloads-0.8.10-yellow.svg[link="https://james.apache.org/download.cgi#Apache_Mime4J"]
+image:https://img.shields.io/badge/Downloads-0.8.11-yellow.svg[link="https://james.apache.org/download.cgi#Apache_Mime4J"]
 image:https://img.shields.io/badge/Tickets-JIRA-blue.svg[link="https://issues.apache.org/jira/projects/MIME4J/issues"]
 image:https://img.shields.io/badge/License-ApacheV2-orange.svg[link="https://www.apache.org/licenses/"]
 image:https://img.shields.io/badge/Latests-news-red.svg[link="https://james.apache.org/index.html#posts"]
@@ -55,7 +55,7 @@ Add this maven dependency to import MIME4J core:
 <dependency>
     <groupId>org.apache.james</groupId>
     <artifactId>apache-mime4j-core</artifactId>
-    <version>0.8.10</version>
+    <version>0.8.11</version>
 </dependency>
 ....
 
@@ -65,7 +65,7 @@ Add this maven dependency to import MIME4J dom:
 <dependency>
     <groupId>org.apache.james</groupId>
     <artifactId>apache-mime4j-dom</artifactId>
-    <version>0.8.10</version>
+    <version>0.8.11</version>
 </dependency>
 ....
 ====


=====================================
assemble/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>apache-mime4j-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
benchmark/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>apache-mime4j-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
core/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>apache-mime4j-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
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");


=====================================
core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
=====================================
@@ -195,12 +195,6 @@ public class RawFieldParser {
      *  is not delimited by any character.
      */
     public String parseValue(final ByteSequence buf, final ParserCursor cursor, final BitSet delimiters) {
-        if (!CharsetUtil.isASCII(buf)) {
-            String value = parseUtf8Filename(buf);
-            if (value != null)
-                return value;
-        }
-
         StringBuilder dst = new StringBuilder();
         boolean whitespace = false;
         while (!cursor.atEnd()) {
@@ -229,25 +223,6 @@ public class RawFieldParser {
         return dst.toString();
     }
 
-    /**
-     * Special case for parsing {@code filename} attribute in nonstandard encoding like:
-     * {@code Content-Disposition: attachment; filename="УПД ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ "СТАНЦИЯ ВИРТУАЛЬНАЯ" 01-05-21.pdf"}
-     * 
-     * @param buf field raw.
-     * @return filename value or {@code null}.
-     */
-    private String parseUtf8Filename(ByteSequence buf) {
-        final String value = new String(buf.toByteArray(), StandardCharsets.UTF_8);
-
-        final String prefix = "filename=\"";
-        final int pos = value.indexOf(prefix);
-        if (pos > 0) {
-            return value.substring(pos + prefix.length(), value.length() - 1);
-        }
-        
-        return null;
-    }
-
     /**
      * Skips semantically insignificant whitespace characters and moves the cursor to the closest
      * non-whitespace character.
@@ -379,16 +354,22 @@ public class RawFieldParser {
         int pos = cursor.getPos();
         int indexFrom = cursor.getPos();
         int indexTo = cursor.getUpperBound();
+
+        ByteArrayBuffer dstRaw = new ByteArrayBuffer(indexTo - indexFrom);
+
         for (int i = indexFrom; i < indexTo; i++) {
-            char current = (char) (buf.byteAt(i) & 0xff);
+            byte currentByte = buf.byteAt(i);
+            char current = (char) (currentByte & 0xff);
             if ((delimiters != null && delimiters.get(current))
                     || CharsetUtil.isWhitespace(current) || current == '(' || current == '\"') {
                 break;
             } else {
                 pos++;
-                dst.append(current);
+                dstRaw.append(currentByte);
             }
         }
+        String decoded = CharsetUtil.isASCII(dstRaw) ? ContentUtil.decode(dstRaw) : ContentUtil.decode(StandardCharsets.UTF_8, dstRaw);
+        dst.append(decoded);
         cursor.updatePos(pos);
     }
 
@@ -414,16 +395,17 @@ public class RawFieldParser {
         pos++;
         indexFrom++;
 
-        ByteArrayBuffer dstRaw = new ByteArrayBuffer(200);
+        ByteArrayBuffer dstRaw = new ByteArrayBuffer(indexTo - indexFrom);
 
         boolean escaped = false;
         for (int i = indexFrom; i < indexTo; i++, pos++) {
-            current = (char) (buf.byteAt(i) & 0xff);
+            byte currentByte = buf.byteAt(i);
+            current = (char) (currentByte & 0xff);
             if (escaped) {
                 if (current != '\"' && current != '\\') {
                     dstRaw.append('\\');
                 }
-                dstRaw.append(current);
+                dstRaw.append(currentByte);
                 escaped = false;
             } else {
                 if (current == '\"') {
@@ -433,12 +415,12 @@ public class RawFieldParser {
                 if (current == '\\') {
                     escaped = true;
                 } else if (current != '\r' && current != '\n') {
-                    dstRaw.append(current);
+                    dstRaw.append(currentByte);
                 }
             }
         }
 
-        String decoded = ContentUtil.decode(dstRaw);
+        String decoded = CharsetUtil.isASCII(dstRaw) ? ContentUtil.decode(dstRaw) : ContentUtil.decode(StandardCharsets.UTF_8, dstRaw);
         if (decoded.startsWith("=?")) {
             decoded = DecoderUtil.decodeEncodedWords(decoded, DecodeMonitor.SILENT);
         }


=====================================
core/src/main/java/org/apache/james/mime4j/util/CharsetUtil.java
=====================================
@@ -95,6 +95,27 @@ public class CharsetUtil {
         return true;
     }
 
+    /**
+     * Returns <code>true</code> if the specified string consists entirely of
+     * US ASCII characters.
+     *
+     * @param s
+     *            string to test.
+     * @return <code>true</code> if the specified string consists entirely of
+     *         US ASCII characters, <code>false</code> otherwise.
+     */
+    public static boolean isASCII(final CharSequence s) {
+        if (s == null) {
+            throw new IllegalArgumentException("String may not be null");
+        }
+        final int len = s.length();
+        for (int i = 0; i < len; i++) {
+            if (!isASCII(s.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
     /**
      * Returns <code>true</code> if the specified character is a whitespace
      * character (CR, LF, SP or HT).


=====================================
core/src/main/java/org/apache/james/mime4j/util/ContentUtil.java
=====================================
@@ -30,6 +30,7 @@ import java.lang.ref.SoftReference;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.james.mime4j.Charsets;
@@ -131,7 +132,8 @@ public class ContentUtil {
 
     /**
      * Encodes the specified string into an immutable sequence of bytes using
-     * the US-ASCII charset.
+     * the US-ASCII charset or UTF-8 in case none ASCII characters are in the 
+     * sequence.
      *
      * @param string
      *            string to encode.
@@ -141,6 +143,9 @@ public class ContentUtil {
         if (string == null) {
             return null;
         }
+        if (!CharsetUtil.isASCII(string)) {
+            return encode(StandardCharsets.UTF_8, string);
+        }
         ByteArrayBuffer buf = new ByteArrayBuffer(string.length());
         for (int i = 0; i < string.length(); i++) {
             buf.append((byte) string.charAt(i));


=====================================
core/src/main/java/org/apache/james/mime4j/util/MimeUtil.java
=====================================
@@ -73,6 +73,10 @@ public final class MimeUtil {
      * The <code>7bit</code> encoding.
      */
     public static final String ENC_7BIT = "7bit";
+    /**
+     * The default maximum number of characters.
+     */
+    public static final int DEFAULT_MAX_CHARACTERS = 76;
 
     // used to create unique ids
     private static final Random random = new Random();
@@ -203,11 +207,11 @@ public final class MimeUtil {
 
     /**
      * Splits the specified string into a multiple-line representation with
-     * lines no longer than 76 characters (because the line might contain
+     * lines no longer than the maximum number of characters (because the line might contain
      * encoded words; see <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC
      * 2047</a> section 2). If the string contains non-whitespace sequences
-     * longer than 76 characters a line break is inserted at the whitespace
-     * character following the sequence resulting in a line longer than 76
+     * longer than the maximum number of characters a line break is inserted at the whitespace
+     * character following the sequence resulting in a line longer than the maximum number of
      * characters.
      *
      * @param s
@@ -215,11 +219,11 @@ public final class MimeUtil {
      * @param usedCharacters
      *            number of characters already used up. Usually the number of
      *            characters for header field name plus colon and one space.
+     * @param maxCharacters
+     *            maximum number of characters
      * @return a multiple-line representation of the given string.
      */
-    public static String fold(String s, int usedCharacters) {
-        final int maxCharacters = 76;
-
+    public static String fold(String s, int usedCharacters, int maxCharacters) {
         final int length = s.length();
         if (usedCharacters + length <= maxCharacters)
             return s;
@@ -246,6 +250,26 @@ public final class MimeUtil {
         }
     }
 
+    /**
+     * Splits the specified string into a multiple-line representation with
+     * lines no longer than 76 characters (because the line might contain
+     * encoded words; see <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC
+     * 2047</a> section 2). If the string contains non-whitespace sequences
+     * longer than 76 characters a line break is inserted at the whitespace
+     * character following the sequence resulting in a line longer than 76
+     * characters.
+     *
+     * @param s
+     *            string to split.
+     * @param usedCharacters
+     *            number of characters already used up. Usually the number of
+     *            characters for header field name plus colon and one space.
+     * @return a multiple-line representation of the given string.
+     */
+    public static String fold(String s, int usedCharacters) {
+        return fold(s, usedCharacters, DEFAULT_MAX_CHARACTERS);
+    }
+
     /**
      * Unfold a multiple-line representation into a single line.
      *
@@ -266,7 +290,7 @@ public final class MimeUtil {
     }
 
     /**
-    Unfold and decode header value
+     Unfold and decode header value
      */
     public static String unscrambleHeaderValue(String headerValue) {
         return DecoderUtil.decodeEncodedWords(
@@ -364,4 +388,4 @@ public final class MimeUtil {
         result.put(7L, "Sun");
         return result;
     }
-}
+}
\ No newline at end of file


=====================================
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);


=====================================
core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
=====================================
@@ -461,4 +461,32 @@ public class RawFieldParserTest {
         org.junit.Assert.assertEquals("simple boundary", params.get(0).getValue());
     }
 
+    @Test
+    public void testRegressionForContentDispositionParsingASCIIonly() {
+        ByteSequence buf = ContentUtil.encode(
+                "name=\"filedata\"; filename=\"Sanity a.doc\"");
+        ParserCursor cursor = new ParserCursor(0, buf.length());
+        List<NameValuePair> params = parser.parseParameters(buf, cursor);
+
+        org.junit.Assert.assertEquals(2, params.size());
+        org.junit.Assert.assertEquals("name", params.get(0).getName());
+        org.junit.Assert.assertEquals("filedata", params.get(0).getValue());
+        org.junit.Assert.assertEquals("filename", params.get(1).getName());
+        org.junit.Assert.assertEquals("Sanity a.doc", params.get(1).getValue());
+   }
+
+    @Test
+    public void testRegressionForContentDispositionParsingUTF8() {
+        ByteSequence buf = ContentUtil.encode("name=\"filedata\"; filename=\"Sanity ä.doc\"");
+        ParserCursor cursor = new ParserCursor(0, buf.length());
+        List<NameValuePair> params = parser.parseParameters(buf, cursor);
+
+        org.junit.Assert.assertEquals(2, params.size());
+        org.junit.Assert.assertEquals("name", params.get(0).getName());
+        org.junit.Assert.assertEquals("filedata", params.get(0).getValue());
+        org.junit.Assert.assertEquals("filename", params.get(1).getName());
+        org.junit.Assert.assertEquals("Sanity ä.doc", params.get(1).getValue());
+   }
+
+
 }


=====================================
core/src/test/java/org/apache/james/mime4j/util/MimeUtilTest.java
=====================================
@@ -25,23 +25,30 @@ import org.junit.Test;
 public class MimeUtilTest {
 
     @Test
-    public void testFold() throws Exception {
+    public void testFold() {
+        Assert.assertEquals("this\r\n is\r\n a\r\n test", MimeUtil.fold("this is a test", 0, 4));
+        Assert.assertEquals("this\r\n is a\r\n test", MimeUtil.fold("this is a test", 0, 5));
+        Assert.assertEquals("this\r\n is\r\n a\r\n test", MimeUtil.fold("this is a test", 1, 4));
+    }
+
+    @Test
+    public void testFoldWithDefaultMaxCharacters() {
         Assert.assertEquals("this is\r\n a test", MimeUtil.fold("this is a test", 68));
         Assert.assertEquals("this is\r\n a test", MimeUtil.fold("this is a test", 69));
         Assert.assertEquals("this\r\n is a test", MimeUtil.fold("this is a test", 70));
         Assert.assertEquals("this  \r\n   is a test", MimeUtil.fold(
-                "this     is a test", 70));
+            "this     is a test", 70));
     }
 
     @Test
     public void testFoldOverlyLongNonWhitespace() throws Exception {
         String ninety = "1234567890123456789012345678901234567890"
-                + "12345678901234567890123456789012345678901234567890";
+            + "12345678901234567890123456789012345678901234567890";
         String input = String.format("testing 1 2 %s testing %s", ninety,
-                ninety);
+            ninety);
 
         String expected = String.format(
-                "testing 1 2\r\n %s\r\n testing\r\n %s", ninety, ninety);
+            "testing 1 2\r\n %s\r\n testing\r\n %s", ninety, ninety);
 
         Assert.assertEquals(expected, MimeUtil.fold(input, 0));
     }
@@ -65,10 +72,10 @@ public class MimeUtilTest {
         Assert.assertEquals("this is a test", MimeUtil.unfold("this is\r\n a test"));
         Assert.assertEquals("this is a test", MimeUtil.unfold("this\r\n is a test"));
         Assert.assertEquals("this     is a test", MimeUtil
-                .unfold("this  \r\n   is a test"));
+            .unfold("this  \r\n   is a test"));
 
         Assert.assertEquals("this is a test", MimeUtil
-                .unfold("this\r\n is\r\n a\r\n test"));
+            .unfold("this\r\n is\r\n a\r\n test"));
     }
 
-}
+}
\ No newline at end of file


=====================================
debian/changelog
=====================================
@@ -1,3 +1,11 @@
+apache-mime4j (0.8.12-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream version 0.8.12
+  * Bump Standards-Version to 4.7.0
+
+ -- tony mancill <tmancill at debian.org>  Sun, 29 Dec 2024 10:56:29 -0800
+
 apache-mime4j (0.8.11-1) unstable; urgency=medium
 
   * Team upload


=====================================
debian/control
=====================================
@@ -17,7 +17,7 @@ Build-Depends:
  libmaven-bundle-plugin-java,
  libmockito-java,
  maven-debian-helper
-Standards-Version: 4.6.2
+Standards-Version: 4.7.0
 Vcs-Git: https://salsa.debian.org/java-team/apache-mime4j.git
 Vcs-Browser: https://salsa.debian.org/java-team/apache-mime4j
 Homepage: https://james.apache.org/mime4j/


=====================================
doap_James_Mime4j.rdf
=====================================
@@ -1,8 +1,8 @@
 <?xml version="1.0"?>
 <?xml-stylesheet type="text/xsl"?>
 <rdf:RDF xml:lang="en"
-         xmlns="http://usefulinc.com/ns/doap#" 
-         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
+         xmlns="http://usefulinc.com/ns/doap#"
+         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
          xmlns:asfext="http://projects.apache.org/ns/asfext#"
          xmlns:foaf="http://xmlns.com/foaf/0.1/">
 <!--
@@ -45,10 +45,10 @@ Mime4j can be used to parse e-mail message streams in plain rfc822 and MIME form
 and to build a tree representation of an e-mail message.
     </shortdesc>
     <description>
-Mime4j provides a parser for e-mail message streams in plain rfc822 and MIME format. 
-The parser uses a callback mechanism to report parsing events such as the start of 
-an entity header, the start of a body. The parser has been designed to be extremely 
-tolerant against messages violating the standards. Mime4j can also be used to build 
+Mime4j provides a parser for e-mail message streams in plain rfc822 and MIME format.
+The parser uses a callback mechanism to report parsing events such as the start of
+an entity header, the start of a body. The parser has been designed to be extremely
+tolerant against messages violating the standards. Mime4j can also be used to build
 a tree representation of an e-mail message
     </description>
     <bug-database rdf:resource="http://issues.apache.org/jira/browse/MIME4J" />
@@ -60,6 +60,91 @@ a tree representation of an e-mail message
 
     <!-- Multiple releases can be listed, each in its own section -->
     <release>
+      <Version>
+        <name>Apache James Mime4j 0.8.11</name>
+        <created>2024-03-05</created>
+        <revision>0.8.11</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.10</name>
+        <created>2024-02-22</created>
+        <revision>0.8.10</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.9</name>
+        <created>2022-12-30</created>
+        <revision>0.8.9</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.8</name>
+        <created>2022-10-28</created>
+        <revision>0.8.8</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.7</name>
+        <created>2022-04-01</created>
+        <revision>0.8.7</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.6</name>
+        <created>2021-09-24</created>
+        <revision>0.8.6</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.5</name>
+        <created>2021-07-01</created>
+        <revision>0.8.5</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.4</name>
+        <created>2021-04-21</created>
+        <revision>0.8.4</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.3</name>
+        <created>2019-03-21</created>
+        <revision>0.8.3</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.2</name>
+        <created>2018-04-27</created>
+        <revision>0.8.2</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8.1</name>
+        <created>2017-06-27</created>
+        <revision>0.8.1</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.8</name>
+        <created>2016-10-12</created>
+        <revision>0.8</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.7.2</name>
+        <created>2012-01-07</created>
+        <revision>0.7.2</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.7.1</name>
+        <created>2011-10-08</created>
+        <revision>0.7.1</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.7</name>
+        <created>2011-07-20</created>
+        <revision>0.7</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.6.1</name>
+        <created>2010-12-27</created>
+        <revision>0.6.1</revision>
+      </Version>
+      <Version>
+        <name>Apache James Mime4j 0.6</name>
+        <created>2009-03-05</created>
+        <revision>0.6</revision>
+      </Version>
       <Version>
         <name>Apache James Mime4j 0.5</name>
         <created>2008-10-18</created>


=====================================
dom/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>apache-mime4j-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressParser.java
=====================================
@@ -152,7 +152,7 @@ public class LenientAddressParser implements AddressParser {
         }
         pos = cursor.getPos();
         current = (char) (buf.byteAt(pos) & 0xff);
-        if (current == AT) {
+        if (current == AT || current == CLOSING_BRACKET) {
             cursor.updatePos(pos + 1);
         } else {
             return createMailbox(openingText, domainList, localPart, null);


=====================================
dom/src/test/java/org/apache/james/mime4j/field/FieldsTest.java
=====================================
@@ -21,6 +21,7 @@ package org.apache.james.mime4j.field;
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
@@ -399,6 +400,14 @@ public class FieldsTest {
                 decode(field));
     }
 
+    @Test
+    public void testAddressListWhenMailboxAbsentDomain() {
+        Mailbox mailbox = new Mailbox("name1", "localpart", "");
+        AddressListField field = Fields.addressList("To", Collections.singleton(mailbox));
+        Assert.assertEquals(1, field.getAddressList().size());
+        Assert.assertEquals(mailbox, field.getAddressList().get(0));
+    }
+
     @Test
     public void testInvalidFieldName() throws Exception {
         try {


=====================================
dom/src/test/java/org/apache/james/mime4j/field/LenientContentDispositionFieldTest.java
=====================================
@@ -19,14 +19,12 @@
 
 package org.apache.james.mime4j.field;
 
-import java.nio.charset.StandardCharsets;
 import java.util.Date;
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.dom.field.ContentDispositionField;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.stream.RawFieldParser;
-import org.apache.james.mime4j.util.ByteArrayBuffer;
 import org.apache.james.mime4j.util.ByteSequence;
 import org.apache.james.mime4j.util.ContentUtil;
 import org.junit.Assert;
@@ -40,11 +38,6 @@ public class LenientContentDispositionFieldTest {
         return ContentDispositionFieldLenientImpl.PARSER.parse(rawField, null);
     }
 
-    static ContentDispositionField parse(final byte[] raw) throws MimeException {
-        RawField rawField = RawFieldParser.DEFAULT.parseField(new ByteArrayBuffer(raw, true));
-        return ContentDispositionFieldLenientImpl.PARSER.parse(rawField, null);
-    }
-
     @Test
     public void testDispositionTypeWithSemiColonNoParams() throws Exception {
         ContentDispositionField f = parse("Content-Disposition: inline;");
@@ -120,10 +113,9 @@ public class LenientContentDispositionFieldTest {
 
     @Test
     public void testGetFilenameEncoded() throws Exception {
-        byte[] data = ("Content-Disposition: attachment;\n" +
+        String data = "Content-Disposition: attachment;\n" +
             " FileName=\"=?WINDOWS-1251?Q?3244659=5F=C0=EA=F2_=E7=E0_=C8=FE=EB=FC_?=\n" +
-            " =?WINDOWS-1251?Q?2020.pdf?=\"")
-            .getBytes(StandardCharsets.UTF_8);
+            " =?WINDOWS-1251?Q?2020.pdf?=\"";
 
         ContentDispositionField f = parse(data);
 
@@ -132,10 +124,8 @@ public class LenientContentDispositionFieldTest {
 
     @Test
     public void testGetFilenameUtf8() throws Exception {
-        byte[] data =
-            "Content-Disposition: attachment; filename=\"УПД ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ \"СТАНЦИЯ ВИРТУАЛЬНАЯ\" 01-05-21.pdf\""
-            .getBytes(StandardCharsets.UTF_8);
-
+        String data =
+            "Content-Disposition: attachment; filename=\"УПД ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ \\\"СТАНЦИЯ ВИРТУАЛЬНАЯ\\\" 01-05-21.pdf\"";
         ContentDispositionField f = parse(data);
 
         Assert.assertEquals("UTF8 encoded filename", "УПД ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ \"СТАНЦИЯ ВИРТУАЛЬНАЯ\" 01-05-21.pdf", f.getFilename());
@@ -143,10 +133,9 @@ public class LenientContentDispositionFieldTest {
 
     @Test
     public void testGetFilenameMultipartUtf8() throws Exception {
-        byte[] data = ("Content-Disposition: attachment;\n" +
+        String data = "Content-Disposition: attachment;\n" +
             "	filename*0*=\"UTF-8''%D0%A0%D0%BE%D1%81%D1%82%D0%B5%D0%BB%D0%B5%D0%BA%D0%BE\";\n" +
-            "	filename*1*=\"%D0%BC%2E%78%6C%73%78\"\n")
-            .getBytes(StandardCharsets.UTF_8);
+            "	filename*1*=\"%D0%BC%2E%78%6C%73%78\"\n";
 
         ContentDispositionField f = parse(data);
         Assert.assertEquals("Ростелеком.xlsx", f.getFilename());


=====================================
dom/src/test/java/org/apache/james/mime4j/field/UnstructuredFieldTest.java
=====================================
@@ -43,6 +43,14 @@ public class UnstructuredFieldTest {
         Assert.assertEquals("Testing value without a leading ' '", "yada", f.getValue());
     }
 
+    @Test
+    public void testUnfoldWithEqualSign() throws Exception {
+        UnstructuredField f = (UnstructuredField) DefaultFieldParser.parse("\n" +
+            "References: <CAMpLFpB=uu_mqGwf5RToWqCfkd9cmZKBoJ782872YDgfp1d2sA at mail.gmail.com>\n" +
+            " <CAMpLFpCVygEwb+t=FmD6TqiDLrQHkREvh=_2=ZinF8WH1-yxbQ at mail.gmail.com>\r\n");
+        Assert.assertEquals("<CAMpLFpB=uu_mqGwf5RToWqCfkd9cmZKBoJ782872YDgfp1d2sA at mail.gmail.com> <CAMpLFpCVygEwb+t=FmD6TqiDLrQHkREvh=_2=ZinF8WH1-yxbQ at mail.gmail.com>", f.getValue());
+    }
+
     @Test
     public void testGetBodyUtf8() throws Exception {
         UnstructuredField f;


=====================================
dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
=====================================
@@ -108,6 +108,20 @@ public class LenientAddressBuilderTest {
         Assert.assertEquals("=?utf-8?Q?Dupont,_Gr=C3=A9goire", mailbox.getName());
     }
 
+    @Test // MIME4J-327
+    public void testNameUTF8Support() throws Exception {
+        String s = "\"시험\" <koreantest at example.com>";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, raw.length());
+
+        Address address = parser.parseAddress(raw, cursor, RawFieldParser.INIT_BITSET(','));
+        Assert.assertNotNull(address);
+        Assert.assertTrue(address instanceof Mailbox);
+        Mailbox mailbox = (Mailbox) address;
+        Assert.assertEquals("시험", mailbox.getName());
+        Assert.assertEquals("koreantest at example.com", mailbox.getAddress());
+    }
+
     @Test
     public void shouldTolerateMalformedEncoding() throws Exception {
         String s = "\"=?windows-1251?B?onsonsmekqixrbahkinyv?=\" <atfilpd at louisphaethon.co.ua>";


=====================================
examples/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>apache-mime4j-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
james-logo.png
=====================================
Binary files /dev/null and b/james-logo.png differ


=====================================
james-utils/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.james</groupId>
         <artifactId>apache-mime4j-project</artifactId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
mbox/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.james</groupId>
         <artifactId>apache-mime4j-project</artifactId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 


=====================================
pom.xml
=====================================
@@ -29,7 +29,7 @@
 
     <groupId>org.apache.james</groupId>
     <artifactId>apache-mime4j-project</artifactId>
-    <version>0.8.11</version>
+    <version>0.8.12</version>
     <packaging>pom</packaging>
 
     <name>Apache James :: Mime4j :: Project</name>
@@ -52,7 +52,7 @@
         <connection>scm:git:http://git-wip-us.apache.org/repos/asf/james-mime4j.git</connection>
         <developerConnection>scm:git:ssh://git@github.com/apache/james-mime4j.git</developerConnection>
         <url>https://git-wip-us.apache.org/repos/asf/james-mime4j.git</url>
-      <tag>apache-mime4j-project-0.8.11</tag>
+      <tag>apache-mime4j-project-0.8.12</tag>
   </scm>
     <issueManagement>
         <url>http://issues.apache.org/jira/browse/MIME4J</url>
@@ -73,7 +73,7 @@
         <log4j.version>2.19.0</log4j.version>
         <junit.version>4.13.2</junit.version>
         <mockito.version>3.12.4</mockito.version>
-        <commons-io.version>2.11.0</commons-io.version>
+        <commons-io.version>2.17.0</commons-io.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
 


=====================================
storage/pom.xml
=====================================
@@ -23,7 +23,7 @@
     <parent>
         <artifactId>apache-mime4j-project</artifactId>
         <groupId>org.apache.james</groupId>
-        <version>0.8.11</version>
+        <version>0.8.12</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 



View it on GitLab: https://salsa.debian.org/java-team/apache-mime4j/-/compare/acbe32ed527e73f47a9377886b7c22cdfdeeef10...cb092a92f647717132556ba9e5685855b1dfbdcc

-- 
View it on GitLab: https://salsa.debian.org/java-team/apache-mime4j/-/compare/acbe32ed527e73f47a9377886b7c22cdfdeeef10...cb092a92f647717132556ba9e5685855b1dfbdcc
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20241229/3fe68741/attachment.htm>


More information about the pkg-java-commits mailing list