You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rd...@apache.org on 2008/05/25 20:42:24 UTC

svn commit: r660013 - in /james/mime4j/trunk/src: main/java/org/apache/james/mime4j/message/ main/java/org/apache/james/mime4j/util/ test/java/org/apache/james/mime4j/ test/java/org/apache/james/mime4j/message/

Author: rdonkin
Date: Sun May 25 11:42:23 2008
New Revision: 660013

URL: http://svn.apache.org/viewvc?rev=660013&view=rev
Log:
Confirmed and fixed MIME4J-37 Wrong implementation of TempFileBinaryBody.writeTo https://issues.apache.org/jira/browse/MIME4J-37 for the binary Base64 encoded case only. Binaries transfer encoded with printed-quotable.

Added:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/CodecUtil.java   (contents, props changed)
      - copied, changed from r659933, james/mime4j/trunk/src/test/java/org/apache/james/mime4j/EncodeUtils.java
Modified:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BinaryBody.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/MessageUtils.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/ExampleMail.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageWriteToTest.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BinaryBody.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BinaryBody.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BinaryBody.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/BinaryBody.java Sun May 25 11:42:23 2008
@@ -35,7 +35,7 @@
      * Gets a <code>InputStream</code> which reads the bytes of the
      * body.
      * 
-     * @return the stream.
+     * @return the stream, transfer decoded
      * @throws IOException on I/O errors.
      */
     InputStream getInputStream() throws IOException;

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java Sun May 25 11:42:23 2008
@@ -28,12 +28,9 @@
 import org.apache.james.mime4j.ContentHandler;
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.MimeStreamParser;
-import org.apache.james.mime4j.decoder.Base64InputStream;
-import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
 import org.apache.james.mime4j.field.Field;
 import org.apache.james.mime4j.field.UnstructuredField;
 import org.apache.james.mime4j.util.MessageUtils;
-import org.apache.james.mime4j.util.MimeUtil;
 
 
 /**
@@ -99,7 +96,7 @@
         getHeader().writeTo(out, mode);
 
         final Body body = getBody();
-        body.writeTo(out, MessageUtils.LENIENT);
+        body.writeTo(out, mode);
     }
     
     private class MessageBuilder implements ContentHandler {
@@ -179,21 +176,16 @@
         /**
          * @see org.apache.james.mime4j.ContentHandler#body(org.apache.james.mime4j.BodyDescriptor, java.io.InputStream)
          */
-        public void body(BodyDescriptor bd, InputStream is) throws IOException {
+        public void body(BodyDescriptor bd, final InputStream is) throws IOException {
             expect(Entity.class);
             
-            String enc = bd.getTransferEncoding();
-            if (MimeUtil.ENC_BASE64.equals(enc)) {
-                is = new Base64InputStream(is);
-            } else if (MimeUtil.ENC_QUOTED_PRINTABLE.equals(enc)) {
-                is = new QuotedPrintableInputStream(is);
-            }
+            final String enc = bd.getTransferEncoding();
             
-            Body body = null;
+            final Body body;
             if (bd.getMimeType().startsWith("text/")) {
                 body = new TempFileTextBody(is, bd.getCharset());
             } else {
-                body = new TempFileBinaryBody(is);
+                body = new TempFileBinaryBody(is, enc);
             }
             
             ((Entity) stack.peek()).setBody(body);
@@ -252,7 +244,7 @@
         }
         
         /**
-         * TODO: Implement me
+         * TODO: Implement me... but how?
          * 
          * @see org.apache.james.mime4j.ContentHandler#raw(java.io.InputStream)
          */

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java Sun May 25 11:42:23 2008
@@ -208,7 +208,8 @@
             writer.write(boundary);
             writer.write(MessageUtils.CRLF);
             writer.flush();
-            ((BodyPart) bodyParts.get(i)).writeTo(out, mode);
+            final BodyPart bodyPart = (BodyPart) bodyParts.get(i);
+            bodyPart.writeTo(out, mode);
             writer.write(MessageUtils.CRLF);
         }
 
