Author: mwiederkehr
Date: Thu Jan 22 07:43:01 2009
New Revision: 736679

URL: http://svn.apache.org/viewvc?rev=736679&view=rev
Log:
MIME4J-100: parameter values with space characters have to be quoted

Modified:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java
    
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/FieldsTest.java

Modified: 
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java
URL: 
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java?rev=736679&r1=736678&r2=736679&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java 
(original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java 
Thu Jan 22 07:43:01 2009
@@ -22,6 +22,7 @@
 import java.text.DateFormat;
 import java.text.FieldPosition;
 import java.text.SimpleDateFormat;
+import java.util.BitSet;
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.Locale;
@@ -32,6 +33,19 @@
 import org.apache.james.mime4j.util.MimeUtil;
 
 public class Fields {
+
+    private static final BitSet TOKEN_CHARS;
+
+    static {
+        final String specials = "()<>@,;:\\\"/[]?=";
+        TOKEN_CHARS = new BitSet(128);
+        for (char ch = 33; ch < 127; ch++) {
+            if (specials.indexOf(ch) == -1) {
+                TOKEN_CHARS.set(ch);
+            }
+        }
+    }
+
     private Fields() {
     }
 
@@ -52,7 +66,7 @@
                 sb.append("; ");
                 sb.append(entry.getKey());
                 sb.append('=');
-                sb.append(quote(entry.getValue()));
+                sb.append(encodeValue(entry.getValue()));
             }
             String contentType = sb.toString();
             return contentType(contentType);
@@ -103,20 +117,38 @@
         return (UnstructuredField) Field.parse(Field.SUBJECT, rawValue);
     }
 
-    private static String quote(String value) {
-        for (int idx = 0; idx < value.length(); idx++) {
-            if (isSpecial(value.charAt(idx))) {
-                value = value.replaceAll("[\\\"]", "\\\\$0");
-                return "\"" + value + "\"";
-            }
+    // value := token / quoted-string
+    private static String encodeValue(String value) {
+        if (isToken(value)) {
+            return value;
+        } else {
+            return quote(value);
         }
-
-        return value;
     }
 
-    private static boolean isSpecial(char ch) {
-        final String tspecials = "()<>@,;:\\\"/[]?="; // rfc 2045
-        return ch < 32 || ch >= 127 || tspecials.indexOf(ch) != -1;
+    // token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, or tspecials>
+    // tspecials := "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "\" / <"> /
+    // "/" / "[" / "]" / "?" / "="
+    // CTL := 0.- 31., 127.
+    private static boolean isToken(String str) {
+        final int length = str.length();
+        for (int idx = 0; idx < length; idx++) {
+            char ch = str.charAt(idx);
+            if (!TOKEN_CHARS.get(ch))
+                return false;
+        }
+        return true;
+    }
+
+    // quoted-string = [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS]
+    // qcontent = qtext / quoted-pair
+    // qtext = %d33 / %d35-91 / %d93-126
+    // quoted-pair = ("\" (VCHAR / WSP))
+    // VCHAR = %x21-7E
+    // DQUOTE = %x22
+    private static String quote(String str) {
+        String escaped = str.replaceAll("[\\\"]", "\\\\$0");
+        return "\"" + escaped + "\"";
     }
 
     private static final ThreadLocal<DateFormat> RFC822_DATE_FORMAT = new 
ThreadLocal<DateFormat>() {

Modified: 
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/FieldsTest.java
URL: 
http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/FieldsTest.java?rev=736679&r1=736678&r2=736679&view=diff
==============================================================================
--- 
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/FieldsTest.java 
(original)
+++ 
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/FieldsTest.java 
Thu Jan 22 07:43:01 2009
@@ -54,6 +54,18 @@
         assertEquals(expectedRaw, field.getRaw());
     }
 
+    public void testContentTypeStringParametersWithSpaces() throws Exception {
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put("param", "value with space chars");
+        ContentTypeField field = Fields.contentType("multipart/mixed",
+                parameters);
+        assertTrue(field.isValidField());
+
+        String expectedRaw = "Content-Type: multipart/mixed; "
+                + "param=\"value with space chars\"";
+        assertEquals(expectedRaw, field.getRaw());
+    }
+
     public void testContentTypeStringNullParameters() throws Exception {
         ContentTypeField field = Fields.contentType("text/plain", null);
         assertTrue(field.isValidField());



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

Reply via email to