Index: src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java =================================================================== --- src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java (revision 766438) +++ src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java (working copy) @@ -32,6 +32,7 @@ private int maxHeaderCount; private long maxContentLen; private boolean countLineNumbers; + private String defaultContentType; public MimeEntityConfig() { this.maximalBodyDescriptor = false; @@ -159,6 +160,30 @@ return countLineNumbers; } + /** + * Returns the value of the default content type. Used by + * {@link MimeStreamParser#parse(java.io.InputStream)} to do a + * headless parsing when this property is not null. + * + * @param defaultContentType + * value of the default content type. + */ + public String getDefaultContentType() { + return defaultContentType; + } + + /** + * Defines a default content type. Used by + * {@link MimeStreamParser#parse(java.io.InputStream)} to do a + * headless parsing when this property is not null. + * + * @param defaultContentType + * value of the default content type. + */ + public void setDefaultContentType(String defaultContentType) { + this.defaultContentType = defaultContentType; + } + @Override public MimeEntityConfig clone() { try { Index: src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java =================================================================== --- src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java (revision 766438) +++ src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java (working copy) @@ -19,12 +19,15 @@ package org.apache.james.mime4j.parser; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; + import org.apache.james.mime4j.MimeException; import org.apache.james.mime4j.descriptor.BodyDescriptor; +import org.apache.james.mime4j.field.FieldName; -import java.io.IOException; -import java.io.InputStream; - /** *

* Parses MIME (or RFC822) message streams of bytes or characters and reports @@ -43,18 +46,18 @@ private ContentHandler handler = null; private boolean contentDecoding; + private final MimeEntityConfig mimeEntityConfig; private final MimeTokenStream mimeTokenStream; public MimeStreamParser(final MimeEntityConfig config) { super(); - MimeEntityConfig localConfig; if (config != null) { - localConfig = config.clone(); + mimeEntityConfig = config.clone(); } else { - localConfig = new MimeEntityConfig(); + mimeEntityConfig = new MimeEntityConfig(); } - this.mimeTokenStream = new MimeTokenStream(localConfig); + this.mimeTokenStream = new MimeTokenStream(mimeEntityConfig); this.contentDecoding = false; } @@ -79,14 +82,24 @@ } /** - * Parses a stream of bytes containing a MIME message. + * Parses a stream of bytes containing a MIME message. If the mime config of this + * object contains a not null defaultContentType + * ({@link MimeEntityConfig#getDefaultContentType()}) a headless parsing is performed. * * @param is the stream to parse. * @throws MimeException if the message can not be processed * @throws IOException on I/O errors. */ public void parse(InputStream is) throws MimeException, IOException { - mimeTokenStream.parse(is); + boolean headless = mimeEntityConfig.getDefaultContentType() != null; + InputStream inputStream = is; + if (headless) { + ByteArrayInputStream headerInputStream = new ByteArrayInputStream( + (FieldName.CONTENT_TYPE + ": " + mimeEntityConfig.getDefaultContentType() + + "\r\n\r\n").getBytes("iso-8859-1")); + inputStream = new SequenceInputStream(headerInputStream, is); + } + mimeTokenStream.parse(inputStream); OUTER: for (;;) { int state = mimeTokenStream.getState(); switch (state) { Index: src/test/java/org/apache/james/mime4j/message/MessageHeadlessParserTest.java =================================================================== --- src/test/java/org/apache/james/mime4j/message/MessageHeadlessParserTest.java (revision 0) +++ src/test/java/org/apache/james/mime4j/message/MessageHeadlessParserTest.java (revision 0) @@ -0,0 +1,60 @@ +/**************************************************************** + * 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.message; + +import java.io.ByteArrayInputStream; + +import junit.framework.TestCase; + +import org.apache.james.mime4j.field.ContentTypeField; +import org.apache.james.mime4j.field.FieldName; +import org.apache.james.mime4j.parser.MimeEntityConfig; + +public class MessageHeadlessParserTest extends TestCase { + + public void testMultipartFormContent() throws Exception { + String contentType = "multipart/form-data; boundary=foo"; + String headlessContent = "\r\n" + + "--foo\r\nContent-Disposition: form-data; name=\"field01\"" + + "\r\n" + + "\r\n" + + "this stuff\r\n" + + "--foo\r\n" + + "Content-Disposition: form-data; name=\"field02\"\r\n" + + "\r\n" + + "that stuff\r\n" + + "--foo\r\n" + + "Content-Disposition: form-data; name=\"field03\"; filename=\"mypic.jpg\"\r\n" + + "Content-Type: image/jpeg\r\n" + "\r\n" + + "all kind of stuff\r\n" + "--foo--\r\n"; + + MimeEntityConfig mimeEntityConfig = new MimeEntityConfig(); + mimeEntityConfig.setDefaultContentType(contentType); + Message message = new Message(new ByteArrayInputStream(headlessContent + .getBytes("UTF-8")), mimeEntityConfig); + assertEquals("multipart/form-data", message.getMimeType()); + assertEquals(1, message.getHeader().getFields().size()); + ContentTypeField contentTypeField = ((ContentTypeField) message + .getHeader().getField(FieldName.CONTENT_TYPE)); + assertEquals("foo", contentTypeField.getBoundary()); + Multipart multipart = (Multipart) message.getBody(); + assertEquals(3, multipart.getCount()); + } +}