james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mwiederk...@apache.org
Subject svn commit: r737183 - in /james/mime4j/trunk/src: main/java/org/apache/james/mime4j/codec/ main/java/org/apache/james/mime4j/field/address/ test/java/org/apache/james/mime4j/codec/ test/java/org/apache/james/mime4j/field/address/
Date Fri, 23 Jan 2009 20:51:04 GMT
Author: mwiederkehr
Date: Fri Jan 23 12:51:03 2009
New Revision: 737183

URL: http://svn.apache.org/viewvc?rev=737183&view=rev
Log:
MIME4J-107: new method Address.getEncodedString()

Modified:
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/codec/EncoderUtil.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Group.java
    james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Mailbox.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/codec/EncoderUtilTest.java
    james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/codec/EncoderUtil.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/codec/EncoderUtil.java?rev=737183&r1=737182&r2=737183&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/codec/EncoderUtil.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/codec/EncoderUtil.java Fri Jan
23 12:51:03 2009
@@ -54,6 +54,8 @@
 
     private static final BitSet TOKEN_CHARS = initChars("()<>@,;:\\\"/[]?=");
 
+    private static final BitSet ATEXT_CHARS = initChars("()<>@.,;:\\\"[]");
+
     private static BitSet initChars(String specials) {
         BitSet bs = new BitSet(128);
         for (char ch = 33; ch < 127; ch++) {
@@ -95,6 +97,54 @@
     }
 
     /**
+     * Encodes the display-name portion of an address. See <a
+     * href='http://www.faqs.org/rfcs/rfc5322.html'>RFC 5322</a> section 3.4
+     * and <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC 2047</a> section
+     * 5.3. The specified string should not be folded.
+     * 
+     * @param displayName
+     *            display-name to encode.
+     * @return encoded display-name.
+     */
+    public static String encodeAddressDisplayName(String displayName) {
+        // display-name = phrase
+        // phrase = 1*( encoded-word / word )
+        // word = atom / quoted-string
+        // atom = [CFWS] 1*atext [CFWS]
+        // CFWS = comment or folding white space
+
+        if (isAtomPhrase(displayName)) {
+            return displayName;
+        } else if (hasToBeEncoded(displayName, 0)) {
+            return encodeEncodedWord(displayName, Usage.WORD_ENTITY);
+        } else {
+            return quote(displayName);
+        }
+    }
+
+    /**
+     * Encodes the local part of an address specification as described in RFC
+     * 5322 section 3.4.1. Leading and trailing CFWS should have been removed
+     * before calling this method. The specified string should not contain any
+     * illegal (control or non-ASCII) characters.
+     * 
+     * @param localPart
+     *            the local part to encode
+     * @return the encoded local part.
+     */
+    public static String encodeAddressLocalPart(String localPart) {
+        // local-part = dot-atom / quoted-string
+        // dot-atom = [CFWS] dot-atom-text [CFWS]
+        // CFWS = comment or folding white space
+
+        if (isDotAtomText(localPart)) {
+            return localPart;
+        } else {
+            return quote(localPart);
+        }
+    }
+
+    /**
      * Encodes the specified string as a value of a Content-Type parameter as
      * described in RFC 2045 section 5.1. The specified string should not
      * contain any illegal (control or non-ASCII) characters.
@@ -371,6 +421,45 @@
         return true;
     }
 
+    private static boolean isAtomPhrase(String str) {
+        // atom = [CFWS] 1*atext [CFWS]
+
+        final int length = str.length();
+        for (int idx = 0; idx < length; idx++) {
+            char ch = str.charAt(idx);
+            if (!ATEXT_CHARS.get(ch) && !CharsetUtil.isWhitespace(ch))
+                return false;
+        }
+
+        return true;
+    }
+
+    // RFC 5322 section 3.2.3
+    private static boolean isDotAtomText(String str) {
+        // dot-atom-text = 1*atext *("." 1*atext)
+        // atext = ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" /
+        // "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
+
+        char prev = '.';
+
+        final int length = str.length();
+        for (int idx = 0; idx < length; idx++) {
+            char ch = str.charAt(idx);
+
+            if (ch == '.') {
+                if (prev == '.' || idx == length - 1)
+                    return false;
+            } else {
+                if (!ATEXT_CHARS.get(ch))
+                    return false;
+            }
+
+            prev = ch;
+        }
+
+        return true;
+    }
+
     // RFC 5322 section 3.2.4
     private static String quote(String str) {
         // quoted-string = [CFWS] DQUOTE *([FWS] qcontent) [FWS] DQUOTE [CFWS]
@@ -383,7 +472,7 @@
         String escaped = str.replaceAll("[\\\\\"]", "\\\\$0");
         return "\"" + escaped + "\"";
     }
-    
+
     private static String encodeB(String prefix, String text,
             int usedCharacters, Charset charset, byte[] bytes) {
         int encodedLength = bEncodedLength(bytes);

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java?rev=737183&r1=737182&r2=737183&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Address.java Fri
Jan 23 12:51:03 2009
@@ -78,6 +78,17 @@
      */
     public abstract String getDisplayString(boolean includeRoute);
 
+    /**
+     * Returns a string representation of this address that can be used for
+     * transport purposes. The route is never included in this representation
+     * because routes are obsolete and RFC 5322 states that obsolete syntactic
+     * forms MUST NOT be generated.
+     * 
+     * @return a string representation of this address intended for transport
+     *         purposes.
+     */
+    public abstract String getEncodedString();
+
     @Override
     public String toString() {
         return getDisplayString(false);

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Group.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Group.java?rev=737183&r1=737182&r2=737183&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Group.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Group.java Fri
Jan 23 12:51:03 2009
@@ -21,6 +21,8 @@
 
 import java.util.List;
 
+import org.apache.james.mime4j.codec.EncoderUtil;
+
 /**
  * A named group of zero or more mailboxes.
  */
@@ -82,6 +84,25 @@
     }
 
     @Override
+    public String getEncodedString() {
+        StringBuilder buf = new StringBuilder();
+
+        for (Mailbox mailbox : mailboxList) {
+            if (buf.length() == 0) {
+                buf.append(EncoderUtil.encodeAddressDisplayName(name));
+                buf.append(':');
+            } else {
+                buf.append(',');
+            }
+            buf.append(mailbox.getEncodedString());
+        }
+
+        buf.append(';');
+
+        return buf.toString();
+    }
+
+    @Override
     protected void doAddMailboxesTo(List<Mailbox> results) {
         for (Mailbox mailbox : mailboxList) {
             results.add(mailbox);

Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Mailbox.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Mailbox.java?rev=737183&r1=737182&r2=737183&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Mailbox.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/address/Mailbox.java Fri
Jan 23 12:51:03 2009
@@ -23,6 +23,8 @@
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.james.mime4j.codec.EncoderUtil;
+
 /**
  * Represents a single e-mail address.
  */
@@ -191,6 +193,32 @@
     }
 
     @Override
+    public String getEncodedString() {
+        StringBuilder sb = new StringBuilder();
+
+        if (name != null) {
+            sb.append(EncoderUtil.encodeAddressDisplayName(name));
+            sb.append(" <");
+        }
+
+        sb.append(EncoderUtil.encodeAddressLocalPart(localPart));
+
+        // domain = dot-atom / domain-literal
+        // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
+        // dtext = %d33-90 / %d94-126
+        if (domain != null) {
+            sb.append('@');
+            sb.append(domain);
+        }
+
+        if (name != null) {
+            sb.append('>');
+        }
+
+        return sb.toString();
+    }
+
+    @Override
     public int hashCode() {
         return getCanonicalizedAddress().hashCode();
     }

Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/codec/EncoderUtilTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/codec/EncoderUtilTest.java?rev=737183&r1=737182&r2=737183&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/codec/EncoderUtilTest.java (original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/codec/EncoderUtilTest.java Fri
Jan 23 12:51:03 2009
@@ -30,6 +30,28 @@
 
 public class EncoderUtilTest extends TestCase {
 
+    public void testEncodeAddressDisplayName() throws Exception {
+        assertEquals("", EncoderUtil.encodeAddressDisplayName(""));
+        assertEquals("test", EncoderUtil.encodeAddressDisplayName("test"));
+        assertEquals(" test ", EncoderUtil.encodeAddressDisplayName(" test "));
+        assertEquals(" test\ttest ", EncoderUtil
+                .encodeAddressDisplayName(" test\ttest "));
+        assertEquals("\"test()\"", EncoderUtil
+                .encodeAddressDisplayName("test()"));
+        assertEquals("=?ISO-8859-1?Q?Semmelbr=F6sel?=", EncoderUtil
+                .encodeAddressDisplayName("Semmelbr\366sel"));
+        // dollar sign as to be encoded as =24 when used as a word in a phrase
+        assertEquals("=?UTF-8?Q?Dollar_=24_Euro_=E2=82=AC?=", EncoderUtil
+                .encodeAddressDisplayName("Dollar $ Euro \u20ac"));
+    }
+
+    public void testEncodeAddressLocalPart() throws Exception {
+        assertEquals("john.wayne", EncoderUtil
+                .encodeAddressLocalPart("john.wayne"));
+        assertEquals("\"clint eastwood\"", EncoderUtil
+                .encodeAddressLocalPart("clint eastwood"));
+    }
+
     public void testEncodeContentTypeParameterValue() throws Exception {
         assertEquals("test", EncoderUtil
                 .encodeContentTypeParameterValue("test"));

Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java?rev=737183&r1=737182&r2=737183&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java
(original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java
Fri Jan 23 12:51:03 2009
@@ -372,4 +372,30 @@
         } catch (ParseException pe) {
         }
     }
+    
+    public void testMailboxGetEncodedString() throws Exception {
+        assertEquals("john.doe@acme.org", new Mailbox("john.doe", "acme.org")
+                .getEncodedString());
+        assertEquals("\"john doe\"@acme.org", new Mailbox("john doe",
+                "acme.org").getEncodedString());
+        assertEquals("John Doe <john.doe@acme.org>", new Mailbox("John Doe",
+                "john.doe", "acme.org").getEncodedString());
+        assertEquals("\"John Doe @Home\" <john.doe@acme.org>", new Mailbox(
+                "John Doe @Home", "john.doe", "acme.org").getEncodedString());
+        assertEquals("=?ISO-8859-1?Q?Hans_M=FCller?= <hans.mueller@acme.org>",
+                new Mailbox("Hans M\374ller", "hans.mueller", "acme.org")
+                        .getEncodedString());
+    }
+
+    public void testGroupGetEncodedString() throws Exception {
+        List<Mailbox> al = new ArrayList<Mailbox>();
+        al.add(new Mailbox("test", "example.com"));
+        al.add(new Mailbox("Foo!", "foo", "example.com"));
+        al.add(new Mailbox("Hans M\374ller", "hans.mueller", "acme.org"));
+        Group g = new Group("group @work", new MailboxList(al, false));
+        assertEquals("\"group @work\":test@example.com,Foo! <foo@example.com>"
+                + ",=?ISO-8859-1?Q?Hans_M=FCller?= <hans.mueller@acme.org>;", g
+                .getEncodedString());
+    }
+    
 }



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


Mime
View raw message