Index: core/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java =================================================================== --- core/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java (revision 906403) +++ core/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java (working copy) @@ -192,6 +192,6 @@ @Override protected MutableBodyDescriptor newBodyDescriptor(BodyDescriptor parent) { - return new MaximalBodyDescriptor(parent); + return new MaximalBodyDescriptor(parent, null); } } Index: core/src/test/java/org/apache/james/mime4j/stream/BaseTestForBodyDescriptors.java =================================================================== --- core/src/test/java/org/apache/james/mime4j/stream/BaseTestForBodyDescriptors.java (revision 906403) +++ core/src/test/java/org/apache/james/mime4j/stream/BaseTestForBodyDescriptors.java (working copy) @@ -27,7 +27,7 @@ protected abstract MutableBodyDescriptor newBodyDescriptor(BodyDescriptor parent); - public void testGetParameters() { + public void testGetParameters() throws Exception { MutableBodyDescriptor bd = null; bd = newBodyDescriptor(); @@ -64,7 +64,7 @@ assertEquals("\\n\\\"", bd.getContentTypeParameters().get("param")); } - public void testAddField() { + public void testAddField() throws Exception { MutableBodyDescriptor bd = null; /* @@ -79,7 +79,7 @@ assertEquals("iso-8859-1", bd.getCharset()); } - public void testGetMimeType() { + public void testGetMimeType() throws Exception { MutableBodyDescriptor bd = null; bd = newBodyDescriptor(); @@ -135,7 +135,7 @@ } - public void testParameters() { + public void testParameters() throws Exception { MutableBodyDescriptor bd = null; /* Index: core/src/test/java/org/apache/james/mime4j/parser/DefaultBodyDescriptorTest.java =================================================================== --- core/src/test/java/org/apache/james/mime4j/parser/DefaultBodyDescriptorTest.java (revision 906403) +++ core/src/test/java/org/apache/james/mime4j/parser/DefaultBodyDescriptorTest.java (working copy) @@ -32,6 +32,6 @@ @Override protected MutableBodyDescriptor newBodyDescriptor(BodyDescriptor parent) { - return new DefaultBodyDescriptor(parent); + return new DefaultBodyDescriptor(parent, null); } } Index: core/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java (revision 906403) +++ core/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java (working copy) @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.james.mime4j.MimeException; +import org.apache.james.mime4j.codec.DecodeMonitor; import org.apache.james.mime4j.dom.datetime.DateTime; import org.apache.james.mime4j.field.datetime.parser.DateTimeParser; import org.apache.james.mime4j.field.datetime.parser.ParseException; @@ -74,11 +75,11 @@ private boolean isContentMD5Set; protected MaximalBodyDescriptor() { - this(null); + this(null, null); } - public MaximalBodyDescriptor(BodyDescriptor parent) { - super(parent); + public MaximalBodyDescriptor(final BodyDescriptor parent, final DecodeMonitor monitor) { + super(parent, monitor); isMimeVersionSet = false; mimeMajorVersion = DEFAULT_MAJOR_VERSION; mimeMinorVersion = DEFAULT_MINOR_VERSION; @@ -108,11 +109,11 @@ } public MutableBodyDescriptor newChild() { - return new MaximalBodyDescriptor(this); + return new MaximalBodyDescriptor(this, getDecodeMonitor()); } @Override - public void addField(RawField field) { + public void addField(RawField field) throws MimeException { String name = field.getName(); String value = field.getBody(); name = name.trim().toLowerCase(); @@ -174,9 +175,9 @@ } } - private void parseContentDisposition(final String value) { + private void parseContentDisposition(final String value) throws MimeException { isContentDispositionSet = true; - contentDispositionParameters = DefaultBodyDescriptor.getHeaderParams(value); + contentDispositionParameters = DefaultBodyDescriptor.getHeaderParams(value, getDecodeMonitor()); contentDispositionType = contentDispositionParameters.get(""); final String contentDispositionModificationDate Index: core/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java (revision 906403) +++ core/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java (working copy) @@ -19,13 +19,14 @@ package org.apache.james.mime4j.message; +import org.apache.james.mime4j.codec.DecodeMonitor; import org.apache.james.mime4j.stream.MutableBodyDescriptor; import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory; public class MaximalBodyDescriptorFactory implements MutableBodyDescriptorFactory { - public MutableBodyDescriptor newInstance() { - return new MaximalBodyDescriptor(null); + public MutableBodyDescriptor newInstance(DecodeMonitor monitor) { + return new MaximalBodyDescriptor(null, monitor); } } Index: core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java (revision 906403) +++ core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java (working copy) @@ -22,8 +22,8 @@ import java.util.HashMap; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.apache.james.mime4j.MimeException; +import org.apache.james.mime4j.codec.DecodeMonitor; import org.apache.james.mime4j.util.MimeUtil; /** @@ -47,7 +47,7 @@ private static final String DEFAULT_MIME_TYPE = DEFAULT_MEDIA_TYPE + "/" + DEFAULT_SUB_TYPE; - private static Log log = LogFactory.getLog(DefaultBodyDescriptor.class); + private final DecodeMonitor monitor; private String mediaType = DEFAULT_MEDIA_TYPE; private String subType = DEFAULT_SUB_TYPE; @@ -64,7 +64,7 @@ * Creates a new root BodyDescriptor instance. */ public DefaultBodyDescriptor() { - this(null); + this(null, null); } /** @@ -73,20 +73,25 @@ * @param parent the descriptor of the parent or null if this * is the root descriptor. */ - public DefaultBodyDescriptor(BodyDescriptor parent) { + public DefaultBodyDescriptor(final BodyDescriptor parent, final DecodeMonitor monitor) { if (parent != null && MimeUtil.isSameMimeType("multipart/digest", parent.getMimeType())) { - mimeType = EMAIL_MESSAGE_MIME_TYPE; - subType = SUB_TYPE_EMAIL; - mediaType = MEDIA_TYPE_MESSAGE; + this.mimeType = EMAIL_MESSAGE_MIME_TYPE; + this.subType = SUB_TYPE_EMAIL; + this.mediaType = MEDIA_TYPE_MESSAGE; } else { - mimeType = DEFAULT_MIME_TYPE; - subType = DEFAULT_SUB_TYPE; - mediaType = DEFAULT_MEDIA_TYPE; + this.mimeType = DEFAULT_MIME_TYPE; + this.subType = DEFAULT_SUB_TYPE; + this.mediaType = DEFAULT_MEDIA_TYPE; } + this.monitor = monitor != null ? monitor : DecodeMonitor.SILENT; } + protected DecodeMonitor getDecodeMonitor() { + return monitor; + } + public MutableBodyDescriptor newChild() { - return new DefaultBodyDescriptor(this); + return new DefaultBodyDescriptor(this, getDecodeMonitor()); } /** @@ -95,7 +100,7 @@ * * @param field the MIME field. */ - public void addField(RawField field) { + public void addField(RawField field) throws MimeException { String name = field.getName(); String value = field.getBody(); @@ -113,17 +118,20 @@ try { contentLength = Long.parseLong(value.trim()); } catch (NumberFormatException e) { - log.error("Invalid content-length: " + value); + if (monitor.warn("Invalid content length: " + value, + "ignoring Content-Length header")) { + throw new MimeException("Invalid Content-Length header: " + value); + } } } else if (name.equals("content-type") && !contentTypeSet) { parseContentType(value); } } - private void parseContentType(String value) { + private void parseContentType(String value) throws MimeException { contentTypeSet = true; - Map params = DefaultBodyDescriptor.getHeaderParams(value); + Map params = DefaultBodyDescriptor.getHeaderParams(value, getDecodeMonitor()); String main = params.get(""); String type = null; @@ -258,7 +266,8 @@ * @param pValue The field value to parse. * @return The result map; use the key "" to retrieve the first value. */ - public static Map getHeaderParams(String pValue) { + public static Map getHeaderParams( + String pValue, DecodeMonitor monitor) throws MimeException { pValue = pValue.trim(); Map result = new HashMap(); @@ -299,7 +308,9 @@ case READY_FOR_NAME: if (c == '=') { - log.error("Expected header param name, got '='"); + if (monitor.warn("Expected header param name, got '='", "ignoring")) { + throw new MimeException("Expected header param name, got '='"); + } state = ERROR; break; } Index: core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java (revision 906403) +++ core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java (working copy) @@ -120,7 +120,7 @@ * internal state. */ public void parse(InputStream stream) { - doParse(stream, null); + doParse(stream, newBodyDescriptor(), T_START_MESSAGE); } /** Instructs the {@code MimeTokenStream} to parse the given content with @@ -136,17 +136,14 @@ if (contentType == null) { throw new IllegalArgumentException("Content type may not be null"); } - doParse(stream, contentType); - } - - protected void doParse(InputStream stream, String contentType) { MutableBodyDescriptor newBodyDescriptor = newBodyDescriptor(); - int start = T_START_MESSAGE; - if (contentType != null) { - start = T_END_HEADER; + try { newBodyDescriptor.addField(new RawField("Content-Type", contentType)); + } catch (MimeException ex) { + // should never happen + throw new IllegalArgumentException(ex.getMessage()); } - doParse(stream, newBodyDescriptor, start); + doParse(stream, newBodyDescriptor, T_END_HEADER); } /** @@ -157,9 +154,9 @@ protected MutableBodyDescriptor newBodyDescriptor() { final MutableBodyDescriptor result; if (bodyDescFactory != null) { - result = bodyDescFactory.newInstance(); + result = bodyDescFactory.newInstance(monitor); } else { - result = new DefaultBodyDescriptor(null); + result = new DefaultBodyDescriptor(null, monitor); } return result; } Index: core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java (revision 906403) +++ core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java (working copy) @@ -20,6 +20,7 @@ package org.apache.james.mime4j.stream; +import org.apache.james.mime4j.MimeException; /** * Adds mutator. @@ -30,7 +31,7 @@ * Adds a field to the body descriptor. * @param field the MIME field. */ - void addField(RawField field); + void addField(RawField field) throws MimeException; MutableBodyDescriptor newChild(); Index: core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptorFactory.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptorFactory.java (revision 906403) +++ core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptorFactory.java (working copy) @@ -19,11 +19,13 @@ package org.apache.james.mime4j.stream; +import org.apache.james.mime4j.codec.DecodeMonitor; + /** * {@link MutableBodyDescriptor} factory. */ public interface MutableBodyDescriptorFactory { - MutableBodyDescriptor newInstance(); + MutableBodyDescriptor newInstance(DecodeMonitor monitor); }