@@ -216,8 +217,8 @@
         writer.write(boundary);
         writer.write("--");
         writer.write(MessageUtils.CRLF);
-        writer.write(getEpilogue());
-        writer.write(MessageUtils.CRLF);
+        final String epilogue = getEpilogue();
+        writer.write(epilogue);
         writer.flush();
     }
 }

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/TempFileBinaryBody.java Sun May 25 11:42:23 2008
@@ -24,8 +24,10 @@
 import java.io.OutputStream;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.james.mime4j.decoder.Base64InputStream;
+import org.apache.james.mime4j.decoder.QuotedPrintableInputStream;
+import org.apache.james.mime4j.util.CodecUtil;
+import org.apache.james.mime4j.util.MimeUtil;
 import org.apache.james.mime4j.util.TempFile;
 import org.apache.james.mime4j.util.TempPath;
 import org.apache.james.mime4j.util.TempStorage;
@@ -38,10 +40,10 @@
  * @version $Id: TempFileBinaryBody.java,v 1.2 2004/10/02 12:41:11 ntherning Exp $
  */
 class TempFileBinaryBody extends AbstractBody implements BinaryBody {
-    private static Log log = LogFactory.getLog(TempFileBinaryBody.class);
     
     private Entity parent = null;
     private TempFile tempFile = null;
+    private final String transferEncoding;
 
     /**
      * Use the given InputStream to build the TemporyFileBinaryBody
@@ -49,13 +51,22 @@
      * @param is the InputStream to use as source
      * @throws IOException
      */
-    public TempFileBinaryBody(InputStream is) throws IOException {
+    public TempFileBinaryBody(final InputStream is, final String transferEncoding) throws IOException {
         
+        this.transferEncoding = transferEncoding;
         TempPath tempPath = TempStorage.getInstance().getRootTempPath();
         tempFile = tempPath.createTempFile("attachment", ".bin");
         
         OutputStream out = tempFile.getOutputStream();
-        IOUtils.copy(is, out);
+        final InputStream decodedStream;
+        if (MimeUtil.ENC_BASE64.equals(transferEncoding)) {
+            decodedStream = new Base64InputStream(is);
+        } else if (MimeUtil.ENC_QUOTED_PRINTABLE.equals(transferEncoding)) {
+            decodedStream = new QuotedPrintableInputStream(is);
+        } else {
+            decodedStream = is;
+        }
+        IOUtils.copy(decodedStream, out);
         out.close();
     }
     
@@ -84,6 +95,14 @@
      * @see org.apache.james.mime4j.message.Body#writeTo(java.io.OutputStream, int)
      */
     public void writeTo(OutputStream out, int mode) throws IOException {
-	IOUtils.copy(getInputStream(),out);
+        final InputStream inputStream = getInputStream();
+        if (MimeUtil.ENC_BASE64.equals(transferEncoding)) {
+            CodecUtil.encodeBase64(inputStream, out);
+            out.write(CodecUtil.CRLF_CRLF);
+        } else if (MimeUtil.ENC_QUOTED_PRINTABLE.equals(transferEncoding)) {
+            IOUtils.copy(inputStream,out);
+        } else {
+            IOUtils.copy(inputStream,out);
+        }
     }
 }

Copied: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/CodecUtil.java (from r659933, james/mime4j/trunk/src/test/java/org/apache/james/mime4j/EncodeUtils.java)
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/CodecUtil.java?p2=james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/CodecUtil.java&p1=james/mime4j/trunk/src/test/java/org/apache/james/mime4j/EncodeUtils.java&r1=659933&r2=660013&rev=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/EncodeUtils.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/CodecUtil.java Sun May 25 11:42:23 2008
@@ -17,95 +17,131 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.mime4j;
+package org.apache.james.mime4j.util;
 
-
-public class EncodeUtils {
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Utility methods related to codecs.
+ */
+public class CodecUtil {
+    
+    
+    public static final byte[] CRLF = {'\r', '\n'};
     
-    public static final int MASK = 0x3F;
-    public static final int FIRST_MASK = MASK << 18; 
-    public static final int SECOND_MASK = MASK << 12; 
-    public static final int THIRD_MASK = MASK << 6; 
-    public static final int FORTH_MASK = MASK; 
-    
-    public static final byte[] ENCODING = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
-        'O', 'P' ,'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
-        'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
-        '4', '5', '6', '7', '8', '9', '+', '/'};
-    
-    public static final void main(String[] args) throws Exception {
-        byte[] bytes = {(byte) 0, (byte) 128, (byte) 0};
-        System.out.println(new String(toBase64(bytes)));
-        System.out.println(new String(toBase64("Hello, World".getBytes())));
-        System.out.println(new String(toBase64("Monday".getBytes())));
-        System.out.println(new String(toBase64("M\u00F6nchengladbach\r\n".getBytes("ISO-8859-1"))));
+    public static final byte[] CRLF_CRLF = {'\r', '\n', '\r', '\n'};
+    
+    private static final int DEFAULT_ENCODING_BUFFER_SIZE = 1024;
+    
+    /**
+     * Encodes the given stream using Base64.
+     * @param in not null
+     * @param out not null 
+     * @throws IOException
+     */
+    public static void encodeBase64(final InputStream in, final OutputStream out) throws IOException {
+        Base64Encoder encoder = new Base64Encoder(DEFAULT_ENCODING_BUFFER_SIZE);
+        encoder.encode(in, out);
     }
     
-    public static byte[] toBase64(byte[] in) {
-        int inputLength = in.length;
-        int outputLength = (int) Math.floor((4*inputLength) / 3f) + 3;
-        outputLength = outputLength + 2 * (int) Math.floor(outputLength / 76f);
-        byte[] results = new byte[outputLength];
-        int inputIndex = 0;
-        int outputIndex = 0;
-        while (inputLength - inputIndex > 2) {
-            int one = (toInt(in[inputIndex++]) << 16);
-            int two = (toInt(in[inputIndex++]) << 8);
-            int three = toInt(in[inputIndex++]);
-            int quantum = one | two | three;
-            int index = (quantum & FIRST_MASK) >> 18;
-            outputIndex = setResult(results, outputIndex, ENCODING[index]);
-            index = (quantum & SECOND_MASK) >> 12;
-            outputIndex = setResult(results, outputIndex, ENCODING[index]);
-            index = (quantum & THIRD_MASK) >> 6;
-            outputIndex = setResult(results, outputIndex, ENCODING[index]);
-            index = (quantum & FORTH_MASK);
-            outputIndex = setResult(results, outputIndex, ENCODING[index]);
-        }
-        
-        switch (inputLength - inputIndex) {
-            case 1:
-                int quantum = in[inputIndex++] << 16;
+    private static final class Base64Encoder {
+        private static final int MASK = 0x3F;
+        private static final int FIRST_MASK = MASK << 18; 
+        private static final int SECOND_MASK = MASK << 12; 
+        private static final int THIRD_MASK = MASK << 6; 
+        private static final int FORTH_MASK = MASK; 
+        
+        private static final byte[] ENCODING = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+            'O', 'P' ,'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+            'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+            '4', '5', '6', '7', '8', '9', '+', '/'};
+        
+        private final byte[] in;
+        private final byte[] out;
+        
+        public Base64Encoder(final int inputBufferSize) {
+            in = new byte[inputBufferSize];
+            int outputBufferSize = ((int) Math.floor((4*inputBufferSize) / 3f) + 3);
+            outputBufferSize = outputBufferSize + 2 * (int) Math.floor(outputBufferSize / 76f);
+            out = new byte[outputBufferSize];            
+        }
+        
+        public void encode(final InputStream inStream, final OutputStream outStream) throws IOException {
+            int inputLength = inStream.read(in);
+            while (inputLength > -1) {
+                int outputLength = encodeInputBuffer(inputLength);
+                if (outputLength > 0) {
+                    outStream.write(out, 0, outputLength);
+                }
+                inputLength = inStream.read(in);
+            }
+        }
+        
+        private int encodeInputBuffer(final int inputLength) {
+            if (inputLength == 0) {
+                return 0;
+            }
+            int inputIndex = 0;
+            int outputIndex = 0;
+            while (inputLength - inputIndex > 2) {
+                int one = (toInt(in[inputIndex++]) << 16);
+                int two = (toInt(in[inputIndex++]) << 8);
+                int three = toInt(in[inputIndex++]);
+                int quantum = one | two | three;
                 int index = (quantum & FIRST_MASK) >> 18;
-                outputIndex = setResult(results, outputIndex, ENCODING[index]);
-                index = (quantum & SECOND_MASK) >> 12;
-                outputIndex = setResult(results, outputIndex, ENCODING[index]);
-                outputIndex = setResult(results, outputIndex, (byte) '=');
-                outputIndex = setResult(results, outputIndex, (byte) '=');
-                break;
-                
-            case 2:
-                quantum = (in[inputIndex++] << 16) + (in[inputIndex++] << 8);
-                index = (quantum & FIRST_MASK) >> 18;
-                outputIndex = setResult(results, outputIndex, ENCODING[index]);
+                outputIndex = setResult(out, outputIndex, ENCODING[index]);
                 index = (quantum & SECOND_MASK) >> 12;
-                outputIndex = setResult(results, outputIndex, ENCODING[index]);
+                outputIndex = setResult(out, outputIndex, ENCODING[index]);
                 index = (quantum & THIRD_MASK) >> 6;
-                outputIndex = setResult(results, outputIndex, ENCODING[index]);
-                outputIndex = setResult(results, outputIndex, (byte) '=');
-                break;
+                outputIndex = setResult(out, outputIndex, ENCODING[index]);
+                index = (quantum & FORTH_MASK);
+                outputIndex = setResult(out, outputIndex, ENCODING[index]);
+            }
+            
+            switch (inputLength - inputIndex) {
+                case 1:
+                    int quantum = in[inputIndex++] << 16;
+                    int index = (quantum & FIRST_MASK) >> 18;
+                    outputIndex = setResult(out, outputIndex, ENCODING[index]);
+                    index = (quantum & SECOND_MASK) >> 12;
+                    outputIndex = setResult(out, outputIndex, ENCODING[index]);
+                    outputIndex = setResult(out, outputIndex, (byte) '=');
+                    outputIndex = setResult(out, outputIndex, (byte) '=');
+                    break;
+                    
+                case 2:
+                    quantum = (in[inputIndex++] << 16) + (in[inputIndex++] << 8);
+                    index = (quantum & FIRST_MASK) >> 18;
+                    outputIndex = setResult(out, outputIndex, ENCODING[index]);
+                    index = (quantum & SECOND_MASK) >> 12;
+                    outputIndex = setResult(out, outputIndex, ENCODING[index]);
+                    index = (quantum & THIRD_MASK) >> 6;
+                    outputIndex = setResult(out, outputIndex, ENCODING[index]);
+                    outputIndex = setResult(out, outputIndex, (byte) '=');
+                    break;
+            }
+            
+            return outputIndex;
         }
         
-        return results;
-    }
-
-    private static int toInt(byte b) {
-        return (int)(b & 255);
-    }
-
-
-    private static int setResult(byte[] results, int outputIndex, byte value) {
-        results[outputIndex++] = value;
-        outputIndex = checkLineLength(results, outputIndex);
-        return outputIndex;
-    }
+        private int toInt(byte b) {
+            return (int)(b & 255);
+        }
 
+        private int setResult(byte[] results, int outputIndex, byte value) {
+            results[outputIndex++] = value;
+            outputIndex = checkLineLength(results, outputIndex);
+            return outputIndex;
+        }
 
-    private static int checkLineLength(byte[] results, int outputIndex) {
-        if (outputIndex == 76 || outputIndex > 76 && (outputIndex - 2*Math.floor(outputIndex/76f - 1)) % 76 == 0) {
-            results[outputIndex++] = '\r';
-            results[outputIndex++] = '\n';
+        private int checkLineLength(byte[] results, int outputIndex) {
+            if (outputIndex == 76 || outputIndex > 76 && (outputIndex - 2*Math.floor(outputIndex/76f - 1)) % 76 == 0) {
+                results[outputIndex++] = '\r';
+                results[outputIndex++] = '\n';
+            }
+            return outputIndex;
         }
-        return outputIndex;
     }
 }

Propchange: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/CodecUtil.java
------------------------------------------------------------------------------
    svn:mergeinfo = 

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/MessageUtils.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/MessageUtils.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/MessageUtils.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/MessageUtils.java Sun May 25 11:42:23 2008
@@ -38,7 +38,7 @@
     public static final Charset ISO_8859_1 = CharsetUtil.getCharset("ISO-8859-1");
     
     public static final Charset DEFAULT_CHARSET = ASCII;
-
+    
     public static final String CRLF = "\r\n";
     
     public static boolean isASCII(char ch) {
@@ -57,5 +57,4 @@
         }
         return true;
     }
-    
 }

Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/ExampleMail.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/ExampleMail.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/ExampleMail.java (original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/ExampleMail.java Sun May 25 11:42:23 2008
@@ -25,6 +25,157 @@
     public static final Charset US_ASCII = Charset.forName("US-ASCII");
     public static final Charset LATIN1 = Charset.forName("ISO-8859-1");
     
+    public static final String MULTIPART_WITH_BINARY_ATTACHMENTS = 
+        "Return-Path: <ro...@blueyonder.co.uk>\r\n" +
+        "Received: (qmail 18554 invoked from network); 25 May 2008 14:38:53 -0000\r\n" +
+        "Received: from unknown (HELO p3presmtp01-16.prod.phx3.secureserver.net)\r\n" +
+        "        ([208.109.80.165]) (envelope-sender <rd...@locus.apache.org>) by\r\n" +
+        "        smtp20-01.prod.mesa1.secureserver.net (qmail-1.03) with SMTP for\r\n" +
+        "        <as...@xmlmapt.org>; 25 May 2008 14:38:53 -0000\r\n" +
+        "Received: (qmail 9751 invoked from network); 25 May 2008 14:38:53 -0000\r\n" +
+        "Received: from minotaur.apache.org ([140.211.11.9]) (envelope-sender\r\n" +
+        "        <rd...@locus.apache.org>) by\r\n" +
+        "        p3presmtp01-16.prod.phx3.secureserver.net (qmail-ldap-1.03) with SMTP for\r\n" +
+        "        <as...@xmlmapt.org>; 25 May 2008 14:38:50 -0000\r\n" +
+        "Received: (qmail 46768 invoked by uid 1289); 25 May 2008 14:38:46 -0000\r\n" +
+        "Delivered-To: rdonkin@locus.apache.org\r\n" +
+        "Received: (qmail 46763 invoked from network); 25 May 2008 14:38:46 -0000\r\n" +
+        "Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by\r\n" +
+        "        minotaur.apache.org with SMTP; 25 May 2008 14:38:46 -0000\r\n" +
+        "Received: (qmail 61275 invoked by uid 500); 25 May 2008 14:38:48 -0000\r\n" +
+        "Delivered-To: apmail-rdonkin@apache.org\r\n" +
+        "Delivered-To: rob@localhost\r\n" +
+        "Delivered-To: rob@localhost\r\n" +
+        "Received: (qmail 61272 invoked by uid 99); 25 May 2008 14:38:48 -0000\r\n" +
+        "Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136)\r\n" +
+        "        by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 25 May 2008 07:38:48 -0700\r\n" +
+        "X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS\r\n" +
+        "X-Spam-Check-By: apache.org\r\n" +
+        "Received-SPF: pass (athena.apache.org: domain of\r\n" +
+        "        robertburrelldonkin@blueyonder.co.uk designates 195.188.213.5 as permitted\r\n" +
+        "        sender)\r\n" +
+        "Received: from [195.188.213.5] (HELO smtp-out2.blueyonder.co.uk)\r\n" +
+        "        (195.188.213.5) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 25 May 2008\r\n" +
+        "        14:38:00 +0000\r\n" +
+        "Received: from [172.23.170.140] (helo=anti-virus02-07) by\r\n" +
+        "        smtp-out2.blueyonder.co.uk with smtp (Exim 4.52) id 1K0HMV-00087e-HY for\r\n" +
+        "        rdonkin@apache.org; Sun, 25 May 2008 15:38:15 +0100\r\n" +
+        "Received: from [82.38.65.6] (helo=[10.0.0.27]) by\r\n" +
+        "        asmtp-out5.blueyonder.co.uk with esmtpa (Exim 4.52) id 1K0HMU-0001A2-3q for\r\n" +
+        "        rdonkin@apache.org; Sun, 25 May 2008 15:38:14 +0100\r\n" +
+        "Subject: This is an example of a multipart mixed email with image content\r\n" +
+        "From: Robert Burrell Donkin <ro...@blueyonder.co.uk>\r\n" +
+        "To: Robert Burrell Donkin <rd...@apache.org>\r\n" +
+        "Content-Type: multipart/mixed; boundary=\"=-tIdGYVstQJghyEDATnJ+\"\r\n" +
+        "Date: Sun, 25 May 2008 15:38:13 +0100\r\n" +
+        "Message-Id: <12...@localhost>\r\n" +
+        "Mime-Version: 1.0\r\n" +
+        "X-Mailer: Evolution 2.12.3 \r\n" +
+        "X-Virus-Checked: Checked by ClamAV on apache.org\r\n" +
+        "X-Nonspam: None\r\n" +
+        "X-fetched-from: mail.xmlmapt.org\r\n" +
+        "X-Evolution-Source: imap://rob@thebes/\r\n" +
+        "\r\n" +
+        "\r\n" +
+        "--=-tIdGYVstQJghyEDATnJ+\r\n" +
+        "Content-Type: text/plain\r\n" +
+        "Content-Transfer-Encoding: 7bit\r\n" +
+        "\r\n" +
+        "Licensed to the Apache Software Foundation (ASF) under one\r\n" +
+        "or more contributor license agreements.  See the NOTICE file\r\n" +
+        "distributed with this work for additional information\r\n" +
+        "regarding copyright ownership.  The ASF licenses this file\r\n" +
+        "to you under the Apache License, Version 2.0 (the\r\n" +
+        "\"License\"); you may not use this file except in compliance\r\n" +
+        "with the License.  You may obtain a copy of the License at\r\n" +
+        "\r\n" +
+        "    http://www.apache.org/licenses/LICENSE-2.0\r\n" +
+        " \r\n" +
+        "Unless required by applicable law or agreed to in writing,\r\n" +
+        "software distributed under the License is distributed on an\r\n" +
+        "\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\n" +
+        "KIND, either express or implied.  See the License for the\r\n" +
+        "specific language governing permissions and limitations\r\n" +
+        "under the License.\r\n" +
+        " \r\n" +
+        "\r\n" +
+        "--=-tIdGYVstQJghyEDATnJ+\r\n" +
+        "Content-Disposition: attachment; filename=blob.png\r\n" +
+        "Content-Type: image/png; name=blob.png\r\n" +
+        "Content-Transfer-Encoding: base64\r\n" +
+        "\r\n" +
+        "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAL\r\n" +
+        "EwAACxMBAJqcGAAAAAd0SU1FB9gFGQ4iJ99ufcYAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRo\r\n" +
+        "IEdJTVBXgQ4XAAAA0ElEQVQY02XMwUrDQBhF4XsnkyYhjWJaCloEN77/a/gERVwJLQiiNjYmbTqZ\r\n" +
+        "/7qIG/VsPziMTw+23Wj/ovZdMQJgViCvWNVusfa23djuUf2nugbnI2RynkWF5a2Fwdvrs7q9vhqE\r\n" +
+        "E2QAEIO6BhZBerUf6luMw49NyTR0OLw5kJD9sqk4Ipwc6GAREv5n5piXTDOQfy1JMSs8ZgXKq2kF\r\n" +
+        "iwDgEriEecnLlefFEmGAIvqD4ggJJNMM85qLtXfX9xYGuEQ+4/kIi0g88zlXd66++QaQDG5GPZyp\r\n" +
+        "rQAAAABJRU5ErkJggg==\r\n" +
+        "\r\n" +
+        "\r\n" +
+        "--=-tIdGYVstQJghyEDATnJ+\r\n" +
+        "Content-Disposition: attachment; filename=blob.png\r\n" +
+        "Content-Type: image/png; name=blob.png\r\n" +
+        "Content-Transfer-Encoding: base64\r\n" +
+        "\r\n" +
+        "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAL\r\n" +
+        "EwAACxMBAJqcGAAAAAd0SU1FB9gFGQ4iJ99ufcYAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRo\r\n" +
+        "IEdJTVBXgQ4XAAAA0ElEQVQY02XMwUrDQBhF4XsnkyYhjWJaCloEN77/a/gERVwJLQiiNjYmbTqZ\r\n" +
+        "/7qIG/VsPziMTw+23Wj/ovZdMQJgViCvWNVusfa23djuUf2nugbnI2RynkWF5a2Fwdvrs7q9vhqE\r\n" +
+        "E2QAEIO6BhZBerUf6luMw49NyTR0OLw5kJD9sqk4Ipwc6GAREv5n5piXTDOQfy1JMSs8ZgXKq2kF\r\n" +
+        "iwDgEriEecnLlefFEmGAIvqD4ggJJNMM85qLtXfX9xYGuEQ+4/kIi0g88zlXd66++QaQDG5GPZyp\r\n" +
+        "rQAAAABJRU5ErkJggg==\r\n" +
+        "\r\n" +
+        "\r\n" +
+        "--=-tIdGYVstQJghyEDATnJ+\r\n" +
+        "Content-Disposition: attachment; filename=rhubarb.txt\r\n" +
+        "Content-Type: text/plain; name=rhubarb.txt; charset=us-ascii\r\n" +
+        "Content-Transfer-Encoding: quoted-printable\r\n" +
+        "\r\n" +
+        "Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhu=\r\n" +
+        "barb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubar=\r\n" +
+        "b Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb R=\r\n" +
+        "hubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhub=\r\n" +
+        "arb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb=\r\n" +
+        " Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rh=\r\n" +
+        "ubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhuba=\r\n" +
+        "rb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb =\r\n" +
+        "Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhu=\r\n" +
+        "barb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubar=\r\n" +
+        "b Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb R=\r\n" +
+        "hubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhub=\r\n" +
+        "arb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb=\r\n" +
+        " Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rh=\r\n" +
+        "ubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhuba=\r\n" +
+        "rb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb =\r\n" +
+        "Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhu=\r\n" +
+        "barb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubar=\r\n" +
+        "b Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb R=\r\n" +
+        "hubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhub=\r\n" +
+        "arb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb=\r\n" +
+        " Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rh=\r\n" +
+        "ubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhuba=\r\n" +
+        "rb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb =\r\n" +
+        "Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhu=\r\n" +
+        "barb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubar=\r\n" +
+        "b Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb R=\r\n" +
+        "hubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhub=\r\n" +
+        "arb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb=\r\n" +
+        " Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rh=\r\n" +
+        "ubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhuba=\r\n" +
+        "rb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb =\r\n" +
+        "Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhu=\r\n" +
+        "barb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubar=\r\n" +
+        "b Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb R=\r\n" +
+        "hubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhub=\r\n" +
+        "arb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb=\r\n" +
+        " Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rh=\r\n" +
+        "ubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhuba=\r\n" +
+        "rb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb =\r\n" +
+        "Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb Rhubarb\r\n" +
+        "\r\n" +
+        "--=-tIdGYVstQJghyEDATnJ+--\r\n";
+    
     public static final String ONE_PART_MIME_ASCII_BODY = "A single part MIME mail.\r\n";
 
     public static final String RFC822_SIMPLE_BODY = "This is a very simple email.\r\n";
@@ -246,7 +397,8 @@
     public static final byte[] RFC822_SIMPLE_BYTES = US_ASCII.encode(RFC_SIMPLE).array();
     public static final byte[] ONE_PART_MIME_ASCII_BYTES = US_ASCII.encode(ONE_PART_MIME_ASCII).array();
     public static final byte[] ONE_PART_MIME_8859_BYTES = LATIN1.encode(ONE_PART_MIME_8859).array();
-    
+    public static final byte[] MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES = US_ASCII.encode(MULTIPART_WITH_BINARY_ATTACHMENTS).array();
+     
     public static final byte[] ascii(String text) {
         
         return US_ASCII.encode(text).array();

Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageWriteToTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageWriteToTest.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageWriteToTest.java (original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageWriteToTest.java Sun May 25 11:42:23 2008
@@ -41,6 +41,7 @@
         assertFalse("Not multipart", message.isMultipart());
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         message.writeTo(out, MessageUtils.STRICT_IGNORE);
+        assertEquals(out.toByteArray(), ExampleMail.RFC822_SIMPLE_BYTES);
     }
     
     public void testSimpleMailStrictError() throws Exception {
@@ -48,6 +49,7 @@
         assertFalse("Not multipart", message.isMultipart());
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         message.writeTo(out, MessageUtils.STRICT_ERROR);
+        assertEquals(out.toByteArray(), ExampleMail.RFC822_SIMPLE_BYTES);
     }
     
     public void testSimpleMailLenient() throws Exception {
@@ -55,6 +57,40 @@
         assertFalse("Not multipart", message.isMultipart());
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         message.writeTo(out, MessageUtils.LENIENT);
+        assertEquals(out.toByteArray(), ExampleMail.RFC822_SIMPLE_BYTES);
+    }
+    
+    private void assertEquals(byte[] expected, byte[] actual) {
+        StringBuffer buffer = new StringBuffer(expected.length);
+        assertEquals(expected.length, actual.length);
+        for (int i = 0; i < actual.length; i++) {
+            buffer.append((char)actual[i]);
+            assertEquals("Mismatch@" + i, expected[i], actual[i]);
+        }
+    }
+    
+    public void testBinaryAttachmentLenient() throws Exception {
+        Message message = createMessage(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES);
+        assertTrue("Is multipart", message.isMultipart());
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        message.writeTo(out, MessageUtils.LENIENT);
+        assertEquals(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES, out.toByteArray());
+    }
+    
+    public void testBinaryAttachmentStrictError() throws Exception {
+        Message message = createMessage(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES);
+        assertTrue("Is multipart", message.isMultipart());
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        message.writeTo(out, MessageUtils.STRICT_ERROR);
+        assertEquals(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES, out.toByteArray());
+    }
+    
+    public void testBinaryAttachmentStrictIgnore() throws Exception {
+        Message message = createMessage(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES);
+        assertTrue("Is multipart", message.isMultipart());
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        message.writeTo(out, MessageUtils.STRICT_IGNORE);
+        assertEquals(ExampleMail.MULTIPART_WITH_BINARY_ATTACHMENTS_BYTES, out.toByteArray());
     }
     
     private Message createMessage(byte[] octets) throws Exception {

Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java?rev=660013&r1=660012&r2=660013&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java (original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java Sun May 25 11:42:23 2008
@@ -85,8 +85,7 @@
             "Content-Type: text/plain\r\n" +
             "\r\n" +
             "all kind of stuff\r\n" +
-            "--foo--\r\n" +
-            "\r\n";
+            "--foo--\r\n";
         String s = out.toString("US-ASCII");
         assertEquals(expected, s);
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org