james-mime4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Norman Maurer <norman.mau...@googlemail.com>
Subject Re: svn commit: r895486 - in /james/mime4j/branches/cycleclean/core/src: main/java/org/apache/james/mime4j/codec/ test/java/org/apache/james/mime4j/codec/
Date Mon, 04 Jan 2010 08:27:17 GMT
Hi Stefano,

DecodeMonitor is missing the asl2 header ....

Bye,
Norman


2010/1/3  <bago@apache.org>:
> 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);
>             }
>         }
>
>
>

Mime
View raw message