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