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("[email protected]", new Mailbox("john.doe", "acme.org")
+ .getEncodedString());
+ assertEquals("\"john doe\"@acme.org", new Mailbox("john doe",
+ "acme.org").getEncodedString());
+ assertEquals("John Doe <[email protected]>", new Mailbox("John Doe",
+ "john.doe", "acme.org").getEncodedString());
+ assertEquals("\"John Doe @Home\" <[email protected]>", new Mailbox(
+ "John Doe @Home", "john.doe", "acme.org").getEncodedString());
+ assertEquals("=?ISO-8859-1?Q?Hans_M=FCller?= <[email protected]>",
+ 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\":[email protected],Foo! <[email protected]>"
+ + ",=?ISO-8859-1?Q?Hans_M=FCller?= <[email protected]>;", g
+ .getEncodedString());
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]