james-mime4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From b...@apache.org
Subject svn commit: r894523 - in /james/mime4j/branches/cycleclean/core/src: main/java/org/apache/james/mime4j/field/ main/java/org/apache/james/mime4j/parser/ test/java/org/apache/james/mime4j/descriptor/ test/java/org/apache/james/mime4j/message/ test/java/o...
Date Wed, 30 Dec 2009 00:41:01 GMT
Author: bago
Date: Wed Dec 30 00:41:00 2009
New Revision: 894523

URL: http://svn.apache.org/viewvc?rev=894523&view=rev
Log:
Make sure we have a single place (RawField) where we decide how to parse a rawfield, how to
build it from name/body and how to deal with the WSP after the colon. (MIME4J-151).

Modified:
    james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
    james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/Fields.java
    james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
    james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
    james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/RawField.java
    james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java
    james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/message/HeaderTest.java
    james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java

Modified: james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
Wed Dec 30 00:41:00 2009
@@ -19,19 +19,13 @@
 
 package org.apache.james.mime4j.field;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.parser.RawField;
 import org.apache.james.mime4j.util.ByteSequence;
 import org.apache.james.mime4j.util.ContentUtil;
-import org.apache.james.mime4j.util.MimeUtil;
 
 public class DefaultFieldParser extends DelegatingFieldParser {
 
-	private static final Pattern FIELD_NAME_PATTERN = Pattern
-    .compile("^([\\x21-\\x39\\x3b-\\x7e]+)[\\x20\\x09]*:");
-	
     private static final DefaultFieldParser PARSER = new DefaultFieldParser();
     
 
@@ -56,8 +50,8 @@
      * @throws MimeException if the raw string cannot be split into field name and body.
      */
     public static ParsedField parse(final ByteSequence raw) throws MimeException {
-        String rawStr = ContentUtil.decode(raw);
-        return parse(raw, rawStr);
+    	RawField rawField = new RawField(raw);
+        return PARSER.parse(rawField.getName(), rawField.getBody(), raw);
     }
 
 
@@ -84,23 +78,7 @@
      */
     public static ParsedField parse(final String rawStr) throws MimeException {
         ByteSequence raw = ContentUtil.encode(rawStr);
-        return parse(raw, rawStr);
-    }
-
-    private static ParsedField parse(final ByteSequence raw, final String rawStr)
-            throws MimeException {
-        final Matcher fieldMatcher = FIELD_NAME_PATTERN.matcher(rawStr);
-        if (!fieldMatcher.find()) {
-            throw new MimeException("Invalid field in string");
-        }
-        final String name = fieldMatcher.group(1);
-
-        String body = rawStr.substring(fieldMatcher.end());
-        if (body.length() > 0 && body.charAt(0) == ' ') {
-            body = body.substring(1);
-        }
-        body = MimeUtil.unfold(body);
-        return PARSER.parse(name, body, raw);
+        return parse(raw);
     }
 
 

Modified: james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/Fields.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/Fields.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/Fields.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/field/Fields.java
Wed Dec 30 00:41:00 2009
@@ -30,8 +30,7 @@
 import org.apache.james.mime4j.codec.EncoderUtil;
 import org.apache.james.mime4j.field.address.Address;
 import org.apache.james.mime4j.field.address.Mailbox;
-import org.apache.james.mime4j.util.ByteSequence;
-import org.apache.james.mime4j.util.ContentUtil;
+import org.apache.james.mime4j.parser.RawField;
 import org.apache.james.mime4j.util.MimeUtil;
 
 /**
@@ -603,9 +602,8 @@
 
     private static <F extends ParsedField> F parse(FieldParser<F> parser,
             String fieldName, String fieldBody) {
-        String rawStr = MimeUtil.fold(fieldName + ": " + fieldBody, 0);
-        ByteSequence raw = ContentUtil.encode(rawStr);
-        return parser.parse(fieldName, fieldBody, raw);
+    	RawField rawField = new RawField(fieldName, fieldBody);
+        return parser.parse(rawField.getName(), rawField.getBody(), rawField.getRaw());
     }
 
     private static String encodeAddresses(Iterable<? extends Address> addresses) {

Modified: james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
Wed Dec 30 00:41:00 2009
@@ -20,7 +20,6 @@
 package org.apache.james.mime4j.parser;
 
 import java.io.IOException;
-import java.util.BitSet;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -58,17 +57,6 @@
     private boolean endOfHeader;
     private int headerCount;
 
-    private static final BitSet fieldChars = new BitSet();
-
-    static {
-        for (int i = 0x21; i <= 0x39; i++) {
-            fieldChars.set(i);
-        }
-        for (int i = 0x3b; i <= 0x7e; i++) {
-            fieldChars.set(i);
-        }
-    }
-
     /**
      * Internal state, not exposed.
      */
@@ -200,33 +188,14 @@
             }
             fieldbuf.setLength(len);
             
