james-mime4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1095175 - in /james/mime4j/trunk/core/src: main/java/org/apache/james/mime4j/stream/ test/java/org/apache/james/mime4j/stream/
Date Tue, 19 Apr 2011 19:39:10 GMT
Author: olegk
Date: Tue Apr 19 19:39:10 2011
New Revision: 1095175

URL: http://svn.apache.org/viewvc?rev=1095175&view=rev
Log:
A complete rewrite of the low level field parsing routines: the parser should be more flexible
now while still being very efficient and fast (the parser never needs to move backward and
does not create intermediate copies of the data being parsed). Handling of comments will be
implemented as the next step

Modified:
    james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/LenientFieldBuilder.java
    james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/NameValuePair.java
    james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
    james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/LenientFieldBuilderTest.java
    james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java

Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/LenientFieldBuilder.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/LenientFieldBuilder.java?rev=1095175&r1=1095174&r2=1095175&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/LenientFieldBuilder.java
(original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/LenientFieldBuilder.java
Tue Apr 19 19:39:10 2011
@@ -22,6 +22,7 @@ package org.apache.james.mime4j.stream;
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.io.MaxHeaderLengthLimitException;
 import org.apache.james.mime4j.util.ByteArrayBuffer;
+import org.apache.james.mime4j.util.CharsetUtil;
 
 public class LenientFieldBuilder implements FieldBuilder {
 
@@ -51,10 +52,12 @@ public class LenientFieldBuilder impleme
         }
         int beginIndex = 0;
         int endIndex = len;
-        while (beginIndex < endIndex && RawFieldParser.isWhitespace(line.byteAt(beginIndex)))
{
+        while (beginIndex < endIndex 
+                && CharsetUtil.isWhitespace((char)(line.byteAt(beginIndex) &
0xff))) {
             beginIndex++;
         }
-        while (endIndex > beginIndex && RawFieldParser.isWhitespace(line.byteAt(endIndex
- 1))) {
+        while (endIndex > beginIndex 
+                && CharsetUtil.isWhitespace((char)(line.byteAt(endIndex - 1) &
0xff))) {
             endIndex--;
         }
         if (this.buf.length() > 0) {
@@ -67,14 +70,9 @@ public class LenientFieldBuilder impleme
         if (this.buf == null) {
             return null;
         }
-        int idx = RawFieldParser.indexOf(this.buf, RawFieldParser.COLON);
-        if (idx == -1) {
-            throw new MimeException("Invalid MIME field: no name/value separator found: "
+
-                    this.buf.toString());
-        }
-        String name = RawFieldParser.copyTrimmed(this.buf, 0, idx);
-        String value = RawFieldParser.copyTrimmed(this.buf, idx + 1, this.buf.length());
-        return new RawField(name, value);
+        RawField field = RawFieldParser.DEFAULT.parseField(this.buf);
+        // Discard modified raw data
+        return new RawField(field.getName(), field.getBody());
     }
     
     public ByteArrayBuffer getRaw() {

Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/NameValuePair.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/NameValuePair.java?rev=1095175&r1=1095174&r2=1095175&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/NameValuePair.java
(original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/NameValuePair.java
Tue Apr 19 19:39:10 2011
@@ -25,16 +25,14 @@ public final class NameValuePair {
 
     private final String name;
     private final String value;
-    private final boolean quoted;
 
-    public NameValuePair(final String name, final String value, boolean quoted) {
+    public NameValuePair(final String name, final String value) {
         super();
         if (name == null) {
             throw new IllegalArgumentException("Name may not be null");
         }
         this.name = name;
         this.value = value;
-        this.quoted = quoted;
     }
 
     public String getName() {
@@ -45,10 +43,6 @@ public final class NameValuePair {
         return this.value;
     }
 
-    public boolean isQuoted() {
-        return this.quoted;
-    }
-
     public String toString() {
         if (this.value == null) {
             return name;
@@ -56,13 +50,9 @@ public final class NameValuePair {
             StringBuilder buffer = new StringBuilder();
             buffer.append(this.name);
             buffer.append("=");
-            if (this.quoted) {
-                buffer.append("\"");
-            }
+            buffer.append("\"");
             buffer.append(this.value);
-            if (this.quoted) {
-                buffer.append("\"");
-            }
+            buffer.append("\"");
             return buffer.toString();
         }
     }

Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java?rev=1095175&r1=1095174&r2=1095175&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
(original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
Tue Apr 19 19:39:10 2011
@@ -24,6 +24,7 @@ import java.util.List;
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.CharsetUtil;
 import org.apache.james.mime4j.util.ContentUtil;
 
 /**
@@ -31,30 +32,28 @@ import org.apache.james.mime4j.util.Cont
  */
 public class RawFieldParser {
 
-    static final int COLON   = ':';
-    static final int SPACE   = 0x20;
-    static final int TAB     = 0x09;
-    static final int CR      = 0x0d;
-    static final int LF      = 0x0a;
-    
-    public static final RawFieldParser DEFAULT = new RawFieldParser(); 
+    static final int[] COLON                   = { ':' };
+    static final int[] EQUAL_OR_SEMICOLON      = { '=', ';' };
+    static final int[] SEMICOLON               = { ';' };
+
+    public static final RawFieldParser DEFAULT = new RawFieldParser();
 
     public RawField parseField(final ByteSequence raw) throws MimeException {
         if (raw == null) {
             return null;
         }
-        int idx = indexOf(raw, COLON);
-        if (idx == -1) {
+        ParserCursor cursor = new ParserCursor(0, raw.length());
+        String name = parseToken(raw, cursor, COLON);
+        if (cursor.atEnd()) {
             throw new MimeException("Invalid MIME field: no name/value separator found: "
+
-            		raw.toString());
+                    raw.toString());
         }
-        String name = copyTrimmed(raw, 0, idx);
-        return new RawField(raw, idx, name, null);
+        return new RawField(raw, cursor.getPos(), name, null);
     }
 
     public RawBody parseRawBody(final RawField field) {
         ByteSequence buf = field.getRaw();
-        int pos = field.getDelimiterIdx() + 1; 
+        int pos = field.getDelimiterIdx() + 1;
         if (buf == null) {
             String body = field.getBody();
             if (body == null) {
@@ -66,155 +65,44 @@ public class RawFieldParser {
         ParserCursor cursor = new ParserCursor(pos, buf.length());
         return parseRawBody(buf, cursor);
     }
-    
-    static final int[] DELIMS = { ';' };
 
     RawBody parseRawBody(final ByteSequence buf, final ParserCursor cursor) {
-        int pos = cursor.getPos();
-        int indexFrom = pos;
-        int indexTo = cursor.getUpperBound();
-        while (pos < indexTo) {
-            int ch = buf.byteAt(pos);
-            if (isOneOf(ch, DELIMS)) {
-                break;
-            }
-            pos++;
-        }
-        String value = copyTrimmed(buf, indexFrom, pos);
-        if (pos == indexTo) {
-            cursor.updatePos(pos);
-            return new RawBody(value, null);
+        String value = parseToken(buf, cursor, SEMICOLON);
+        if (cursor.atEnd()) {
+            return new RawBody(value, new ArrayList<NameValuePair>());
         }
-        cursor.updatePos(pos + 1);
+        cursor.updatePos(cursor.getPos() + 1);
         List<NameValuePair> params = parseParameters(buf, cursor);
         return new RawBody(value, params);
     }
-    
+
     List<NameValuePair> parseParameters(final ByteSequence buf, final ParserCursor
cursor) {
         List<NameValuePair> params = new ArrayList<NameValuePair>();
-        int pos = cursor.getPos();
-        int indexTo = cursor.getUpperBound();
-
-        while (pos < indexTo) {
-            int ch = buf.byteAt(pos);
-            if (isWhitespace(ch)) {
-                pos++;
-            } else {
-                break;
-            }
-        }
-        cursor.updatePos(pos);
-        if (cursor.atEnd()) {
-            return params;
-        }
-
+        skipWhiteSpace(buf, cursor);
         while (!cursor.atEnd()) {
-            NameValuePair param = parseParameter(buf, cursor, DELIMS);
+            NameValuePair param = parseParameter(buf, cursor);
             params.add(param);
         }
         return params;
     }
 
     NameValuePair parseParameter(final ByteSequence buf, final ParserCursor cursor) {
-        return parseParameter(buf, cursor, DELIMS);
-    }
-    
-    NameValuePair parseParameter(final ByteSequence buf, final ParserCursor cursor, final
int[] delimiters) {
-        boolean terminated = false;
-
-        int pos = cursor.getPos();
-        int indexFrom = cursor.getPos();
-        int indexTo = cursor.getUpperBound();
-
-        // Find name
-        String name = null;
-        while (pos < indexTo) {
-            int ch = buf.byteAt(pos);
-            if (ch == '=') {
-                break;
-            }
-            if (isOneOf(ch, delimiters)) {
-                terminated = true;
-                break;
-            }
-            pos++;
-        }
-
-        if (pos == indexTo) {
-            terminated = true;
-            name = copyTrimmed(buf, indexFrom, indexTo);
-        } else {
-            name = copyTrimmed(buf, indexFrom, pos);
-            pos++;
-        }
-
-        if (terminated) {
-            cursor.updatePos(pos);
-            return new NameValuePair(name, null, false);
-        }
-
-        // Find value
-        String value = null;
-        int i1 = pos;
-
-        boolean qouted = false;
-        boolean escaped = false;
-        while (pos < indexTo) {
-            int ch = buf.byteAt(pos);
-            if (ch == '"' && !escaped) {
-                qouted = !qouted;
-            }
-            if (!qouted && !escaped && isOneOf(ch, delimiters)) {
-                terminated = true;
-                break;
-            }
-            if (escaped) {
-                escaped = false;
-            } else {
-                escaped = qouted && ch == '\\';
-            }
-            pos++;
-        }
-
-        int i2 = pos;
-        // Trim leading white spaces
-        while (i1 < i2 && (isWhitespace(buf.byteAt(i1)))) {
-            i1++;
-        }
-        // Trim trailing white spaces
-        while ((i2 > i1) && (isWhitespace(buf.byteAt(i2 - 1)))) {
-            i2--;
-        }
-        boolean quoted = false;
-        // Strip away quotes if necessary
-        if (((i2 - i1) >= 2)
-            && (buf.byteAt(i1) == '"')
-            && (buf.byteAt(i2 - 1) == '"')) {
-            quoted = true;
-            i1++;
-            i2--;
-        }
-        if (quoted) {
-            value = copyEscaped(buf, i1, i2);
-        } else {
-            value = copy(buf, i1, i2);
-        }
-        if (terminated) {
-            pos++;
+        String name = parseToken(buf, cursor, EQUAL_OR_SEMICOLON);
+        if (cursor.atEnd()) {
+            return new NameValuePair(name, null);
         }
-        cursor.updatePos(pos);
-        return new NameValuePair(name, value, quoted);
-    }
-    
-    static int indexOf(final ByteSequence buf, int b) {
-        for (int i = 0; i < buf.length(); i++) {
-            if (buf.byteAt(i) == b) {
-                return i;
-            }
+        int delim = buf.byteAt(cursor.getPos());
+        cursor.updatePos(cursor.getPos() + 1);
+        if (delim == ';') {
+            return new NameValuePair(name, null);
+        }
+        String value = parseValue(buf, cursor, SEMICOLON);
+        if (!cursor.atEnd()) {
+            cursor.updatePos(cursor.getPos() + 1);
         }
-        return -1;
+        return new NameValuePair(name, value);
     }
-    
+
     static boolean isOneOf(final int ch, final int[] chs) {
         if (chs != null) {
             for (int i = 0; i < chs.length; i++) {
@@ -225,49 +113,123 @@ public class RawFieldParser {
         }
         return false;
     }
-    
-    static boolean isWhitespace(int i) {
-        return i == SPACE || i == TAB || i == CR || i == LF;
+
+    static String parseToken(final ByteSequence buf, final ParserCursor cursor, final int[]
delimiters) {
+        StringBuilder dst = new StringBuilder();
+        boolean whitespace = false;
+        while (!cursor.atEnd()) {
+            char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
+            if (isOneOf(current, delimiters)) {
+                break;
+            } else if (CharsetUtil.isWhitespace(current)) {
+                skipWhiteSpace(buf, cursor);
+                whitespace = true;
+            } else {
+                if (dst.length() > 0 && whitespace) {
+                    dst.append(' ');
+                }
+                copyContent(buf, cursor, delimiters, dst);
+                whitespace = false;
+            }
+        }
+        return dst.toString();
     }
-    
-    static String copy(final ByteSequence buf, int beginIndex, int endIndex) {
-        StringBuilder strbuf = new StringBuilder(endIndex - beginIndex);
-        for (int i = beginIndex; i < endIndex; i++) {
-            strbuf.append((char) (buf.byteAt(i) & 0xff));
+
+    static String parseValue(final ByteSequence buf, final ParserCursor cursor, final int[]
delimiters) {
+        StringBuilder dst = new StringBuilder();
+        boolean whitespace = false;
+        while (!cursor.atEnd()) {
+            char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
+            if (isOneOf(current, delimiters)) {
+                break;
+            } else if (CharsetUtil.isWhitespace(current)) {
+                skipWhiteSpace(buf, cursor);
+                whitespace = true;
+            } else if (current == '\"') {
+                if (dst.length() > 0 && whitespace) {
+                    dst.append(' ');
+                }
+                copyQuotedContent(buf, cursor, dst);
+                whitespace = false;
+            } else {
+                if (dst.length() > 0 && whitespace) {
+                    dst.append(' ');
+                }
+                copyContent(buf, cursor, delimiters, dst);
+                whitespace = false;
+            }
         }
-        return strbuf.toString();
+        return dst.toString();
     }
 
-    static String copyTrimmed(final ByteSequence buf, int beginIndex, int endIndex) {
-        while (beginIndex < endIndex && isWhitespace(buf.byteAt(beginIndex)))
{
-            beginIndex++;
+    static void skipWhiteSpace(final ByteSequence buf, final ParserCursor cursor) {
+        int pos = cursor.getPos();
+        int indexFrom = cursor.getPos();
+        int indexTo = cursor.getUpperBound();
+        for (int i = indexFrom; i < indexTo; i++) {
+            char current = (char) (buf.byteAt(i) & 0xff);
+            if (!CharsetUtil.isWhitespace(current)) {
+                break;
+            } else {
+                pos++;
+            }
         }
-        while (endIndex > beginIndex && isWhitespace(buf.byteAt(endIndex - 1)))
{
-            endIndex--;
+        cursor.updatePos(pos);
+    }
+
+    static void copyContent(final ByteSequence buf, final ParserCursor cursor, final int[]
delimiters,
+            final StringBuilder dst) {
+        int pos = cursor.getPos();
+        int indexFrom = cursor.getPos();
+        int indexTo = cursor.getUpperBound();
+        for (int i = indexFrom; i < indexTo; i++) {
+            char current = (char) (buf.byteAt(i) & 0xff);
+            if (isOneOf(current, delimiters) || CharsetUtil.isWhitespace(current)) {
+                break;
+            } else {
+                pos++;
+                dst.append(current);
+            }
         }
-        return copy(buf, beginIndex, endIndex);
+        cursor.updatePos(pos);
     }
 
-    static String copyEscaped(final ByteSequence buf, int beginIndex, int endIndex) {
-        StringBuilder strbuf  = new StringBuilder(endIndex - beginIndex);
+    static void copyQuotedContent(final ByteSequence buf, final ParserCursor cursor,
+            final StringBuilder dst) {
+        if (cursor.atEnd()) {
+            return;
+        }
+        int pos = cursor.getPos();
+        int indexFrom = cursor.getPos();
+        int indexTo = cursor.getUpperBound();
+        char current = (char) (buf.byteAt(pos) & 0xff);
+        if (current != '\"') {
+            return;
+        }
+        pos++;
+        indexFrom++;
         boolean escaped = false;
-        for (int i = beginIndex; i < endIndex; i++) {
-            char ch = (char) (buf.byteAt(i) & 0xff);
+        for (int i = indexFrom; i < indexTo; i++, pos++) {
+            current = (char) (buf.byteAt(i) & 0xff);
             if (escaped) {
-                if (ch != '\"' && ch != '\\') {
-                    strbuf.append('\\');
+                if (current != '\"' && current != '\\') {
+                    dst.append('\\');
                 }
-                strbuf.append(ch);
+                dst.append(current);
                 escaped = false;
             } else {
-                if (ch == '\\') {
+                if (current == '\"') {
+                    pos++;
+                    break;
+                }
+                if (current == '\\') {
                     escaped = true;
                 } else {
-                    strbuf.append(ch);
+                    dst.append(current);
                 }
             }
         }
-        return strbuf.toString();
+        cursor.updatePos(pos);
     }
 
 }

Modified: james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/LenientFieldBuilderTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/LenientFieldBuilderTest.java?rev=1095175&r1=1095174&r2=1095175&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/LenientFieldBuilderTest.java
(original)
+++ james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/LenientFieldBuilderTest.java
Tue Apr 19 19:39:10 2011
@@ -45,7 +45,7 @@ public class LenientFieldBuilderTest ext
         RawField field = builder.build();
         assertNotNull(field);
         assertEquals("raw", field.getName());
-        assertEquals("stuff; more stuff; a lot more stuff", field.getBody());
+        assertEquals("  stuff; more stuff; a lot more stuff", field.getBody());
         ByteSequence raw = field.getRaw();
         assertNull(raw);
     }

Modified: james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java?rev=1095175&r1=1095174&r2=1095175&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
(original)
+++ james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
Tue Apr 19 19:39:10 2011
@@ -30,6 +30,98 @@ import junit.framework.TestCase;
 
 public class RawFieldParserTest extends TestCase {
 
+    public void testBasicTokenParsing() throws Exception {
+        String s = "   raw: \" some stuff \"";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        RawFieldParser.skipWhiteSpace(raw, cursor);
+
+        Assert.assertFalse(cursor.atEnd());
+        Assert.assertEquals(3, cursor.getPos());
+
+        StringBuilder strbuf1 = new StringBuilder();
+        RawFieldParser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
+
+        Assert.assertFalse(cursor.atEnd());
+        Assert.assertEquals(6, cursor.getPos());
+        Assert.assertEquals("raw", strbuf1.toString());
+        Assert.assertEquals(':', raw.byteAt(cursor.getPos()));
+        cursor.updatePos(cursor.getPos() + 1);
+
+        RawFieldParser.skipWhiteSpace(raw, cursor);
+
+        Assert.assertFalse(cursor.atEnd());
+        Assert.assertEquals(8, cursor.getPos());
+
+        StringBuilder strbuf2 = new StringBuilder();
+        RawFieldParser.copyQuotedContent(raw, cursor, strbuf2);
+
+        Assert.assertTrue(cursor.atEnd());
+        Assert.assertEquals(" some stuff ", strbuf2.toString());
+
+        RawFieldParser.copyQuotedContent(raw, cursor, strbuf2);
+        Assert.assertTrue(cursor.atEnd());
+
+        RawFieldParser.skipWhiteSpace(raw, cursor);
+        Assert.assertTrue(cursor.atEnd());
+    }
+
+    public void testTokenParsingWithQuotedPairs() throws Exception {
+        String s = "raw: \"\\\"some\\stuff\\\\\"";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        RawFieldParser.skipWhiteSpace(raw, cursor);
+
+        Assert.assertFalse(cursor.atEnd());
+        Assert.assertEquals(0, cursor.getPos());
+
+        StringBuilder strbuf1 = new StringBuilder();
+        RawFieldParser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
+
+        Assert.assertFalse(cursor.atEnd());
+        Assert.assertEquals("raw", strbuf1.toString());
+        Assert.assertEquals(':', raw.byteAt(cursor.getPos()));
+        cursor.updatePos(cursor.getPos() + 1);
+
+        RawFieldParser.skipWhiteSpace(raw, cursor);
+
+        Assert.assertFalse(cursor.atEnd());
+
+        StringBuilder strbuf2 = new StringBuilder();
+        RawFieldParser.copyQuotedContent(raw, cursor, strbuf2);
+
+        Assert.assertTrue(cursor.atEnd());
+        Assert.assertEquals("\"some\\stuff\\", strbuf2.toString());
+    }
+
+    public void testTokenParsingIncompleteQuote() throws Exception {
+        String s = "\"stuff and more stuff  ";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        StringBuilder strbuf1 = new StringBuilder();
+        RawFieldParser.copyQuotedContent(raw, cursor, strbuf1);
+        Assert.assertEquals("stuff and more stuff  ", strbuf1.toString());
+    }
+
+
+    public void testTokenParsingTokensWithUnquotedBlanks() throws Exception {
+        String s = "  stuff and   \tsome\tmore  stuff  ;";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        String result = RawFieldParser.parseToken(raw, cursor, new int[] { ';' });
+        Assert.assertEquals("stuff and some more stuff", result);
+    }
+
+    public void testTokenParsingMixedValuesAndQuotedValues() throws Exception {
+        String s = "  stuff and    \" some more \"   \"stuff  ;";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        String result = RawFieldParser.parseValue(raw, cursor, new int[] { ';' });
+        Assert.assertEquals("stuff and  some more  stuff  ;", result);
+    }
+
     public void testBasicParsing() throws Exception {
         String s = "raw: stuff;\r\n  more stuff";
         ByteSequence raw = ContentUtil.encode(s);
@@ -43,6 +135,19 @@ public class RawFieldParserTest extends 
         Assert.assertEquals(s, field.toString());
     }
 
+    public void testParsingNoBlankAfterColon() throws Exception {
+        String s = "raw:stuff";
+        ByteSequence raw = ContentUtil.encode(s);
+
+        RawFieldParser parser = new RawFieldParser();
+
+        RawField field = parser.parseField(raw);
+        Assert.assertSame(raw, field.getRaw());
+        Assert.assertEquals("raw", field.getName());
+        Assert.assertEquals("stuff", field.getBody());
+        Assert.assertEquals(s, field.toString());
+    }
+
     public void testParsingObsoleteSyntax() throws Exception {
         String s = "raw  \t  : stuff;\r\n  more stuff";
         ByteSequence raw = ContentUtil.encode(s);
@@ -150,7 +255,7 @@ public class RawFieldParserTest extends 
         assertEquals("test", param.getName());
         assertEquals("  stuff\"", param.getValue());
 
-        s = "test  = \"  stuff\\\\\"\"";
+        s = "test  = \"  stuff\\\\\\\"\"";
         buf = ContentUtil.encode(s);
         cursor = new ParserCursor(0, s.length());
 
@@ -197,7 +302,7 @@ public class RawFieldParserTest extends 
         assertEquals("test2", params.get(2).getName());
         assertEquals("stuff; stuff", params.get(2).getValue());
         assertEquals("test3", params.get(3).getName());
-        assertEquals("\"stuff", params.get(3).getValue());
+        assertEquals("stuff", params.get(3).getValue());
         assertEquals(buf.length(), cursor.getPos());
         assertTrue(cursor.atEnd());
     }
@@ -266,7 +371,7 @@ public class RawFieldParserTest extends 
 
     /**
      * Proof for MIME4J-189.
-     * Either RawFieldParser implements unfolding or callers of RawFieldParser 
+     * Either RawFieldParser implements unfolding or callers of RawFieldParser
      * have to make sure the content is unfolded before being parsed.
      */
     /** TODO fix the main code.
@@ -285,4 +390,4 @@ public class RawFieldParserTest extends 
     }
     */
 
-}
\ No newline at end of file
+}



Mime
View raw message