Index: core/src/test/java/org/apache/james/mime4j/message/MessageHeadlessParserTest.java =================================================================== --- core/src/test/java/org/apache/james/mime4j/message/MessageHeadlessParserTest.java (revision 0) +++ core/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 config = new MimeEntityConfig(); + config.setHeadlessContentType(contentType); + + Message message = new Message(new ByteArrayInputStream(headlessContent + .getBytes("UTF-8")), config); + assertEquals(message.getMimeType(), "multipart/form-data"); + assertEquals(message.getHeader().getFields().size(), 1); + ContentTypeField contentTypeField = ((ContentTypeField) message + .getHeader().getField(FieldName.CONTENT_TYPE)); + assertEquals(contentTypeField.getBoundary(), "foo"); + Multipart multipart = (Multipart) message.getBody(); + assertEquals(multipart.getCount(), 3); + } +} Property changes on: core/src/test/java/org/apache/james/mime4j/message/MessageHeadlessParserTest.java ___________________________________________________________________ Added: svn:eol-style + native Index: core/src/main/java/org/apache/james/mime4j/message/Message.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/message/Message.java (revision 766288) +++ core/src/main/java/org/apache/james/mime4j/message/Message.java (working copy) @@ -136,9 +136,20 @@ StorageProvider storageProvider) throws IOException, MimeIOException { try { + final String headlessContentType; + if (config == null) { + headlessContentType = null; + } else { + headlessContentType = config.getHeadlessContentType(); + } MimeStreamParser parser = new MimeStreamParser(config); parser.setContentHandler(new MessageBuilder(this, storageProvider)); parser.parse(is); + if (headlessContentType != null) { + Header header = obtainHeader(); + header.addField(Fields.contentType(headlessContentType)); + } + } catch (MimeException e) { throw new MimeIOException(e); } Index: core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java (revision 766288) +++ core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java (working copy) @@ -128,7 +128,7 @@ * internal state. */ public void parse(InputStream stream) { - doParse(stream, null); + doParse(stream, config.getHeadlessContentType()); } /** Instructs the {@code MimeTokenStream} to parse the given content with @@ -139,6 +139,7 @@ *
* If the {@code MimeTokenStream} has already been in use, resets the streams * internal state. + * @deprecated set {@link MimeEntityConfig#setHeadlessContentType(String)} */ public void parseHeadless(InputStream stream, String contentType) { if (contentType == null) { @@ -252,6 +253,16 @@ } /** + * Gets the MIME entity configuration. + * Note that mutating values whilst parsing is in progress + * may have interesting results. + * @return not null + */ + public MimeEntityConfig getConfiguration() { + return config; + } + + /** * This method returns the raw entity, preamble, or epilogue contents. * * This method is valid, if {@link #getState()} returns either of Index: core/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java (revision 766288) +++ core/src/main/java/org/apache/james/mime4j/parser/MimeEntityConfig.java (working copy) @@ -22,7 +22,8 @@ import org.apache.james.mime4j.MimeException; /** - * MIME entity configuration + * MIME entity configuration. + * This parameter object provides the parsing configuration. */ public final class MimeEntityConfig implements Cloneable { @@ -32,6 +33,7 @@ private int maxHeaderCount; private long maxContentLen; private boolean countLineNumbers; + private String contentType; public MimeEntityConfig() { this.maximalBodyDescriptor = false; @@ -40,6 +42,7 @@ this.maxHeaderCount = 1000; this.maxContentLen = -1; this.countLineNumbers = false; + this.contentType = null; } public boolean isMaximalBodyDescriptor() { @@ -158,6 +161,43 @@ public boolean isCountLineNumbers() { return countLineNumbers; } + + /** + *Gets the content type to be used when parsing a headless mime document.
+ *+ * Any not null value indicates that headless parsing should be forced. + * Headless parsing assumes that the document has no initial headers + * attached, and begins with the message body. + *
+ * @return the content type when parsing a head less document, + * null otherwise + */ + public String getHeadlessContentType() { + return contentType; + } + + /** + * Should be parser be set to headless? + * @return true when the parser should be set to headless, + * false otherwise + */ + public boolean isHeadless() { + return contentType != null; + } + + /** + *Sets the content type to be used when parsing a headless mime document.
+ *+ * Any not null value indicates that headless parsing should be forced. + * Headless parsing assumes that the document has no initial headers + * attached, and begins with the message body. + *
+ * @param contentType the content type when parsing a head less document, + * null otherwise + */ + public void setHeadlessContentType(final String contentType) { + this.contentType = contentType; + } @Override public MimeEntityConfig clone() { Index: core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java =================================================================== --- core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java (revision 766288) +++ core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java (working copy) @@ -86,6 +86,7 @@ * @throws IOException on I/O errors. */ public void parse(InputStream is) throws MimeException, IOException { + boolean skipNextHeaderEnd = mimeTokenStream.getConfiguration().isHeadless(); mimeTokenStream.parse(is); OUTER: for (;;) { int state = mimeTokenStream.getState(); @@ -104,7 +105,11 @@ handler.endBodyPart(); break; case MimeTokenStream.T_END_HEADER: - handler.endHeader(); + if (!skipNextHeaderEnd) { + handler.endHeader(); + } else { + skipNextHeaderEnd = false; + } break; case MimeTokenStream.T_END_MESSAGE: handler.endMessage();