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); > } > } > > >
