This is an automated email from the ASF dual-hosted git repository.
rcordier 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 3d1f2cf3 MIME4J-330 Fix MimeStreamParser bug: part body stream ends
with CR
3d1f2cf3 is described below
commit 3d1f2cf35501ac457ef2e6b71306be5f1295df55
Author: hung phan <[email protected]>
AuthorDate: Fri Jan 10 15:24:14 2025 +0700
MIME4J-330 Fix MimeStreamParser bug: part body stream ends with CR
---
.../james/mime4j/io/MimeBoundaryInputStream.java | 14 +++--
.../ExtractPartWithDifferentLengthsTest.java | 73 ++++++++++++++++++++++
2 files changed, 83 insertions(+), 4 deletions(-)
diff --git
a/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
b/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
index 140f6b65..53ab013c 100644
--- a/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
+++ b/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
@@ -245,14 +245,14 @@ public class MimeBoundaryInputStream extends
LineReaderInputStream {
// Make sure the boundary is terminated with EOS
break;
} else {
- // or with a whitespace or '--'
+ // or with a whitespace or '--'
char ch = (char)(buffer.byteAt(pos));
if (CharsetUtil.isWhitespace(ch)) {
break;
}
if (ch == '-' && remaining > 1 &&
(char)(buffer.byteAt(pos+1)) == '-') {
break;
- }
+ }
}
}
off = i + boundary.length;
@@ -265,8 +265,14 @@ public class MimeBoundaryInputStream extends
LineReaderInputStream {
if (eof) {
limit = buffer.limit();
} else {
- limit = buffer.limit() - (boundary.length + 2);
- // [LF] [boundary] [CR][LF] minus one char
+ int position = buffer.limit() - (boundary.length + 3); //
2nd position before boundary
+ if (position >= 0 && (char) buffer.byteAt(position) == '\r') {
+ limit = buffer.limit() - (boundary.length + 3);
+ // boundary [CR][LF] minus two chars
+ } else {
+ limit = buffer.limit() - (boundary.length + 2);
+ // boundary [LF] minus one char
+ }
}
}
return bytesRead;
diff --git
a/core/src/test/java/org/apache/james/mime4j/parser/ExtractPartWithDifferentLengthsTest.java
b/core/src/test/java/org/apache/james/mime4j/parser/ExtractPartWithDifferentLengthsTest.java
new file mode 100644
index 00000000..ec8eb4fa
--- /dev/null
+++
b/core/src/test/java/org/apache/james/mime4j/parser/ExtractPartWithDifferentLengthsTest.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.mime4j.parser;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.stream.BodyDescriptor;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+public class ExtractPartWithDifferentLengthsTest {
+ @Test
+ public void testExtractPartWithDifferentLengths() throws Exception {
+ StringBuilder partBuilder = new StringBuilder();
+ for (int i = 1; i <= 5000; i++) {
+ partBuilder.append(i % 80 == 0 ? "\n" : "A");
+ String part = partBuilder.toString();
+ String mimeMessage = createMimeMultipart(part);
+
+ String extracted = extractPart(mimeMessage);
+ Assert.assertEquals(part, extracted);
+ }
+ }
+
+ private String createMimeMultipart(String part) {
+ return "Content-type: multipart/mixed; boundary=QvEgqhjEnYxz\n"
+ + "\n"
+ + "--QvEgqhjEnYxz\n"
+ + "Content-Type: text/plain\n"
+ + "\n"
+ + part
+ + "\r\n"
+ + "--QvEgqhjEnYxz--\n";
+ }
+
+ private String extractPart(String mimeMessage) throws
+ MimeException, IOException {
+ String[] resultWrapper = new String[1];
+
+ MimeStreamParser parser = new MimeStreamParser();
+ parser.setContentHandler(new AbstractContentHandler() {
+ @Override
+ public void body(BodyDescriptor bd, InputStream is) throws
IOException {
+ resultWrapper[0] = new String(IOUtils.toString(is,
+ StandardCharsets.UTF_8).getBytes());
+ }
+ });
+ parser.parse(new ByteArrayInputStream(mimeMessage.getBytes()));
+ return resultWrapper[0];
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]