Hi Stefano,

DecodeMonitor is missing the asl2 header ....

Bye,
Norman


2010/1/3  <[email protected]>:
> Author: bago
> Date: Sun Jan  3 21:47:38 2010
> New Revision: 895486
>
> URL: http://svn.apache.org/viewvc?rev=895486&view=rev
> Log:
> Introduced a DecodeMonitor object with 2 basic implementations (SILENT, 
> STRICT). The decoding classes/methods in codec have been upgraded to use a 
> DecodeMonitor instead of the internal boolean strict. Fixed a bug in 
> QuotedPrintableInputStream that sometimes was not converting a lonely LF to 
> CRLF. Added some malformation monitoring to QuotedPrintableInputStream (lone 
> LF and lone CR are "monitored"). Added some more invalid data monitoring to 
> Base64InputStream that now "notifies" unexpected chars (non base64, non CR, 
> LF or SP). (MIME4J-158 + MIME4J-161)
>
> Added:
>    
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java
>    (with props)
> Modified:
>    
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java
>    
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java
>    
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java
>    
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java
>    
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableInputStreamTest.java
>    
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java
>
> Modified: 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java?rev=895486&r1=895485&r2=895486&view=diff
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java
>  (original)
> +++ 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/Base64InputStream.java
>  Sun Jan  3 21:47:38 2010
> @@ -22,16 +22,12 @@
>  import java.io.IOException;
>  import java.io.InputStream;
>
> -import org.apache.commons.logging.Log;
> -import org.apache.commons.logging.LogFactory;
>  import org.apache.james.mime4j.util.ByteArrayBuffer;
>
>  /**
>  * Performs Base-64 decoding on an underlying stream.
>  */
>  public class Base64InputStream extends InputStream {
> -    private static Log log = LogFactory.getLog(Base64InputStream.class);
> -
>     private static final int ENCODED_BUFFER_SIZE = 1536;
>
>     private static final int[] BASE64_DECODE = new int[256];
> @@ -50,7 +46,6 @@
>     private final byte[] singleByte = new byte[1];
>
>     private final InputStream in;
> -    private final boolean strict;
>     private final byte[] encoded;
>     private final ByteArrayBuffer decodedBuf;
>
> @@ -60,21 +55,27 @@
>     private boolean closed = false;
>     private boolean eof; // end of file or pad character reached
>
> -    protected Base64InputStream(int bufsize, InputStream in, boolean strict) 
> {
> +    private final DecodeMonitor monitor;
> +
> +    public Base64InputStream(InputStream in, DecodeMonitor monitor) {
> +        this(ENCODED_BUFFER_SIZE, in, monitor);
> +    }
> +
> +    protected Base64InputStream(int bufsize, InputStream in, DecodeMonitor 
> monitor) {
>         if (in == null)
>             throw new IllegalArgumentException();
>         this.encoded = new byte[bufsize];
>         this.decodedBuf = new ByteArrayBuffer(512);
>         this.in = in;
> -        this.strict = strict;
> +        this.monitor = monitor;
>     }
>
>     public Base64InputStream(InputStream in) {
> -        this(ENCODED_BUFFER_SIZE, in, false);
> +        this(in, false);
>     }
>
>     public Base64InputStream(InputStream in, boolean strict) {
> -        this(ENCODED_BUFFER_SIZE, in, strict);
> +        this(ENCODED_BUFFER_SIZE, in, strict ? DecodeMonitor.STRICT : 
> DecodeMonitor.SILENT);
>     }
>
>     @Override
> @@ -187,8 +188,13 @@
>                 }
>
>                 int decoded = BASE64_DECODE[value];
> -                if (decoded < 0) // -1: not a base64 char
> +                if (decoded < 0) { // -1: not a base64 char
> +                    if (value != 0x0D && value != 0x0A && value != 0x20) {
> +                        if (monitor.warn("Unexpected base64 byte: "+(byte) 
> value, "ignoring."))
> +                            throw new IOException("Unexpected base64 byte");
> +                    }
>                     continue;
> +                }
>
>                 data = (data << 6) | decoded;
>                 sextets++;
> @@ -269,18 +275,12 @@
>     }
>
>     private void handleUnexpectedEof(int sextets) throws IOException {
> -        if (strict)
> +        if (monitor.warn("Unexpected end of BASE64 stream", "dropping " + 
> sextets + " sextet(s)"))
>             throw new IOException("Unexpected end of BASE64 stream");
> -        else
> -            log.warn("Unexpected end of BASE64 stream; dropping " + sextets
> -                    + " sextet(s)");
>     }
>
>     private void handleUnexpecedPad(int sextets) throws IOException {
> -        if (strict)
> +        if (monitor.warn("Unexpected padding character", "dropping " + 
> sextets + " sextet(s)"))
>             throw new IOException("Unexpected padding character");
> -        else
> -            log.warn("Unexpected padding character; dropping " + sextets
> -                    + " sextet(s)");
>     }
>  }
>
> Added: 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java?rev=895486&view=auto
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java
>  (added)
> +++ 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java
>  Sun Jan  3 21:47:38 2010
> @@ -0,0 +1,46 @@
> +package org.apache.james.mime4j.codec;
> +
> +
> +/**
> + * This class is used to drive how decoder/parser should deal with malformed
> + * and unexpected data.
> + *
> + * 2 basic implementations are provided:
> + * STRICT return "true" on any occourence.
> + * SILENT ignores any problem.
> + *
> + * @see org.apache.james.mime4j.field.impl.LoggingMonitor for an example
> + * about logging malformations via Commons-logging.
> + */
> +public class DecodeMonitor {
> +
> +    /**
> +     * The STRICT monitor throws an exception on every event.
> +     */
> +    public static final DecodeMonitor STRICT = new DecodeMonitor() {
> +
> +       �...@override
> +        public boolean warn(String error, String dropDesc) {
> +            return true;
> +        }
> +
> +       �...@override
> +        public boolean isListening() {
> +            return true;
> +        }
> +    };
> +
> +    /**
> +     * The SILENT monitor ignore requests.
> +     */
> +    public static final DecodeMonitor SILENT = new DecodeMonitor();
> +
> +    public boolean warn(String error, String dropDesc) {
> +        return false;
> +    }
> +
> +    public boolean isListening() {
> +        return false;
> +    }
> +
> +}
>
> Propchange: 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Propchange: 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecodeMonitor.java
> ------------------------------------------------------------------------------
>    svn:mime-type = text/plain
>
> Modified: 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java?rev=895486&r1=895485&r2=895486&view=diff
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java
>  (original)
> +++ 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/DecoderUtil.java
>  Sun Jan  3 21:47:38 2010
> @@ -26,15 +26,12 @@
>  import java.util.regex.Matcher;
>  import java.util.regex.Pattern;
>
> -import org.apache.commons.logging.Log;
> -import org.apache.commons.logging.LogFactory;
>  import org.apache.james.mime4j.util.CharsetUtil;
>
>  /**
>  * Static methods for decoding strings, byte arrays and encoded words.
>  */
>  public class DecoderUtil {
> -    private static Log log = LogFactory.getLog(DecoderUtil.class);
>
>     private static final Pattern PATTERN_ENCODED_WORD = Pattern.compile(
>             "(.*?)=\\?([^\\?]+?)\\?(\\w)\\?([^\\?]+?)\\?=", Pattern.DOTALL);
> @@ -45,14 +42,14 @@
>      * @param s the string to decode.
>      * @return the decoded bytes.
>      */
> -    private static byte[] decodeQuotedPrintable(String s) {
> +    private static byte[] decodeQuotedPrintable(String s, DecodeMonitor 
> monitor) {
>         ByteArrayOutputStream baos = new ByteArrayOutputStream();
>
>         try {
>             byte[] bytes = s.getBytes("US-ASCII");
>
>             QuotedPrintableInputStream is = new QuotedPrintableInputStream(
> -                                               new 
> ByteArrayInputStream(bytes));
> +                                               new 
> ByteArrayInputStream(bytes), monitor);
>
>             int b = 0;
>             while ((b = is.read()) != -1) {
> @@ -60,7 +57,6 @@
>             }
>         } catch (IOException e) {
>             // This should never happen!
> -            log.error(e);
>             throw new IllegalStateException(e);
>         }
>
> @@ -71,16 +67,17 @@
>      * Decodes a string containing base64 encoded data.
>      *
>      * @param s the string to decode.
> +     * @param monitor
>      * @return the decoded bytes.
>      */
> -    private static byte[] decodeBase64(String s) {
> +    private static byte[] decodeBase64(String s, DecodeMonitor monitor) {
>         ByteArrayOutputStream baos = new ByteArrayOutputStream();
>
>         try {
>             byte[] bytes = s.getBytes("US-ASCII");
>
>             Base64InputStream is = new Base64InputStream(
> -                                        new ByteArrayInputStream(bytes));
> +                                        new ByteArrayInputStream(bytes), 
> monitor);
>
>             int b = 0;
>             while ((b = is.read()) != -1) {
> @@ -88,7 +85,6 @@
>             }
>         } catch (IOException e) {
>             // This should never happen!
> -            log.error(e);
>             throw new IllegalStateException(e);
>         }
>
> @@ -101,13 +97,14 @@
>      *
>      * @param encodedText the encoded text to decode.
>      * @param charset the Java charset to use.
> +     * @param monitor
>      * @return the decoded string.
>      * @throws UnsupportedEncodingException if the given Java charset isn't
>      *         supported.
>      */
> -    static String decodeB(String encodedText, String charset)
> +    static String decodeB(String encodedText, String charset, DecodeMonitor 
> monitor)
>             throws UnsupportedEncodingException {
> -        byte[] decodedBytes = decodeBase64(encodedText);
> +        byte[] decodedBytes = decodeBase64(encodedText, monitor);
>         return new String(decodedBytes, charset);
>     }
>
> @@ -121,23 +118,29 @@
>      * @throws UnsupportedEncodingException if the given Java charset isn't
>      *         supported.
>      */
> -    static String decodeQ(String encodedText, String charset)
> +    static String decodeQ(String encodedText, String charset, DecodeMonitor 
> monitor)
>             throws UnsupportedEncodingException {
>         encodedText = replaceUnderscores(encodedText);
>
> -        byte[] decodedBytes = decodeQuotedPrintable(encodedText);
> +        byte[] decodedBytes = decodeQuotedPrintable(encodedText, monitor);
>         return new String(decodedBytes, charset);
>     }
>
> +    static String decodeEncodedWords(String body)  {
> +        return decodeEncodedWords(body, DecodeMonitor.SILENT);
> +    }
> +
>     /**
>      * Decodes a string containing encoded words as defined by RFC 2047. 
> Encoded
>      * words have the form =?charset?enc?encoded-text?= where enc is either 
> 'Q'
>      * or 'q' for quoted-printable and 'B' or 'b' for base64.
>      *
> -     * @param body the string to decode.
> +     * @param body the string to decode
> +     * @param monitor the DecodeMonitor to be used.
>      * @return the decoded string.
> +     * @throws IllegalArgumentException only if the DecodeMonitor strategy 
> throws it (Strict parsing)
>      */
> -    public static String decodeEncodedWords(String body) {
> +    public static String decodeEncodedWords(String body, DecodeMonitor 
> monitor) throws IllegalArgumentException {
>         int tailIndex = 0;
>         boolean lastMatchValid = false;
>
> @@ -149,7 +152,8 @@
>             String encoding = matcher.group(3);
>             String encodedText = matcher.group(4);
>
> -            String decoded = tryDecodeEncodedWord(mimeCharset, encoding, 
> encodedText);
> +            String decoded = null;
> +            decoded = tryDecodeEncodedWord(mimeCharset, encoding, 
> encodedText, monitor);
>             if (decoded == null) {
>                 sb.append(matcher.group(0));
>             } else {
> @@ -173,61 +177,64 @@
>
>     // return null on error
>     private static String tryDecodeEncodedWord(final String mimeCharset,
> -            final String encoding, final String encodedText) {
> +            final String encoding, final String encodedText, DecodeMonitor 
> monitor) throws IllegalArgumentException {
>         String charset = CharsetUtil.toJavaCharset(mimeCharset);
>         if (charset == null) {
> -            if (log.isWarnEnabled()) {
> -                log.warn("MIME charset '" + mimeCharset + "' in encoded word 
> '"
> -                        + recombine(mimeCharset, encoding, encodedText) + "' 
> doesn't have a "
> -                        + "corresponding Java charset");
> -            }
> +            monitor(monitor, mimeCharset, encoding, encodedText, "leaving 
> word encoded",
> +                    "Mime charser '", mimeCharset, "' doesn't have a 
> corresponding Java charset");
>             return null;
>         } else if (!CharsetUtil.isDecodingSupported(charset)) {
> -            if (log.isWarnEnabled()) {
> -                log.warn("Current JDK doesn't support decoding of charset '"
> -                        + charset + "' (MIME charset '" + mimeCharset
> -                        + "' in encoded word '" + recombine(mimeCharset, 
> encoding, encodedText)
> -                        + "')");
> -            }
> +            monitor(monitor, mimeCharset, encoding, encodedText, "leaving 
> word encoded",
> +                    "Current JDK doesn't support decoding of charset '", 
> charset,
> +                    "' - MIME charset '", mimeCharset, "' in encoded word");
>             return null;
>         }
>
>         if (encodedText.length() == 0) {
> -            if (log.isWarnEnabled()) {
> -                log.warn("Missing encoded text in encoded word: '"
> -                        + recombine(mimeCharset, encoding, encodedText) + 
> "'");
> -            }
> +            monitor(monitor, mimeCharset, encoding, encodedText, "leaving 
> word encoded",
> +                    "Missing encoded text in encoded word");
>             return null;
>         }
>
>         try {
>             if (encoding.equalsIgnoreCase("Q")) {
> -                return DecoderUtil.decodeQ(encodedText, charset);
> +                return DecoderUtil.decodeQ(encodedText, charset, monitor);
>             } else if (encoding.equalsIgnoreCase("B")) {
> -                return DecoderUtil.decodeB(encodedText, charset);
> +                return DecoderUtil.decodeB(encodedText, charset, monitor);
>             } else {
> -                if (log.isWarnEnabled()) {
> -                    log.warn("Warning: Unknown encoding in encoded word '"
> -                            + recombine(mimeCharset, encoding, encodedText) 
> + "'");
> -                }
> +                monitor(monitor, mimeCharset, encoding, encodedText, 
> "leaving word encoded",
> +                        "Warning: Unknown encoding in encoded word");
>                 return null;
>             }
>         } catch (UnsupportedEncodingException e) {
>             // should not happen because of isDecodingSupported check above
> -            if (log.isWarnEnabled()) {
> -                log.warn("Unsupported encoding in encoded word '"
> -                        + recombine(mimeCharset, encoding, encodedText) + 
> "'", e);
> -            }
> +            monitor(monitor, mimeCharset, encoding, encodedText, "leaving 
> word encoded",
> +                    "Unsupported encoding (", e.getMessage(), ") in encoded 
> word");
>             return null;
>         } catch (RuntimeException e) {
> -            if (log.isWarnEnabled()) {
> -                log.warn("Could not decode encoded word '"
> -                        + recombine(mimeCharset, encoding, encodedText) + 
> "'", e);
> -            }
> +            monitor(monitor, mimeCharset, encoding, encodedText, "leaving 
> word encoded",
> +                    "Could not decode (", e.getMessage(), ") encoded word");
>             return null;
>         }
>     }
>
> +    private static void monitor(DecodeMonitor monitor, String mimeCharset, 
> String encoding,
> +            String encodedText, String dropDesc, String... strings) throws 
> IllegalArgumentException {
> +        if (monitor.isListening()) {
> +            String encodedWord = recombine(mimeCharset, encoding, 
> encodedText);
> +            StringBuilder text = new StringBuilder();
> +            for (String str : strings) {
> +                text.append(str);
> +            }
> +            text.append(" (");
> +            text.append(encodedWord);
> +            text.append(")");
> +            String exceptionDesc = text.toString();
> +            if (monitor.warn(exceptionDesc, dropDesc))
> +                throw new IllegalArgumentException(text.toString());
> +        }
> +    }
> +
>     private static String recombine(final String mimeCharset,
>             final String encoding, final String encodedText) {
>         return "=?" + mimeCharset + "?" + encoding + "?" + encodedText + "?=";
>
> Modified: 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java?rev=895486&r1=895485&r2=895486&view=diff
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java
>  (original)
> +++ 
> james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/codec/QuotedPrintableInputStream.java
>  Sun Jan  3 21:47:38 2010
> @@ -22,8 +22,6 @@
>  import java.io.IOException;
>  import java.io.InputStream;
>
> -import org.apache.commons.logging.Log;
> -import org.apache.commons.logging.LogFactory;
>  import org.apache.james.mime4j.util.ByteArrayBuffer;
>
>  /**
> @@ -37,12 +35,9 @@
>     private static final byte CR = 0x0D;
>     private static final byte LF = 0x0A;
>
> -    private static Log log = 
> LogFactory.getLog(QuotedPrintableInputStream.class);
> -
>     private final byte[] singleByte = new byte[1];
>
>     private final InputStream in;
> -    private boolean strict;
>     private final ByteArrayBuffer decodedBuf;
>     private final ByteArrayBuffer blanks;
>
> @@ -52,22 +47,32 @@
>
>     private boolean closed;
>
> -    protected QuotedPrintableInputStream(final int bufsize, final 
> InputStream in, boolean strict) {
> +    private final DecodeMonitor monitor;
> +
> +    public QuotedPrintableInputStream(final InputStream in, DecodeMonitor 
> monitor) {
> +        this(DEFAULT_BUFFER_SIZE, in, monitor);
> +    }
> +
> +    protected QuotedPrintableInputStream(final int bufsize, final 
> InputStream in, DecodeMonitor monitor) {
>         super();
>         this.in = in;
> -        this.strict = strict;
>         this.encoded = new byte[bufsize];
>         this.decodedBuf = new ByteArrayBuffer(512);
>         this.blanks = new ByteArrayBuffer(512);
>         this.closed = false;
> +        this.monitor = monitor;
>     }
> -
> +
> +    protected QuotedPrintableInputStream(final int bufsize, final 
> InputStream in, boolean strict) {
> +        this(bufsize, in, strict ? DecodeMonitor.STRICT : 
> DecodeMonitor.SILENT);
> +    }
> +
>     public QuotedPrintableInputStream(final InputStream in, boolean strict) {
>         this(DEFAULT_BUFFER_SIZE, in, strict);
>     }
>
>     public QuotedPrintableInputStream(final InputStream in) {
> -        this(DEFAULT_BUFFER_SIZE, in, false);
> +        this(in, false);
>     }
>
>     /**
> @@ -123,7 +128,7 @@
>     }
>
>     private int transfer(
> -            final int b, final byte[] buffer, final int from, final int to, 
> boolean keepblanks) {
> +            final int b, final byte[] buffer, final int from, final int to, 
> boolean keepblanks) throws IOException {
>         int index = from;
>         if (keepblanks && blanks.length() > 0) {
>             int chunk = Math.min(blanks.length(), to - index);
> @@ -134,6 +139,11 @@
>                 decodedBuf.append(blanks.buffer(), chunk, remaining);
>             }
>             blanks.clear();
> +        } else if (blanks.length() > 0 && !keepblanks) {
> +            StringBuilder sb = new StringBuilder(blanks.length() * 3);
> +            for (int i = 0; i < blanks.length(); i++) sb.append(" 
> "+blanks.byteAt(i));
> +            if (monitor.warn("ignored blanks", sb.toString()))
> +                throw new IOException("ignored blanks");
>         }
>         if (b != -1) {
>             if (index < to) {
> @@ -171,12 +181,30 @@
>                 return index == from ? -1 : index - from;
>             }
>
> +            boolean lastWasCR = false;
>             while (pos < limit && index < to) {
>                 int b = encoded[pos++] & 0xFF;
>
> +                if (lastWasCR && b != LF) {
> +                    if (monitor.warn("Found CR without LF", "Leaving it as 
> is"))
> +                        throw new IOException("Found CR without LF");
> +                    index = transfer(CR, buffer, index, to, false);
> +                } else if (!lastWasCR && b == LF) {
> +                    if (monitor.warn("Found LF without CR", "Translating to 
> CRLF"))
> +                        throw new IOException("Found LF without CR");
> +                }
> +
> +                if (b == CR) {
> +                    lastWasCR = true;
> +                    continue;
> +                } else {
> +                    lastWasCR = false;
> +                }
> +
>                 if (b == LF) {
>                     // at end of line
>                     if (blanks.length() == 0) {
> +                        index = transfer(CR, buffer, index, to, false);
>                         index = transfer(LF, buffer, index, to, false);
>                     } else {
>                         if (blanks.byteAt(0) != EQ) {
> @@ -201,7 +229,10 @@
>                         int bb1 = peek(0);
>                         int bb2 = peek(1);
>                         if (bb1 == LF || (bb1 == CR && bb2 == LF)) {
> +                            monitor.warn("Unexpected ==EOL encountered", "== 
> 0x"+bb1+" 0x"+bb2);
>                             blanks.append(b2);
> +                        } else {
> +                            monitor.warn("Unexpected == encountered", "==");
>                         }
>                     } else if (Character.isWhitespace((char) b2)) {
>                         // soft line break
> @@ -215,14 +246,11 @@
>                         int upper = convert(b2);
>                         int lower = convert(b3);
>                         if (upper < 0 || lower < 0) {
> -                            if (strict) {
> -                                throw new IOException("Malformed encoded 
> value encountered");
> -                            } else {
> -                                log.warn("Malformed encoded value 
> encountered");
> -                                index = transfer(EQ, buffer, index, to, 
> true);
> -                                index = transfer(b2, buffer, index, to, 
> false);
> -                                index = transfer(b3, buffer, index, to, 
> false);
> -                            }
> +                            monitor.warn("Malformed encoded value 
> encountered", "leaving "+((char) EQ)+((char) b2)+((char) b3)+" as is");
> +                            // TODO see MIME4J-160
> +                            index = transfer(EQ, buffer, index, to, true);
> +                            index = transfer(b2, buffer, index, to, false);
> +                            index = transfer(b3, buffer, index, to, false);
>                         } else {
>                             index = transfer((upper << 4) | lower, buffer, 
> index, to, true);
>                         }
>
> Modified: 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java?rev=895486&r1=895485&r2=895486&view=diff
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java
>  (original)
> +++ 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/DecoderUtilTest.java
>  Sun Jan  3 21:47:38 2010
> @@ -35,12 +35,12 @@
>
>     public void testDecodeB() throws UnsupportedEncodingException {
>         String s = DecoderUtil.decodeB("VGhpcyBpcyB0aGUgcGxhaW4gd"
> -                    + "GV4dCBtZXNzYWdlIQ==", "ISO8859-1");
> +                    + "GV4dCBtZXNzYWdlIQ==", "ISO8859-1", 
> DecodeMonitor.STRICT);
>         assertEquals("This is the plain text message!", s);
>     }
>
>     public void testDecodeQ() throws UnsupportedEncodingException {
> -        String s = DecoderUtil.decodeQ("=e1_=e2=09=E3_=E4_", "ISO8859-1");
> +        String s = DecoderUtil.decodeQ("=e1_=e2=09=E3_=E4_", "ISO8859-1", 
> DecodeMonitor.STRICT);
>         assertEquals("\u00e1 \u00e2\t\u00e3 \u00e4 ", s);
>     }
>
>
> Modified: 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableInputStreamTest.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableInputStreamTest.java?rev=895486&r1=895485&r2=895486&view=diff
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableInputStreamTest.java
>  (original)
> +++ 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableInputStreamTest.java
>  Sun Jan  3 21:47:38 2010
> @@ -68,6 +68,13 @@
>         QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(bis);
>         assertEquals("Soft line   Hard line\r\n", new String(read(decoder), 
> "ISO8859-1"));
>     }
> +
> +    public void testInvalidCR() throws IOException, 
> UnsupportedEncodingException {
> +        ByteArrayInputStream bis = new 
> ByteArrayInputStream("Invalid=\rCR\rHard line   \r\n".getBytes("US-ASCII"));
> +        QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(bis);
> +        // TODO is this what we really expect from decoding a stream 
> including CR with no LF?
> +        assertEquals("Invalid=\rCR\rHard line\r\n", new 
> String(read(decoder), "ISO8859-1"));
> +    }
>
>     public void testSoftBreakLoneLFDecode() throws IOException, 
> UnsupportedEncodingException {
>         ByteArrayInputStream bis = new ByteArrayInputStream("Soft line   
> =\nHard line   \r\n".getBytes("US-ASCII"));
> @@ -91,6 +98,7 @@
>         ByteArrayInputStream bis = new ByteArrayInputStream("width==340 
> height=3d200\r\n".getBytes("US-ASCII"));
>         QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(bis);
>         assertEquals("width=340 height=200\r\n", new String(read(decoder), 
> "ISO8859-1"));
> +        // TODO this could be even decoded as width=40 height=200.
>     }
>
>     public void testBrokenEscapedEQDecode() throws IOException, 
> UnsupportedEncodingException {
> @@ -103,6 +111,13 @@
>         assertEquals("width=340 height=200\r\n", new String(read(decoder), 
> "ISO8859-1"));
>     }
>
> +    public void testSpacesBeforeEOL() throws IOException, 
> UnsupportedEncodingException {
> +        ByteArrayInputStream bis = new ByteArrayInputStream("some \r\n 
> spaced\t\r\ncontent \t \r\n".getBytes("US-ASCII"));
> +        QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(bis);
> +        assertEquals("some\r\n spaced\r\ncontent\r\n", new 
> String(read(decoder), "ISO8859-1"));
> +    }
> +
> +
>     public void testDecodeEndOfStream1() throws IOException, 
> UnsupportedEncodingException {
>         ByteArrayInputStream bis = new 
> ByteArrayInputStream("01234567".getBytes("US-ASCII"));
>         QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(6, bis, false);
> @@ -118,7 +133,7 @@
>     public void testDecodeEndOfStream3() throws IOException, 
> UnsupportedEncodingException {
>         ByteArrayInputStream bis = new 
> ByteArrayInputStream("012345\n".getBytes("US-ASCII"));
>         QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(6, bis, false);
> -        assertEquals("012345\n", new String(read(decoder), "ISO8859-1"));
> +        assertEquals("012345\r\n", new String(read(decoder), "ISO8859-1"));
>     }
>
>     public void testDecodeEndOfStream4() throws IOException, 
> UnsupportedEncodingException {
> @@ -133,6 +148,12 @@
>         assertEquals("01234", new String(read(decoder), "ISO8859-1"));
>     }
>
> +    public void testDecodeEndOfStream6() throws IOException, 
> UnsupportedEncodingException {
> +        ByteArrayInputStream bis = new 
> ByteArrayInputStream("01234\r\n".getBytes("US-ASCII"));
> +        QuotedPrintableInputStream decoder = new 
> QuotedPrintableInputStream(6, bis, false);
> +        assertEquals("01234\r\n", new String(read(decoder), "ISO8859-1"));
> +    }
> +
>     public void testDecodePrematureClose() throws IOException, 
> UnsupportedEncodingException {
>         ByteArrayInputStream bis = null;
>         QuotedPrintableInputStream decoder = null;
>
> Modified: 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java
> URL: 
> http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java?rev=895486&r1=895485&r2=895486&view=diff
> ==============================================================================
> --- 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java
>  (original)
> +++ 
> james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/codec/QuotedPrintableTextEncodeTest.java
>  Sun Jan  3 21:47:38 2010
> @@ -103,7 +103,7 @@
>         for (byte b=0;b<Byte.MAX_VALUE;b++) {
>             byte[] content = {b};
>             // White space is only escaped when followed by CRLF
> -            if (b != 13 && b != 32 && b != 9) {
> +            if (b != 10 && b != 13 && b != 32 && b != 9) {
>                 checkRoundtrip(content);
>             }
>         }
>
>
>

Reply via email to