You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mime4j-dev@james.apache.org by ol...@apache.org on 2011/06/15 16:20:18 UTC
svn commit: r1136061 - in /james/mime4j/trunk/core/src:
main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
main/java/org/apache/james/mime4j/stream/MimeEntity.java
test/java/org/apache/james/mime4j/stream/StrictMimeTokenStreamTest.java
Author: olegk
Date: Wed Jun 15 14:20:18 2011
New Revision: 1136061
URL: http://svn.apache.org/viewvc?rev=1136061&view=rev
Log:
MIME4J-180: I/O exception is thrown in the strict parsing mode when reading from body content stream if the mime part has no end boundary; fixed recursion in MimeBoundaryInputStream#read(byte[], int, int) method
Modified:
james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java
james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/StrictMimeTokenStreamTest.java
Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java?rev=1136061&r1=1136060&r2=1136061&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java (original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/io/MimeBoundaryInputStream.java Wed Jun 15 14:20:18 2011
@@ -19,6 +19,8 @@
package org.apache.james.mime4j.io;
+import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.MimeIOException;
import org.apache.james.mime4j.util.ByteArrayBuffer;
import java.io.IOException;
@@ -31,6 +33,7 @@ import java.io.IOException;
public class MimeBoundaryInputStream extends LineReaderInputStream {
private final byte[] boundary;
+ private final boolean strict;
private boolean eof;
private int limit;
@@ -55,8 +58,10 @@ public class MimeBoundaryInputStream ext
* @param boundary Boundary string (not including leading hyphens).
* @throws IllegalArgumentException when boundary is too long
*/
- public MimeBoundaryInputStream(BufferedLineReaderInputStream inbuffer, String boundary)
- throws IOException {
+ public MimeBoundaryInputStream(
+ final BufferedLineReaderInputStream inbuffer,
+ final String boundary,
+ final boolean strict) throws IOException {
super(inbuffer);
int bufferSize = 2 * boundary.length();
if (bufferSize < 4096) {
@@ -72,6 +77,7 @@ public class MimeBoundaryInputStream ext
this.initialLength = -1;
this.completed = false;
+ this.strict = strict;
this.boundary = new byte[boundary.length() + 2];
this.boundary[0] = (byte) '-';
this.boundary[1] = (byte) '-';
@@ -84,6 +90,19 @@ public class MimeBoundaryInputStream ext
}
/**
+ * Creates a new MimeBoundaryInputStream.
+ *
+ * @param inbuffer The underlying stream.
+ * @param boundary Boundary string (not including leading hyphens).
+ * @throws IllegalArgumentException when boundary is too long
+ */
+ public MimeBoundaryInputStream(
+ final BufferedLineReaderInputStream inbuffer,
+ final String boundary) throws IOException {
+ this(inbuffer, boundary, false);
+ }
+
+ /**
* Closes the underlying stream.
*
* @throws IOException on I/O errors.
@@ -104,9 +123,9 @@ public class MimeBoundaryInputStream ext
if (completed) {
return false;
}
- // System.out.println("rA!");
if (endOfStream() && !hasData()) {
- skipBoundary();
+ skipBoundary();
+ verifyEndOfStream();
return false;
}
return true;
@@ -117,13 +136,10 @@ public class MimeBoundaryInputStream ext
*/
@Override
public int read() throws IOException {
- if (!readAllowed()) return -1;
for (;;) {
+ if (!readAllowed()) return -1;
if (hasData()) {
return buffer.read();
- } else if (endOfStream()) {
- skipBoundary();
- return -1;
}
fillBuffer();
}
@@ -131,13 +147,14 @@ public class MimeBoundaryInputStream ext
@Override
public int read(byte[] b, int off, int len) throws IOException {
- if (!readAllowed()) return -1;
- fillBuffer();
- if (!hasData()) {
- return read(b, off, len);
+ for (;;) {
+ if (!readAllowed()) return -1;
+ if (hasData()) {
+ int chunk = Math.min(len, limit - buffer.pos());
+ return buffer.read(b, off, chunk);
+ }
+ fillBuffer();
}
- int chunk = Math.min(len, limit - buffer.pos());
- return buffer.read(b, off, chunk);
}
@Override
@@ -155,6 +172,7 @@ public class MimeBoundaryInputStream ext
bytesRead = fillBuffer();
if (endOfStream() && !hasData()) {
skipBoundary();
+ verifyEndOfStream();
bytesRead = -1;
break;
}
@@ -181,6 +199,12 @@ public class MimeBoundaryInputStream ext
}
}
+ private void verifyEndOfStream() throws IOException {
+ if (strict && eof && !atBoundary) {
+ throw new MimeIOException(new MimeException("Unexpected end of stream"));
+ }
+ }
+
private boolean endOfStream() {
return eof || atBoundary;
}
Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java?rev=1136061&r1=1136060&r2=1136061&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java (original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java Wed Jun 15 14:20:18 2011
@@ -215,7 +215,8 @@ class MimeEntity extends AbstractEntity
private void createMimePartStream() throws MimeException, IOException {
String boundary = body.getBoundary();
try {
- currentMimePartStream = new MimeBoundaryInputStream(inbuffer, boundary);
+ currentMimePartStream = new MimeBoundaryInputStream(inbuffer, boundary,
+ config.isStrictParsing());
} catch (IllegalArgumentException e) {
// thrown when boundary is too long
throw new MimeException(e.getMessage(), e);
Modified: james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/StrictMimeTokenStreamTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/StrictMimeTokenStreamTest.java?rev=1136061&r1=1136060&r2=1136061&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/StrictMimeTokenStreamTest.java (original)
+++ james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/StrictMimeTokenStreamTest.java Wed Jun 15 14:20:18 2011
@@ -22,7 +22,7 @@ package org.apache.james.mime4j.stream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
-import org.apache.commons.io.IOUtils;
+import org.apache.james.mime4j.MimeIOException;
import junit.framework.TestCase;
@@ -84,13 +84,17 @@ public class StrictMimeTokenStreamTest e
checkNextIs(EntityState.T_FIELD);
checkNextIs(EntityState.T_END_HEADER);
checkNextIs(EntityState.T_BODY);
- InputStream out = parser.getInputStream();
- assertEquals("Oh my god! Boundary is missing!\r\n", IOUtils.toString(out, "US-ASCII"));
- checkNextIs(EntityState.T_END_BODYPART);
+ InputStream in = parser.getInputStream();
+ StringBuilder sb = new StringBuilder();
try {
- parser.next();
- fail("MimeParseEventException should have been thrown");
- } catch (MimeParseEventException expected) {
+ byte[] tmp = new byte[1024];
+ int l;
+ while ((l = in.read(tmp)) != -1) {
+ sb.append(new String(tmp, 0, l, "US-ASCII"));
+ }
+ fail("MimeIOException should have been thrown");
+ } catch (MimeIOException expected) {
+ assertEquals("Oh my god! Boundary is missing!\r\n", sb.toString());
}
}