-            boolean valid = true;
-            boolean obsoleteSyntax = false;
-            
-            int pos = fieldbuf.indexOf((byte) ':');
-            if (pos <= 0) {
-                valid = false;
-            } else {
-                for (int i = 0; i < pos; i++) {
-                    if (!fieldChars.get(fieldbuf.byteAt(i) & 0xff)) {
-                    	for (; i < pos; i++) {
-                    		int j = fieldbuf.byteAt(i) & 0xff;
-							if (j != 0x20 && j != 0x09) {
-		                        valid = false;
-		                        break;
-							} else {
-								obsoleteSyntax = true;
-							}
-                    	}
-                    }
-                }
-            }
-            if (valid) {
-                if (obsoleteSyntax) warn(Event.OBSOLETE_HEADER);
-                field = new RawField(fieldbuf, pos);
+            try {
+            	field = new RawField(fieldbuf);
+            	if (field.isObsoleteSyntax()) {
+            		warn(Event.OBSOLETE_HEADER);
+            	}
                 body.addField(field);
                 return true;
-            } else {
+            } catch (MimeException e) {
                 monitor(Event.INVALID_HEADER);
             }
         }

Modified: james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
Wed Dec 30 00:41:00 2009
@@ -32,8 +32,6 @@
 import org.apache.james.mime4j.io.LineReaderInputStream;
 import org.apache.james.mime4j.io.LineReaderInputStreamAdaptor;
 import org.apache.james.mime4j.io.MimeBoundaryInputStream;
-import org.apache.james.mime4j.util.ByteSequence;
-import org.apache.james.mime4j.util.ContentUtil;
 import org.apache.james.mime4j.util.MimeUtil;
 
 public class MimeEntity extends AbstractEntity {
@@ -96,8 +94,7 @@
             throw new IllegalStateException("Invalid state: " + stateToString(state));
         }
         skipHeader = true;
-        ByteSequence raw = ContentUtil.encode("Content-Type: " + contentType);
-        body.addField(new RawField(raw, 12));
+        body.addField(new RawField("Content-Type", contentType));
     }
 
     @Override

Modified: james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/RawField.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/RawField.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/RawField.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/RawField.java
Wed Dec 30 00:41:00 2009
@@ -19,6 +19,9 @@
 
 package org.apache.james.mime4j.parser;
 
+import java.util.BitSet;
+
+import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.util.ByteSequence;
 import org.apache.james.mime4j.util.ContentUtil;
 import org.apache.james.mime4j.util.MimeUtil;
@@ -28,15 +31,61 @@
  */
 public class RawField {
 
-    private final ByteSequence raw;
+    private static final BitSet fieldChars = new BitSet();
+
+    static {
+        for (int i = 0x21; i <= 0x39; i++) {
+            fieldChars.set(i);
+        }
+        for (int i = 0x3b; i <= 0x7e; i++) {
+            fieldChars.set(i);
+        }
+    }
+
+
+    private ByteSequence raw;
     private int colonIdx;
+    private int headerNameEndIdx;
 
     private String name;
     private String body;
+	private final boolean obsoleteSyntax;
+
+    public RawField(String name, String body) {
+    	this.name = name;
+    	this.body = body;
+    	this.raw = null;
+    	this.obsoleteSyntax = false;
+    }
 
-    public RawField(ByteSequence raw, int colonIdx) {
+    /**
+     * @param raw bytes
+     * @throws MimeException on malformed data
+     */
+    public RawField(ByteSequence raw) throws MimeException {
         this.raw = raw;
-        this.colonIdx = colonIdx;
+
+        colonIdx = -1;
+        boolean obsolete = false;
+        for (int i = 0; i < raw.length(); i++) {
+            if (!fieldChars.get(raw.byteAt(i) & 0xff)) {
+            	headerNameEndIdx = i;
+            	for (; i < raw.length(); i++) {
+            		int j = raw.byteAt(i) & 0xff;
+            		if (j == ':') {
+            			colonIdx = i;
+            			break;
+            		} else if (j != 0x20 && j != 0x09) {
+            			throw new MimeException("Invalid header");
+            		} else {
+						obsolete = true;
+					}
+            	}
+            	break;
+            }
+        }
+        if (colonIdx == -1) throw new MimeException("Invalid header. No colon found.");
+        obsoleteSyntax = obsolete;
     }
 
     public String getName() {
@@ -56,25 +105,32 @@
     }
 
     public ByteSequence getRaw() {
+    	if (raw == null) {
+    		raw = ContentUtil.encode(MimeUtil.fold(name+": "+body, 0));
+    	}
         return raw;
     }
 
     @Override
     public String toString() {
-        return getName() + ':' + getBody();
+        return getName() + ": " + getBody();
     }
 
     private String parseName() {
     	// make sure we ignore ending WSP (obsolete rfc822 syntax)
-    	int endIdx = colonIdx;
-    	while (endIdx > 0 && raw.byteAt(endIdx - 1) == 0x20 || raw.byteAt(endIdx
- 1) == 0x09) endIdx--;
-        return ContentUtil.decode(raw, 0, endIdx);
+        return ContentUtil.decode(raw, 0, headerNameEndIdx);
     }
 
     private String parseBody() {
         int offset = colonIdx + 1;
+        // if the header body starts with a space we remove it.
+        if (raw.length() > offset + 1 && (raw.byteAt(offset) & 0xff) == 0x20)
offset++;
         int length = raw.length() - offset;
         return MimeUtil.unfold(ContentUtil.decode(raw, offset, length));
     }
 
+	public boolean isObsoleteSyntax() {
+		return obsoleteSyntax;
+	}
+
 }

Modified: james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java
Wed Dec 30 00:41:00 2009
@@ -21,9 +21,7 @@
 
 import junit.framework.TestCase;
 
-import org.apache.james.mime4j.field.Field;
 import org.apache.james.mime4j.parser.RawField;
-import org.apache.james.mime4j.util.ByteSequence;
 
 public abstract class BaseTestForBodyDescriptors extends TestCase {
 
@@ -214,26 +212,9 @@
     
     private static final class TestField extends RawField {
 
-        private final String name;
-        private final String body;
-
-        public TestField(String name, String body){
-        	super(null, -1);
-            this.name = name;
-            this.body = body;
-        }
-        
-        public String getName() {
-            return name;
-        }
-
-        public String getBody() {
-            return body;
-        }
-
-        public ByteSequence getRaw() {
-            throw new UnsupportedOperationException();
+    	public TestField(String name, String body){
+        	super(name, body);
         }
-        
+    	
     }
 }

Modified: james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/message/HeaderTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/message/HeaderTest.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/message/HeaderTest.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/message/HeaderTest.java
Wed Dec 30 00:41:00 2009
@@ -53,7 +53,9 @@
         
         Field field = header.getField("Hello");
         assertNotNull(field);
-        assertEquals(hello, field.getBody());
+        // field.getBody is already a 7 bit ASCII string, after MIME4J-151
+        // assertEquals(hello, field.getBody());
+        assertEquals("Gr?ezi_z?m?", field.getBody());
         
         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
         

Modified: james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java?rev=894523&r1=894522&r2=894523&view=diff
==============================================================================
--- james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java
(original)
+++ james/mime4j/branches/cycleclean/core/src/test/java/org/apache/james/mime4j/parser/MimeEntityTest.java
Wed Dec 30 00:41:00 2009
@@ -66,23 +66,23 @@
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("To", entity.getField().getName());
-        assertEquals(" Road Runner <runner@example.org>", entity.getField().getBody());
+        assertEquals("Road Runner <runner@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("From", entity.getField().getName());
-        assertEquals(" Wile E. Cayote <wile@example.org>", entity.getField().getBody());
+        assertEquals("Wile E. Cayote <wile@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Date", entity.getField().getName());
-        assertEquals(" Tue, 12 Feb 2008 17:34:09 +0000 (GMT)", entity.getField().getBody());
+        assertEquals("Tue, 12 Feb 2008 17:34:09 +0000 (GMT)", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Subject", entity.getField().getName());
-        assertEquals(" Mail", entity.getField().getBody());
+        assertEquals("Mail", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Content-Type", entity.getField().getName());
-        assertEquals(" text/plain", entity.getField().getBody());
+        assertEquals("text/plain", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_END_HEADER, entity.getState());
         try {
@@ -145,11 +145,11 @@
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("To", entity.getField().getName());
-        assertEquals(" Road Runner <runner@example.org>", entity.getField().getBody());
+        assertEquals("Road Runner <runner@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("From", entity.getField().getName());
-        assertEquals(" Wile E. Cayote <wile@example.org>", entity.getField().getBody());
+        assertEquals("Wile E. Cayote <wile@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Date", entity.getField().getName());
@@ -161,7 +161,7 @@
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Content-Type", entity.getField().getName());
-        assertEquals(" text/plain", entity.getField().getBody());
+        assertEquals("text/plain", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_END_HEADER, entity.getState());
         try {
@@ -231,23 +231,23 @@
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("To", entity.getField().getName());
-        assertEquals(" Road Runner <runner@example.org>", entity.getField().getBody());
+        assertEquals("Road Runner <runner@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("From", entity.getField().getName());
-        assertEquals(" Wile E. Cayote <wile@example.org>", entity.getField().getBody());
+        assertEquals("Wile E. Cayote <wile@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Date", entity.getField().getName());
-        assertEquals(" Tue, 12 Feb 2008 17:34:09 +0000 (GMT)", entity.getField().getBody());
+        assertEquals("Tue, 12 Feb 2008 17:34:09 +0000 (GMT)", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Subject", entity.getField().getName());
-        assertEquals(" Mail", entity.getField().getBody());
+        assertEquals("Mail", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Content-Type", entity.getField().getName());
-        assertEquals(" multipart/mixed;boundary=1729", entity.getField().getBody());
+        assertEquals("multipart/mixed;boundary=1729", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_END_HEADER, entity.getState());
         entity.advance();
@@ -265,7 +265,7 @@
         p1.advance();
         assertEquals(EntityStates.T_FIELD, p1.getState());
         assertEquals("Content-Type", p1.getField().getName());
-        assertEquals(" text/plain; charset=US-ASCII", p1.getField().getBody());
+        assertEquals("text/plain; charset=US-ASCII", p1.getField().getBody());
         p1.advance();
         assertEquals(EntityStates.T_END_HEADER, p1.getState());
         p1.advance();
@@ -285,7 +285,7 @@
         p2.advance();
         assertEquals(EntityStates.T_FIELD, p2.getState());
         assertEquals("Content-Type", p2.getField().getName());
-        assertEquals(" text/plain; charset=US-ASCII", p2.getField().getBody());
+        assertEquals("text/plain; charset=US-ASCII", p2.getField().getBody());
         p2.advance();
         assertEquals(EntityStates.T_END_HEADER, p2.getState());
         p2.advance();
@@ -346,23 +346,23 @@
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("To", entity.getField().getName());
-        assertEquals(" Road Runner <runner@example.org>", entity.getField().getBody());
+        assertEquals("Road Runner <runner@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("From", entity.getField().getName());
-        assertEquals(" Wile E. Cayote <wile@example.org>", entity.getField().getBody());
+        assertEquals("Wile E. Cayote <wile@example.org>", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Date", entity.getField().getName());
-        assertEquals(" Tue, 12 Feb 2008 17:34:09 +0000 (GMT)", entity.getField().getBody());
+        assertEquals("Tue, 12 Feb 2008 17:34:09 +0000 (GMT)", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Subject", entity.getField().getName());
-        assertEquals(" Mail", entity.getField().getBody());
+        assertEquals("Mail", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_FIELD, entity.getState());
         assertEquals("Content-Type", entity.getField().getName());
-        assertEquals(" multipart/mixed;boundary=1729", entity.getField().getBody());
+        assertEquals("multipart/mixed;boundary=1729", entity.getField().getBody());
         entity.advance();
         assertEquals(EntityStates.T_END_HEADER, entity.getState());
         entity.advance();



Mime
View raw message