first commit

This commit is contained in:
MaddoScientisto 2026-03-14 20:04:39 +01:00
commit cf97b64877
27585 changed files with 3281780 additions and 0 deletions

View file

@ -0,0 +1,44 @@
package javax.mail.internet;
public class AddressException extends ParseException {
protected String ref = null;
protected int pos = -1;
private static final long serialVersionUID = 9134583443539323120L;
public AddressException() {}
public AddressException(String s) {
super(s);
}
public AddressException(String s, String ref) {
super(s);
this.ref = ref;
}
public AddressException(String s, String ref, int pos) {
super(s);
this.ref = ref;
this.pos = pos;
}
public String getRef() {
return this.ref;
}
public int getPos() {
return this.pos;
}
public String toString() {
String s = super.toString();
if (this.ref == null)
return s;
s = s + " in string ``" + this.ref + "''";
if (this.pos < 0)
return s;
return s + " at position " + this.pos;
}
}

View file

@ -0,0 +1,80 @@
package javax.mail.internet;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
class AsciiOutputStream extends OutputStream {
private boolean breakOnNonAscii;
private int ascii = 0, non_ascii = 0;
private int linelen = 0;
private boolean longLine = false;
private boolean badEOL = false;
private boolean checkEOL = false;
private int lastb = 0;
private int ret = 0;
public AsciiOutputStream(boolean breakOnNonAscii, boolean encodeEolStrict) {
this.breakOnNonAscii = breakOnNonAscii;
this.checkEOL = (encodeEolStrict && breakOnNonAscii);
}
public void write(int b) throws IOException {
check(b);
}
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len) throws IOException {
len += off;
for (int i = off; i < len; i++)
check(b[i]);
}
private final void check(int b) throws IOException {
b &= 0xFF;
if (this.checkEOL && ((this.lastb == 13 && b != 10) || (this.lastb != 13 && b == 10)))
this.badEOL = true;
if (b == 13 || b == 10) {
this.linelen = 0;
} else {
this.linelen++;
if (this.linelen > 998)
this.longLine = true;
}
if (MimeUtility.nonascii(b)) {
this.non_ascii++;
if (this.breakOnNonAscii) {
this.ret = 3;
throw new EOFException();
}
} else {
this.ascii++;
}
this.lastb = b;
}
public int getAscii() {
if (this.ret != 0)
return this.ret;
if (this.badEOL)
return 3;
if (this.non_ascii == 0) {
if (this.longLine)
return 2;
return 1;
}
if (this.ascii > this.non_ascii)
return 2;
return 3;
}
}

View file

@ -0,0 +1,64 @@
package javax.mail.internet;
public class ContentDisposition {
private String disposition;
private ParameterList list;
public ContentDisposition() {}
public ContentDisposition(String disposition, ParameterList list) {
this.disposition = disposition;
this.list = list;
}
public ContentDisposition(String s) throws ParseException {
HeaderTokenizer h = new HeaderTokenizer(s, "()<>@,;:\\\"\t []/?=");
HeaderTokenizer.Token tk = h.next();
if (tk.getType() != -1)
throw new ParseException("Expected disposition, got " +
tk.getValue());
this.disposition = tk.getValue();
String rem = h.getRemainder();
if (rem != null)
this.list = new ParameterList(rem);
}
public String getDisposition() {
return this.disposition;
}
public String getParameter(String name) {
if (this.list == null)
return null;
return this.list.get(name);
}
public ParameterList getParameterList() {
return this.list;
}
public void setDisposition(String disposition) {
this.disposition = disposition;
}
public void setParameter(String name, String value) {
if (this.list == null)
this.list = new ParameterList();
this.list.set(name, value);
}
public void setParameterList(ParameterList list) {
this.list = list;
}
public String toString() {
if (this.disposition == null)
return "";
if (this.list == null)
return this.disposition;
StringBuffer sb = new StringBuffer(this.disposition);
sb.append(this.list.toString(sb.length() + 21));
return sb.toString();
}
}

View file

@ -0,0 +1,113 @@
package javax.mail.internet;
public class ContentType {
private String primaryType;
private String subType;
private ParameterList list;
public ContentType() {}
public ContentType(String primaryType, String subType, ParameterList list) {
this.primaryType = primaryType;
this.subType = subType;
this.list = list;
}
public ContentType(String s) throws ParseException {
HeaderTokenizer h = new HeaderTokenizer(s, "()<>@,;:\\\"\t []/?=");
HeaderTokenizer.Token tk = h.next();
if (tk.getType() != -1)
throw new ParseException("In Content-Type string <" + s + ">" + ", expected MIME type, got " +
tk.getValue());
this.primaryType = tk.getValue();
tk = h.next();
if ((char)tk.getType() != '/')
throw new ParseException("In Content-Type string <" + s + ">" + ", expected '/', got " +
tk.getValue());
tk = h.next();
if (tk.getType() != -1)
throw new ParseException("In Content-Type string <" + s + ">" + ", expected MIME subtype, got " +
tk.getValue());
this.subType = tk.getValue();
String rem = h.getRemainder();
if (rem != null)
this.list = new ParameterList(rem);
}
public String getPrimaryType() {
return this.primaryType;
}
public String getSubType() {
return this.subType;
}
public String getBaseType() {
if (this.primaryType == null || this.subType == null)
return "";
return this.primaryType + '/' + this.subType;
}
public String getParameter(String name) {
if (this.list == null)
return null;
return this.list.get(name);
}
public ParameterList getParameterList() {
return this.list;
}
public void setPrimaryType(String primaryType) {
this.primaryType = primaryType;
}
public void setSubType(String subType) {
this.subType = subType;
}
public void setParameter(String name, String value) {
if (this.list == null)
this.list = new ParameterList();
this.list.set(name, value);
}
public void setParameterList(ParameterList list) {
this.list = list;
}
public String toString() {
if (this.primaryType == null || this.subType == null)
return "";
StringBuffer sb = new StringBuffer();
sb.append(this.primaryType).append('/').append(this.subType);
if (this.list != null)
sb.append(this.list.toString(sb.length() + 14));
return sb.toString();
}
public boolean match(ContentType cType) {
if ((this.primaryType != null || cType.getPrimaryType() != null) && (this.primaryType == null ||
!this.primaryType.equalsIgnoreCase(cType.getPrimaryType())))
return false;
String sType = cType.getSubType();
if ((this.subType != null && this.subType.startsWith("*")) || (sType != null &&
sType.startsWith("*")))
return true;
return ((this.subType == null && sType == null) || (this.subType != null &&
this.subType.equalsIgnoreCase(sType)));
}
public boolean match(String s) {
try {
return match(new ContentType(s));
} catch (ParseException pex) {
return false;
}
}
}

View file

@ -0,0 +1,243 @@
package javax.mail.internet;
public class HeaderTokenizer {
private String string;
private boolean skipComments;
private String delimiters;
private int currentPos;
private int maxPos;
private int nextPos;
private int peekPos;
public static final String RFC822 = "()<>@,;:\\\"\t .[]";
public static final String MIME = "()<>@,;:\\\"\t []/?=";
public static class Token {
private int type;
private String value;
public static final int ATOM = -1;
public static final int QUOTEDSTRING = -2;
public static final int COMMENT = -3;
public static final int EOF = -4;
public Token(int type, String value) {
this.type = type;
this.value = value;
}
public int getType() {
return this.type;
}
public String getValue() {
return this.value;
}
}
private static final Token EOFToken = new Token(-4, null);
public HeaderTokenizer(String header, String delimiters, boolean skipComments) {
this.string = (header == null) ? "" : header;
this.skipComments = skipComments;
this.delimiters = delimiters;
this.currentPos = this.nextPos = this.peekPos = 0;
this.maxPos = this.string.length();
}
public HeaderTokenizer(String header, String delimiters) {
this(header, delimiters, true);
}
public HeaderTokenizer(String header) {
this(header, "()<>@,;:\\\"\t .[]");
}
public Token next() throws ParseException {
return next('\000', false);
}
public Token next(char endOfAtom) throws ParseException {
return next(endOfAtom, false);
}
public Token next(char endOfAtom, boolean keepEscapes) throws ParseException {
this.currentPos = this.nextPos;
Token tk = getNext(endOfAtom, keepEscapes);
this.nextPos = this.peekPos = this.currentPos;
return tk;
}
public Token peek() throws ParseException {
this.currentPos = this.peekPos;
Token tk = getNext('\000', false);
this.peekPos = this.currentPos;
return tk;
}
public String getRemainder() {
if (this.nextPos >= this.string.length())
return null;
return this.string.substring(this.nextPos);
}
private Token getNext(char endOfAtom, boolean keepEscapes) throws ParseException {
if (this.currentPos >= this.maxPos)
return EOFToken;
if (skipWhiteSpace() == -4)
return EOFToken;
boolean filter = false;
char c = this.string.charAt(this.currentPos);
while (c == '(') {
int i = ++this.currentPos, nesting = 1;
for (; nesting > 0 && this.currentPos < this.maxPos;
this.currentPos++) {
c = this.string.charAt(this.currentPos);
if (c == '\\') {
this.currentPos++;
filter = true;
} else if (c == '\r') {
filter = true;
} else if (c == '(') {
nesting++;
} else if (c == ')') {
nesting--;
}
}
if (nesting != 0)
throw new ParseException("Unbalanced comments");
if (!this.skipComments) {
String s;
if (filter) {
s = filterToken(this.string, i, this.currentPos - 1, keepEscapes);
} else {
s = this.string.substring(i, this.currentPos - 1);
}
return new Token(-3, s);
}
if (skipWhiteSpace() == -4)
return EOFToken;
c = this.string.charAt(this.currentPos);
}
if (c == '"') {
this.currentPos++;
return collectString('"', keepEscapes);
}
if (c < ' ' || c >= '\u007F' || this.delimiters.indexOf(c) >= 0) {
if (endOfAtom > '\000' && c != endOfAtom)
return collectString(endOfAtom, keepEscapes);
this.currentPos++;
char[] ch = new char[1];
ch[0] = c;
return new Token(c, new String(ch));
}
int start;
for (start = this.currentPos; this.currentPos < this.maxPos; this.currentPos++) {
c = this.string.charAt(this.currentPos);
if (c < ' ' || c >= '\u007F' || c == '(' || c == ' ' || c == '"' ||
this.delimiters.indexOf(c) >= 0) {
if (endOfAtom > '\000' && c != endOfAtom) {
this.currentPos = start;
return collectString(endOfAtom, keepEscapes);
}
break;
}
}
return new Token(-1, this.string.substring(start, this.currentPos));
}
private Token collectString(char eos, boolean keepEscapes) throws ParseException {
boolean filter = false;
int start;
for (start = this.currentPos; this.currentPos < this.maxPos; this.currentPos++) {
char c = this.string.charAt(this.currentPos);
if (c == '\\') {
this.currentPos++;
filter = true;
} else if (c == '\r') {
filter = true;
} else if (c == eos) {
String str;
this.currentPos++;
if (filter) {
str = filterToken(this.string, start, this.currentPos - 1, keepEscapes);
} else {
str = this.string.substring(start, this.currentPos - 1);
}
if (c != '"') {
str = trimWhiteSpace(str);
this.currentPos--;
}
return new Token(-2, str);
}
}
if (eos == '"')
throw new ParseException("Unbalanced quoted string");
if (filter) {
s = filterToken(this.string, start, this.currentPos, keepEscapes);
} else {
s = this.string.substring(start, this.currentPos);
}
String s = trimWhiteSpace(s);
return new Token(-2, s);
}
private int skipWhiteSpace() {
for (; this.currentPos < this.maxPos; this.currentPos++) {
char c;
if ((c = this.string.charAt(this.currentPos)) != ' ' && c != '\t' && c != '\r' && c != '\n')
return this.currentPos;
}
return -4;
}
private static String trimWhiteSpace(String s) {
char c;
int i;
for (i = s.length() - 1; i >= 0 && ((
c = s.charAt(i)) == ' ' || c == '\t' || c == '\r' || c == '\n'); i--);
if (i <= 0)
return "";
return s.substring(0, i + 1);
}
private static String filterToken(String s, int start, int end, boolean keepEscapes) {
StringBuffer sb = new StringBuffer();
boolean gotEscape = false;
boolean gotCR = false;
for (int i = start; i < end; i++) {
char c = s.charAt(i);
if (c == '\n' && gotCR) {
gotCR = false;
} else {
gotCR = false;
if (!gotEscape) {
if (c == '\\') {
gotEscape = true;
} else if (c == '\r') {
gotCR = true;
} else {
sb.append(c);
}
} else {
if (keepEscapes)
sb.append('\\');
sb.append(c);
gotEscape = false;
}
}
}
return sb.toString();
}
}

View file

@ -0,0 +1,782 @@
package javax.mail.internet;
import com.sun.mail.util.PropUtil;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import javax.mail.Address;
import javax.mail.Session;
public class InternetAddress extends Address implements Cloneable {
protected String address;
protected String personal;
protected String encodedPersonal;
private static final long serialVersionUID = -7507595530758302903L;
private static final boolean ignoreBogusGroupName = PropUtil.getBooleanSystemProperty("mail.mime.address.ignorebogusgroupname", true);
public InternetAddress() {}
public InternetAddress(String address) throws AddressException {
InternetAddress[] a = parse(address, true);
if (a.length != 1)
throw new AddressException("Illegal address", address);
this.address = (a[0]).address;
this.personal = (a[0]).personal;
this.encodedPersonal = (a[0]).encodedPersonal;
}
public InternetAddress(String address, boolean strict) throws AddressException {
this(address);
if (strict)
if (isGroup()) {
getGroup(true);
} else {
checkAddress(this.address, true, true);
}
}
public InternetAddress(String address, String personal) throws UnsupportedEncodingException {
this(address, personal, null);
}
public InternetAddress(String address, String personal, String charset) throws UnsupportedEncodingException {
this.address = address;
setPersonal(personal, charset);
}
public Object clone() {
InternetAddress a = null;
try {
a = (InternetAddress)super.clone();
} catch (CloneNotSupportedException e) {}
return a;
}
public String getType() {
return "rfc822";
}
public void setAddress(String address) {
this.address = address;
}
public void setPersonal(String name, String charset) throws UnsupportedEncodingException {
this.personal = name;
if (name != null) {
this.encodedPersonal = MimeUtility.encodeWord(name, charset, null);
} else {
this.encodedPersonal = null;
}
}
public void setPersonal(String name) throws UnsupportedEncodingException {
this.personal = name;
if (name != null) {
this.encodedPersonal = MimeUtility.encodeWord(name);
} else {
this.encodedPersonal = null;
}
}
public String getAddress() {
return this.address;
}
public String getPersonal() {
if (this.personal != null)
return this.personal;
if (this.encodedPersonal != null)
try {
this.personal = MimeUtility.decodeText(this.encodedPersonal);
return this.personal;
} catch (Exception ex) {
return this.encodedPersonal;
}
return null;
}
public String toString() {
String a = (this.address == null) ? "" : this.address;
if (this.encodedPersonal == null && this.personal != null)
try {
this.encodedPersonal = MimeUtility.encodeWord(this.personal);
} catch (UnsupportedEncodingException e) {}
if (this.encodedPersonal != null)
return quotePhrase(this.encodedPersonal) + " <" + a + ">";
if (isGroup() || isSimple())
return a;
return "<" + a + ">";
}
public String toUnicodeString() {
String p = getPersonal();
if (p != null)
return quotePhrase(p) + " <" + this.address + ">";
if (isGroup() || isSimple())
return this.address;
return "<" + this.address + ">";
}
private static final String rfc822phrase = "()<>@,;:\\\"\t .[]"
.replace(' ', '\000').replace('\t', '\000');
private static final String specialsNoDotNoAt = "()<>,;:\\\"[]";
private static final String specialsNoDot = "()<>,;:\\\"[]@";
private static String quotePhrase(String phrase) {
int len = phrase.length();
boolean needQuoting = false;
for (int i = 0; i < len; i++) {
char c = phrase.charAt(i);
if (c == '"' || c == '\\') {
StringBuffer sb = new StringBuffer(len + 3);
sb.append('"');
for (int j = 0; j < len; j++) {
char cc = phrase.charAt(j);
if (cc == '"' || cc == '\\')
sb.append('\\');
sb.append(cc);
}
sb.append('"');
return sb.toString();
}
if ((c < ' ' && c != '\r' && c != '\n' && c != '\t') || c >= '\u007F' ||
rfc822phrase.indexOf(c) >= 0)
needQuoting = true;
}
if (needQuoting) {
StringBuffer sb = new StringBuffer(len + 2);
sb.append('"').append(phrase).append('"');
return sb.toString();
}
return phrase;
}
private static String unquote(String s) {
if (s.startsWith("\"") && s.endsWith("\"") && s.length() > 1) {
s = s.substring(1, s.length() - 1);
if (s.indexOf('\\') >= 0) {
StringBuffer sb = new StringBuffer(s.length());
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\' && i < s.length() - 1)
c = s.charAt(++i);
sb.append(c);
}
s = sb.toString();
}
}
return s;
}
public boolean equals(Object a) {
if (!(a instanceof InternetAddress))
return false;
String s = ((InternetAddress)a).getAddress();
if (s == this.address)
return true;
if (this.address != null && this.address.equalsIgnoreCase(s))
return true;
return false;
}
public int hashCode() {
if (this.address == null)
return 0;
return this.address.toLowerCase(Locale.ENGLISH).hashCode();
}
public static String toString(Address[] addresses) {
return toString(addresses, 0);
}
public static String toString(Address[] addresses, int used) {
if (addresses == null || addresses.length == 0)
return null;
StringBuffer sb = new StringBuffer();
for (int i = 0; i < addresses.length; i++) {
if (i != 0) {
sb.append(", ");
used += 2;
}
String s = addresses[i].toString();
int len = lengthOfFirstSegment(s);
if (used + len > 76) {
sb.append("\r\n\t");
used = 8;
}
sb.append(s);
used = lengthOfLastSegment(s, used);
}
return sb.toString();
}
private static int lengthOfFirstSegment(String s) {
int pos;
if ((pos = s.indexOf("\r\n")) != -1)
return pos;
return s.length();
}
private static int lengthOfLastSegment(String s, int used) {
int pos;
if ((pos = s.lastIndexOf("\r\n")) != -1)
return s.length() - pos - 2;
return s.length() + used;
}
public static InternetAddress getLocalAddress(Session session) {
try {
return _getLocalAddress(session);
} catch (SecurityException e) {
} catch (AddressException e) {
} catch (UnknownHostException e) {}
return null;
}
static InternetAddress _getLocalAddress(Session session) throws SecurityException, AddressException, UnknownHostException {
String user = null, host = null, address = null;
if (session == null) {
user = System.getProperty("user.name");
host = getLocalHostName();
} else {
address = session.getProperty("mail.from");
if (address == null) {
user = session.getProperty("mail.user");
if (user == null || user.length() == 0)
user = session.getProperty("user.name");
if (user == null || user.length() == 0)
user = System.getProperty("user.name");
host = session.getProperty("mail.host");
if (host == null || host.length() == 0)
host = getLocalHostName();
}
}
if (address == null && user != null && user.length() != 0 && host != null &&
host.length() != 0)
address = MimeUtility.quote(user.trim(), "()<>,;:\\\"[]@\t ") + "@" + host;
if (address == null)
return null;
return new InternetAddress(address);
}
private static String getLocalHostName() throws UnknownHostException {
String host = null;
InetAddress me = InetAddress.getLocalHost();
if (me != null) {
host = me.getHostName();
if (host != null && host.length() > 0 && isInetAddressLiteral(host))
host = '[' + host + ']';
}
return host;
}
private static boolean isInetAddressLiteral(String addr) {
boolean sawHex = false, sawColon = false;
for (int i = 0; i < addr.length(); i++) {
char c = addr.charAt(i);
if (c < '0' || c > '9')
if (c != '.')
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
sawHex = true;
} else if (c == ':') {
sawColon = true;
} else {
return false;
}
}
return (!sawHex || sawColon);
}
public static InternetAddress[] parse(String addresslist) throws AddressException {
return parse(addresslist, true);
}
public static InternetAddress[] parse(String addresslist, boolean strict) throws AddressException {
return parse(addresslist, strict, false);
}
public static InternetAddress[] parseHeader(String addresslist, boolean strict) throws AddressException {
return parse(MimeUtility.unfold(addresslist), strict, true);
}
private static InternetAddress[] parse(String s, boolean strict, boolean parseHdr) throws AddressException {
int start_personal = -1, end_personal = -1;
int length = s.length();
boolean ignoreErrors = (parseHdr && !strict);
boolean in_group = false;
boolean route_addr = false;
boolean rfc822 = false;
List<InternetAddress> v = new ArrayList();
int start, end, index;
for (start = end = -1, index = 0; index < length; index++) {
int nesting, pindex, rindex;
boolean inquote;
int qindex, lindex;
String addr, pers;
char c = s.charAt(index);
switch (c) {
case '(':
rfc822 = true;
if (start >= 0 && end == -1)
end = index;
pindex = index;
index++;
for (nesting = 1; index < length && nesting > 0;
index++) {
c = s.charAt(index);
switch (c) {
case '\\':
index++;
break;
case '(':
nesting++;
break;
case ')':
nesting--;
break;
}
}
if (nesting > 0) {
if (!ignoreErrors)
throw new AddressException("Missing ')'", s, index);
index = pindex + 1;
break;
}
index--;
if (start_personal == -1)
start_personal = pindex + 1;
if (end_personal == -1)
end_personal = index;
break;
case ')':
if (!ignoreErrors)
throw new AddressException("Missing '('", s, index);
if (start == -1)
start = index;
break;
case '<':
rfc822 = true;
if (route_addr) {
if (!ignoreErrors)
throw new AddressException("Extra route-addr", s, index);
if (start == -1) {
route_addr = false;
rfc822 = false;
start = end = -1;
break;
}
if (!in_group) {
if (end == -1)
end = index;
String str = s.substring(start, end).trim();
InternetAddress ma = new InternetAddress();
ma.setAddress(str);
if (start_personal >= 0)
ma.encodedPersonal = unquote(
s.substring(start_personal, end_personal)
.trim());
v.add(ma);
route_addr = false;
rfc822 = false;
start = end = -1;
start_personal = end_personal = -1;
}
}
rindex = index;
inquote = false;
for (; ++index < length; index++) {
c = s.charAt(index);
switch (c) {
case '\\':
index++;
break;
case '"':
inquote = !inquote;
break;
case '>':
if (inquote)
break;
break;
}
}
if (inquote) {
if (!ignoreErrors)
throw new AddressException("Missing '\"'", s, index);
for (index = rindex + 1; index < length; index++) {
c = s.charAt(index);
if (c == '\\') {
index++;
} else if (c == '>') {
break;
}
}
}
if (index >= length) {
if (!ignoreErrors)
throw new AddressException("Missing '>'", s, index);
index = rindex + 1;
if (start == -1)
start = rindex;
break;
}
if (!in_group) {
if (start >= 0) {
start_personal = start;
end_personal = rindex;
}
start = rindex + 1;
}
route_addr = true;
end = index;
break;
case '>':
if (!ignoreErrors)
throw new AddressException("Missing '<'", s, index);
if (start == -1)
start = index;
break;
case '"':
qindex = index;
rfc822 = true;
if (start == -1)
start = index;
for (; ++index < length; index++) {
c = s.charAt(index);
switch (c) {
case '\\':
index++;
break;
case '"':
break;
}
}
if (index >= length) {
if (!ignoreErrors)
throw new AddressException("Missing '\"'", s, index);
index = qindex + 1;
}
break;
case '[':
rfc822 = true;
lindex = index;
for (; ++index < length; index++) {
c = s.charAt(index);
switch (c) {
case '\\':
index++;
break;
case ']':
break;
}
}
if (index >= length) {
if (!ignoreErrors)
throw new AddressException("Missing ']'", s, index);
index = lindex + 1;
}
break;
case ';':
if (start == -1) {
route_addr = false;
rfc822 = false;
start = end = -1;
break;
}
if (in_group) {
in_group = false;
if (parseHdr && !strict && index + 1 < length &&
s.charAt(index + 1) == '@')
break;
InternetAddress ma = new InternetAddress();
end = index + 1;
ma.setAddress(s.substring(start, end).trim());
v.add(ma);
route_addr = false;
rfc822 = false;
start = end = -1;
start_personal = end_personal = -1;
break;
}
if (!ignoreErrors)
throw new AddressException("Illegal semicolon, not in group", s, index);
case ',':
if (start == -1) {
route_addr = false;
rfc822 = false;
start = end = -1;
break;
}
if (in_group) {
route_addr = false;
break;
}
if (end == -1)
end = index;
addr = s.substring(start, end).trim();
pers = null;
if (rfc822 && start_personal >= 0) {
pers = unquote(
s.substring(start_personal, end_personal).trim());
if (pers.trim().length() == 0)
pers = null;
}
if (parseHdr && !strict && pers != null &&
pers.indexOf('@') >= 0 &&
addr.indexOf('@') < 0 && addr.indexOf('!') < 0) {
String tmp = addr;
addr = pers;
pers = tmp;
}
if (rfc822 || strict || parseHdr) {
if (!ignoreErrors)
checkAddress(addr, route_addr, false);
InternetAddress ma = new InternetAddress();
ma.setAddress(addr);
if (pers != null)
ma.encodedPersonal = pers;
v.add(ma);
} else {
StringTokenizer st = new StringTokenizer(addr);
while (st.hasMoreTokens()) {
String str = st.nextToken();
checkAddress(str, false, false);
InternetAddress ma = new InternetAddress();
ma.setAddress(str);
v.add(ma);
}
}
route_addr = false;
rfc822 = false;
start = end = -1;
start_personal = end_personal = -1;
break;
case ':':
rfc822 = true;
if (in_group &&
!ignoreErrors)
throw new AddressException("Nested group", s, index);
if (start == -1)
start = index;
if (parseHdr && !strict) {
if (index + 1 < length) {
String addressSpecials = ")>[]:@\\,.";
char nc = s.charAt(index + 1);
if (addressSpecials.indexOf(nc) >= 0) {
if (nc != '@')
break;
for (int i = index + 2; i < length; i++) {
nc = s.charAt(i);
if (nc == ';')
break;
if (addressSpecials.indexOf(nc) >= 0)
break;
}
if (nc == ';')
break;
}
}
String gname = s.substring(start, index);
if (ignoreBogusGroupName && (
gname.equalsIgnoreCase("mailto") ||
gname.equalsIgnoreCase("From") ||
gname.equalsIgnoreCase("To") ||
gname.equalsIgnoreCase("Cc") ||
gname.equalsIgnoreCase("Subject") ||
gname.equalsIgnoreCase("Re"))) {
start = -1;
} else {
in_group = true;
}
break;
}
in_group = true;
break;
case '\t':
case '\n':
case '\r':
case ' ':
break;
default:
if (start == -1)
start = index;
break;
}
}
if (start >= 0) {
if (end == -1)
end = length;
String addr = s.substring(start, end).trim();
String pers = null;
if (rfc822 && start_personal >= 0) {
pers = unquote(
s.substring(start_personal, end_personal).trim());
if (pers.trim().length() == 0)
pers = null;
}
if (parseHdr && !strict && pers != null &&
pers.indexOf('@') >= 0 &&
addr.indexOf('@') < 0 && addr.indexOf('!') < 0) {
String tmp = addr;
addr = pers;
pers = tmp;
}
if (rfc822 || strict || parseHdr) {
if (!ignoreErrors)
checkAddress(addr, route_addr, false);
InternetAddress ma = new InternetAddress();
ma.setAddress(addr);
if (pers != null)
ma.encodedPersonal = pers;
v.add(ma);
} else {
StringTokenizer st = new StringTokenizer(addr);
while (st.hasMoreTokens()) {
String str = st.nextToken();
checkAddress(str, false, false);
InternetAddress ma = new InternetAddress();
ma.setAddress(str);
v.add(ma);
}
}
}
InternetAddress[] a = new InternetAddress[v.size()];
v.<InternetAddress>toArray(a);
return a;
}
public void validate() throws AddressException {
if (isGroup()) {
getGroup(true);
} else {
checkAddress(getAddress(), true, true);
}
}
private static void checkAddress(String addr, boolean routeAddr, boolean validate) throws AddressException {
int start = 0;
if (addr == null)
throw new AddressException("Address is null");
int len = addr.length();
if (len == 0)
throw new AddressException("Empty address", addr);
if (routeAddr && addr.charAt(0) == '@') {
int j;
for (start = 0; (j = indexOfAny(addr, ",:", start)) >= 0;
start = j + 1) {
if (addr.charAt(start) != '@')
throw new AddressException("Illegal route-addr", addr);
if (addr.charAt(j) == ':') {
start = j + 1;
break;
}
}
}
char c = Character.MAX_VALUE;
char lastc = Character.MAX_VALUE;
boolean inquote = false;
int i;
for (i = start; i < len; i++) {
lastc = c;
c = addr.charAt(i);
if (c != '\\' && lastc != '\\')
if (c == '"') {
if (inquote) {
if (validate && i + 1 < len && addr.charAt(i + 1) != '@')
throw new AddressException("Quote not at end of local address", addr);
inquote = false;
} else {
if (validate && i != 0)
throw new AddressException("Quote not at start of local address", addr);
inquote = true;
}
} else if (!inquote) {
if (c == '@') {
if (i == 0)
throw new AddressException("Missing local name", addr);
break;
}
if (c <= ' ' || c >= '\u007F')
throw new AddressException("Local address contains control or whitespace", addr);
if ("()<>,;:\\\"[]@".indexOf(c) >= 0)
throw new AddressException("Local address contains illegal character", addr);
}
}
if (inquote)
throw new AddressException("Unterminated quote", addr);
if (c != '@') {
if (validate)
throw new AddressException("Missing final '@domain'", addr);
return;
}
start = i + 1;
if (start >= len)
throw new AddressException("Missing domain", addr);
if (addr.charAt(start) == '.')
throw new AddressException("Domain starts with dot", addr);
for (i = start; i < len; i++) {
c = addr.charAt(i);
if (c == '[')
return;
if (c <= ' ' || c >= '\u007F')
throw new AddressException("Domain contains control or whitespace", addr);
if (!Character.isLetterOrDigit(c) && c != '-' && c != '.')
throw new AddressException("Domain contains illegal character", addr);
if (c == '.' && lastc == '.')
throw new AddressException("Domain contains dot-dot", addr);
lastc = c;
}
if (lastc == '.')
throw new AddressException("Domain ends with dot", addr);
}
private boolean isSimple() {
return (this.address == null || indexOfAny(this.address, "()<>,;:\\\"[]") < 0);
}
public boolean isGroup() {
return (this.address != null &&
this.address.endsWith(";") && this.address.indexOf(':') > 0);
}
public InternetAddress[] getGroup(boolean strict) throws AddressException {
String addr = getAddress();
if (addr == null)
return null;
if (!addr.endsWith(";"))
return null;
int ix = addr.indexOf(':');
if (ix < 0)
return null;
String list = addr.substring(ix + 1, addr.length() - 1);
return parseHeader(list, strict);
}
private static int indexOfAny(String s, String any) {
return indexOfAny(s, any, 0);
}
private static int indexOfAny(String s, String any, int start) {
try {
int len = s.length();
for (int i = start; i < len; i++) {
if (any.indexOf(s.charAt(i)) >= 0)
return i;
}
return -1;
} catch (StringIndexOutOfBoundsException e) {
return -1;
}
}
}

View file

@ -0,0 +1,308 @@
package javax.mail.internet;
import com.sun.mail.util.LineInputStream;
import com.sun.mail.util.PropUtil;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import javax.mail.Header;
import javax.mail.MessagingException;
public class InternetHeaders {
private static final boolean ignoreWhitespaceLines = PropUtil.getBooleanSystemProperty("mail.mime.ignorewhitespacelines", false);
protected List headers;
protected static final class InternetHeader extends Header {
String line;
public InternetHeader(String l) {
super("", "");
int i = l.indexOf(':');
if (i < 0) {
this.name = l.trim();
} else {
this.name = l.substring(0, i).trim();
}
this.line = l;
}
public InternetHeader(String n, String v) {
super(n, "");
if (v != null) {
this.line = n + ": " + v;
} else {
this.line = null;
}
}
public String getValue() {
int i = this.line.indexOf(':');
if (i < 0)
return this.line;
int j;
for (j = i + 1; j < this.line.length(); j++) {
char c = this.line.charAt(j);
if (c != ' ' && c != '\t' && c != '\r' && c != '\n')
break;
}
return this.line.substring(j);
}
}
static class MatchEnum implements Enumeration {
private Iterator e;
private String[] names;
private boolean match;
private boolean want_line;
private InternetHeaders.InternetHeader next_header;
MatchEnum(List v, String[] n, boolean m, boolean l) {
this.e = v.iterator();
this.names = n;
this.match = m;
this.want_line = l;
this.next_header = null;
}
public boolean hasMoreElements() {
if (this.next_header == null)
this.next_header = nextMatch();
return (this.next_header != null);
}
public Object nextElement() {
if (this.next_header == null)
this.next_header = nextMatch();
if (this.next_header == null)
throw new NoSuchElementException("No more headers");
InternetHeaders.InternetHeader h = this.next_header;
this.next_header = null;
if (this.want_line)
return h.line;
return new Header(h.getName(), h.getValue());
}
private InternetHeaders.InternetHeader nextMatch() {
label23: while (this.e.hasNext()) {
InternetHeaders.InternetHeader h = this.e.next();
if (h.line == null)
continue;
if (this.names == null)
return this.match ? null : h;
for (int i = 0; i < this.names.length; i++) {
if (this.names[i].equalsIgnoreCase(h.getName())) {
if (this.match)
return h;
continue label23;
}
}
if (!this.match)
return h;
}
return null;
}
}
public InternetHeaders() {
this.headers = new ArrayList(40);
this.headers.add(new InternetHeader("Return-Path", null));
this.headers.add(new InternetHeader("Received", null));
this.headers.add(new InternetHeader("Resent-Date", null));
this.headers.add(new InternetHeader("Resent-From", null));
this.headers.add(new InternetHeader("Resent-Sender", null));
this.headers.add(new InternetHeader("Resent-To", null));
this.headers.add(new InternetHeader("Resent-Cc", null));
this.headers.add(new InternetHeader("Resent-Bcc", null));
this.headers.add(new InternetHeader("Resent-Message-Id", null));
this.headers.add(new InternetHeader("Date", null));
this.headers.add(new InternetHeader("From", null));
this.headers.add(new InternetHeader("Sender", null));
this.headers.add(new InternetHeader("Reply-To", null));
this.headers.add(new InternetHeader("To", null));
this.headers.add(new InternetHeader("Cc", null));
this.headers.add(new InternetHeader("Bcc", null));
this.headers.add(new InternetHeader("Message-Id", null));
this.headers.add(new InternetHeader("In-Reply-To", null));
this.headers.add(new InternetHeader("References", null));
this.headers.add(new InternetHeader("Subject", null));
this.headers.add(new InternetHeader("Comments", null));
this.headers.add(new InternetHeader("Keywords", null));
this.headers.add(new InternetHeader("Errors-To", null));
this.headers.add(new InternetHeader("MIME-Version", null));
this.headers.add(new InternetHeader("Content-Type", null));
this.headers.add(new InternetHeader("Content-Transfer-Encoding", null));
this.headers.add(new InternetHeader("Content-MD5", null));
this.headers.add(new InternetHeader(":", null));
this.headers.add(new InternetHeader("Content-Length", null));
this.headers.add(new InternetHeader("Status", null));
}
public InternetHeaders(InputStream is) throws MessagingException {
this.headers = new ArrayList(40);
load(is);
}
public void load(InputStream is) throws MessagingException {
LineInputStream lis = new LineInputStream(is);
String prevline = null;
StringBuffer lineBuffer = new StringBuffer();
try {
String line;
do {
line = lis.readLine();
if (line != null && (
line.startsWith(" ") || line.startsWith("\t"))) {
if (prevline != null) {
lineBuffer.append(prevline);
prevline = null;
}
lineBuffer.append("\r\n");
lineBuffer.append(line);
} else {
if (prevline != null) {
addHeaderLine(prevline);
} else if (lineBuffer.length() > 0) {
addHeaderLine(lineBuffer.toString());
lineBuffer.setLength(0);
}
prevline = line;
}
} while (line != null && !isEmpty(line));
} catch (IOException ioex) {
throw new MessagingException("Error in input stream", ioex);
}
}
private static final boolean isEmpty(String line) {
return (line.length() == 0 || (ignoreWhitespaceLines &&
line.trim().length() == 0));
}
public String[] getHeader(String name) {
Iterator<InternetHeader> e = this.headers.iterator();
List<String> v = new ArrayList();
while (e.hasNext()) {
InternetHeader h = e.next();
if (name.equalsIgnoreCase(h.getName()) && h.line != null)
v.add(h.getValue());
}
if (v.size() == 0)
return null;
String[] r = new String[v.size()];
r = v.<String>toArray(r);
return r;
}
public String getHeader(String name, String delimiter) {
String[] s = getHeader(name);
if (s == null)
return null;
if (s.length == 1 || delimiter == null)
return s[0];
StringBuffer r = new StringBuffer(s[0]);
for (int i = 1; i < s.length; i++) {
r.append(delimiter);
r.append(s[i]);
}
return r.toString();
}
public void setHeader(String name, String value) {
boolean found = false;
for (int i = 0; i < this.headers.size(); i++) {
InternetHeader h = this.headers.get(i);
if (name.equalsIgnoreCase(h.getName()))
if (!found) {
int j;
if (h.line != null && (j = h.line.indexOf(':')) >= 0) {
h.line = h.line.substring(0, j + 1) + " " + value;
} else {
h.line = name + ": " + value;
}
found = true;
} else {
this.headers.remove(i);
i--;
}
}
if (!found)
addHeader(name, value);
}
public void addHeader(String name, String value) {
int pos = this.headers.size();
boolean addReverse = (
name.equalsIgnoreCase("Received") ||
name.equalsIgnoreCase("Return-Path"));
if (addReverse)
pos = 0;
for (int i = this.headers.size() - 1; i >= 0; i--) {
InternetHeader h = this.headers.get(i);
if (name.equalsIgnoreCase(h.getName()))
if (addReverse) {
pos = i;
} else {
this.headers.add(i + 1, new InternetHeader(name, value));
return;
}
if (!addReverse && h.getName().equals(":"))
pos = i;
}
this.headers.add(pos, new InternetHeader(name, value));
}
public void removeHeader(String name) {
for (int i = 0; i < this.headers.size(); i++) {
InternetHeader h = this.headers.get(i);
if (name.equalsIgnoreCase(h.getName()))
h.line = null;
}
}
public Enumeration getAllHeaders() {
return new MatchEnum(this.headers, null, false, false);
}
public Enumeration getMatchingHeaders(String[] names) {
return new MatchEnum(this.headers, names, true, false);
}
public Enumeration getNonMatchingHeaders(String[] names) {
return new MatchEnum(this.headers, names, false, false);
}
public void addHeaderLine(String line) {
try {
char c = line.charAt(0);
if (c == ' ' || c == '\t') {
InternetHeader h = this.headers.get(this.headers.size() - 1);
h.line += "\r\n" + line;
} else {
this.headers.add(new InternetHeader(line));
}
} catch (StringIndexOutOfBoundsException e) {
return;
} catch (NoSuchElementException e) {}
}
public Enumeration getAllHeaderLines() {
return getNonMatchingHeaderLines(null);
}
public Enumeration getMatchingHeaderLines(String[] names) {
return new MatchEnum(this.headers, names, true, true);
}
public Enumeration getNonMatchingHeaderLines(String[] names) {
return new MatchEnum(this.headers, names, false, true);
}
}

View file

@ -0,0 +1,125 @@
package javax.mail.internet;
import com.sun.mail.util.MailLogger;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.logging.Level;
public class MailDateFormat extends SimpleDateFormat {
private static final long serialVersionUID = -8148227605210628779L;
public MailDateFormat() {
super("EEE, d MMM yyyy HH:mm:ss 'XXXXX' (z)", Locale.US);
}
public StringBuffer format(Date date, StringBuffer dateStrBuf, FieldPosition fieldPosition) {
int start = dateStrBuf.length();
super.format(date, dateStrBuf, fieldPosition);
int pos = 0;
for (pos = start + 25; dateStrBuf.charAt(pos) != 'X'; pos++);
this.calendar.clear();
this.calendar.setTime(date);
int offset = this.calendar.get(15) +
this.calendar.get(16);
if (offset < 0) {
dateStrBuf.setCharAt(pos++, '-');
offset = -offset;
} else {
dateStrBuf.setCharAt(pos++, '+');
}
int rawOffsetInMins = offset / 60 / 1000;
int offsetInHrs = rawOffsetInMins / 60;
int offsetInMins = rawOffsetInMins % 60;
dateStrBuf.setCharAt(pos++, Character.forDigit(offsetInHrs / 10, 10));
dateStrBuf.setCharAt(pos++, Character.forDigit(offsetInHrs % 10, 10));
dateStrBuf.setCharAt(pos++, Character.forDigit(offsetInMins / 10, 10));
dateStrBuf.setCharAt(pos++, Character.forDigit(offsetInMins % 10, 10));
return dateStrBuf;
}
public Date parse(String text, ParsePosition pos) {
return parseDate(text.toCharArray(), pos, isLenient());
}
static boolean debug = false;
private static MailLogger logger = new MailLogger(MailDateFormat.class, "DEBUG", debug, System.out);
private static Date parseDate(char[] orig, ParsePosition pos, boolean lenient) {
try {
int day = -1;
int month = -1;
int year = -1;
int hours = 0;
int minutes = 0;
int seconds = 0;
int offset = 0;
MailDateParser p = new MailDateParser(orig, pos.getIndex());
p.skipUntilNumber();
day = p.parseNumber();
if (!p.skipIfChar('-'))
p.skipWhiteSpace();
month = p.parseMonth();
if (!p.skipIfChar('-'))
p.skipWhiteSpace();
year = p.parseNumber();
if (year < 50) {
year += 2000;
} else if (year < 100) {
year += 1900;
}
p.skipWhiteSpace();
hours = p.parseNumber();
p.skipChar(':');
minutes = p.parseNumber();
if (p.skipIfChar(':'))
seconds = p.parseNumber();
try {
p.skipWhiteSpace();
offset = p.parseTimeZone();
} catch (java.text.ParseException pe) {
if (logger.isLoggable(Level.FINE))
logger.log(Level.FINE, "No timezone? : '" + new String(orig) + "'", (Throwable)pe);
}
pos.setIndex(p.getIndex());
Date d = ourUTC(year, month, day, hours, minutes, seconds, offset, lenient);
return d;
} catch (Exception e) {
if (logger.isLoggable(Level.FINE))
logger.log(Level.FINE, "Bad date: '" + new String(orig) + "'", (Throwable)e);
pos.setIndex(1);
return null;
}
}
private static final Calendar cal = new GregorianCalendar(
TimeZone.getTimeZone("GMT"));
private static synchronized Date ourUTC(int year, int mon, int mday, int hour, int min, int sec, int tzoffset, boolean lenient) {
cal.clear();
cal.setLenient(lenient);
cal.set(1, year);
cal.set(2, mon);
cal.set(5, mday);
cal.set(11, hour);
cal.set(12, min);
cal.add(12, tzoffset);
cal.set(13, sec);
return cal.getTime();
}
public void setCalendar(Calendar newCalendar) {
throw new RuntimeException("Method setCalendar() shouldn't be called");
}
public void setNumberFormat(NumberFormat newNumberFormat) {
throw new RuntimeException("Method setNumberFormat() shouldn't be called");
}
}

View file

@ -0,0 +1,336 @@
package javax.mail.internet;
class MailDateParser {
int index = 0;
char[] orig = null;
public MailDateParser(char[] orig, int index) {
this.orig = orig;
this.index = index;
}
public void skipUntilNumber() throws java.text.ParseException {
try {
while (true) {
switch (this.orig[this.index]) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return;
}
this.index++;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new java.text.ParseException("No Number Found", this.index);
}
}
public void skipWhiteSpace() {
int len = this.orig.length;
while (this.index < len) {
switch (this.orig[this.index]) {
case '\t':
case '\n':
case '\r':
case ' ':
this.index++;
continue;
}
return;
}
}
public int peekChar() throws java.text.ParseException {
if (this.index < this.orig.length)
return this.orig[this.index];
throw new java.text.ParseException("No more characters", this.index);
}
public void skipChar(char c) throws java.text.ParseException {
if (this.index < this.orig.length) {
if (this.orig[this.index] == c) {
this.index++;
} else {
throw new java.text.ParseException("Wrong char", this.index);
}
} else {
throw new java.text.ParseException("No more characters", this.index);
}
}
public boolean skipIfChar(char c) throws java.text.ParseException {
if (this.index < this.orig.length) {
if (this.orig[this.index] == c) {
this.index++;
return true;
}
return false;
}
throw new java.text.ParseException("No more characters", this.index);
}
public int parseNumber() throws java.text.ParseException {
int length = this.orig.length;
boolean gotNum = false;
int result = 0;
while (this.index < length) {
switch (this.orig[this.index]) {
case '0':
result *= 10;
gotNum = true;
break;
case '1':
result = result * 10 + 1;
gotNum = true;
break;
case '2':
result = result * 10 + 2;
gotNum = true;
break;
case '3':
result = result * 10 + 3;
gotNum = true;
break;
case '4':
result = result * 10 + 4;
gotNum = true;
break;
case '5':
result = result * 10 + 5;
gotNum = true;
break;
case '6':
result = result * 10 + 6;
gotNum = true;
break;
case '7':
result = result * 10 + 7;
gotNum = true;
break;
case '8':
result = result * 10 + 8;
gotNum = true;
break;
case '9':
result = result * 10 + 9;
gotNum = true;
break;
default:
if (gotNum)
return result;
throw new java.text.ParseException("No Number found", this.index);
}
this.index++;
}
if (gotNum)
return result;
throw new java.text.ParseException("No Number found", this.index);
}
public int parseMonth() throws java.text.ParseException {
try {
char curr;
switch (this.orig[this.index++]) {
case 'J':
case 'j':
switch (this.orig[this.index++]) {
case 'A':
case 'a':
curr = this.orig[this.index++];
if (curr == 'N' || curr == 'n')
return 0;
break;
case 'U':
case 'u':
curr = this.orig[this.index++];
if (curr == 'N' || curr == 'n')
return 5;
if (curr == 'L' || curr == 'l')
return 6;
break;
}
break;
case 'F':
case 'f':
curr = this.orig[this.index++];
if (curr == 'E' || curr == 'e') {
curr = this.orig[this.index++];
if (curr == 'B' || curr == 'b')
return 1;
}
break;
case 'M':
case 'm':
curr = this.orig[this.index++];
if (curr == 'A' || curr == 'a') {
curr = this.orig[this.index++];
if (curr == 'R' || curr == 'r')
return 2;
if (curr == 'Y' || curr == 'y')
return 4;
}
break;
case 'A':
case 'a':
curr = this.orig[this.index++];
if (curr == 'P' || curr == 'p') {
curr = this.orig[this.index++];
if (curr == 'R' || curr == 'r')
return 3;
break;
}
if (curr == 'U' || curr == 'u') {
curr = this.orig[this.index++];
if (curr == 'G' || curr == 'g')
return 7;
}
break;
case 'S':
case 's':
curr = this.orig[this.index++];
if (curr == 'E' || curr == 'e') {
curr = this.orig[this.index++];
if (curr == 'P' || curr == 'p')
return 8;
}
break;
case 'O':
case 'o':
curr = this.orig[this.index++];
if (curr == 'C' || curr == 'c') {
curr = this.orig[this.index++];
if (curr == 'T' || curr == 't')
return 9;
}
break;
case 'N':
case 'n':
curr = this.orig[this.index++];
if (curr == 'O' || curr == 'o') {
curr = this.orig[this.index++];
if (curr == 'V' || curr == 'v')
return 10;
}
break;
case 'D':
case 'd':
curr = this.orig[this.index++];
if (curr == 'E' || curr == 'e') {
curr = this.orig[this.index++];
if (curr == 'C' || curr == 'c')
return 11;
}
break;
}
} catch (ArrayIndexOutOfBoundsException e) {}
throw new java.text.ParseException("Bad Month", this.index);
}
public int parseTimeZone() throws java.text.ParseException {
if (this.index >= this.orig.length)
throw new java.text.ParseException("No more characters", this.index);
char test = this.orig[this.index];
if (test == '+' || test == '-')
return parseNumericTimeZone();
return parseAlphaTimeZone();
}
public int parseNumericTimeZone() throws java.text.ParseException {
boolean switchSign = false;
char first = this.orig[this.index++];
if (first == '+') {
switchSign = true;
} else if (first != '-') {
throw new java.text.ParseException("Bad Numeric TimeZone", this.index);
}
int oindex = this.index;
int tz = parseNumber();
if (tz >= 2400)
throw new java.text.ParseException("Numeric TimeZone out of range", oindex);
int offset = tz / 100 * 60 + tz % 100;
if (switchSign)
return -offset;
return offset;
}
public int parseAlphaTimeZone() throws java.text.ParseException {
int result = 0;
boolean foundCommon = false;
try {
char curr;
switch (this.orig[this.index++]) {
case 'U':
case 'u':
curr = this.orig[this.index++];
if (curr == 'T' || curr == 't') {
result = 0;
break;
}
throw new java.text.ParseException("Bad Alpha TimeZone", this.index);
case 'G':
case 'g':
curr = this.orig[this.index++];
if (curr == 'M' || curr == 'm') {
curr = this.orig[this.index++];
if (curr == 'T' || curr == 't') {
result = 0;
break;
}
}
throw new java.text.ParseException("Bad Alpha TimeZone", this.index);
case 'E':
case 'e':
result = 300;
foundCommon = true;
break;
case 'C':
case 'c':
result = 360;
foundCommon = true;
break;
case 'M':
case 'm':
result = 420;
foundCommon = true;
break;
case 'P':
case 'p':
result = 480;
foundCommon = true;
break;
default:
throw new java.text.ParseException("Bad Alpha TimeZone", this.index);
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new java.text.ParseException("Bad Alpha TimeZone", this.index);
}
if (foundCommon) {
char curr = this.orig[this.index++];
if (curr == 'S' || curr == 's') {
curr = this.orig[this.index++];
if (curr != 'T' && curr != 't')
throw new java.text.ParseException("Bad Alpha TimeZone", this.index);
} else if (curr == 'D' || curr == 'd') {
curr = this.orig[this.index++];
if (curr == 'T' || curr != 't') {
result -= 60;
} else {
throw new java.text.ParseException("Bad Alpha TimeZone", this.index);
}
}
}
return result;
}
int getIndex() {
return this.index;
}
}

View file

@ -0,0 +1,739 @@
package javax.mail.internet;
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.FolderClosedIOException;
import com.sun.mail.util.LineOutputStream;
import com.sun.mail.util.MessageRemovedIOException;
import com.sun.mail.util.MimeUtil;
import com.sun.mail.util.PropUtil;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Vector;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.EncodingAware;
import javax.mail.FolderClosedException;
import javax.mail.MessageRemovedException;
import javax.mail.MessagingException;
import javax.mail.Multipart;
public class MimeBodyPart extends BodyPart implements MimePart {
private static final boolean setDefaultTextCharset = PropUtil.getBooleanSystemProperty("mail.mime.setdefaulttextcharset", true);
private static final boolean setContentTypeFileName = PropUtil.getBooleanSystemProperty("mail.mime.setcontenttypefilename", true);
private static final boolean encodeFileName = PropUtil.getBooleanSystemProperty("mail.mime.encodefilename", false);
private static final boolean decodeFileName = PropUtil.getBooleanSystemProperty("mail.mime.decodefilename", false);
private static final boolean ignoreMultipartEncoding = PropUtil.getBooleanSystemProperty("mail.mime.ignoremultipartencoding", true);
static final boolean cacheMultipart = PropUtil.getBooleanSystemProperty("mail.mime.cachemultipart", true);
protected DataHandler dh;
protected byte[] content;
protected InputStream contentStream;
protected InternetHeaders headers;
protected Object cachedContent;
public MimeBodyPart() {
this.headers = new InternetHeaders();
}
public MimeBodyPart(InputStream is) throws MessagingException {
if (!(is instanceof ByteArrayInputStream) && !(is instanceof BufferedInputStream) && !(is instanceof SharedInputStream))
is = new BufferedInputStream(is);
this.headers = new InternetHeaders(is);
if (is instanceof SharedInputStream) {
SharedInputStream sis = (SharedInputStream)is;
this.contentStream = sis.newStream(sis.getPosition(), -1L);
} else {
try {
this.content = ASCIIUtility.getBytes(is);
} catch (IOException ioex) {
throw new MessagingException("Error reading input stream", ioex);
}
}
}
public MimeBodyPart(InternetHeaders headers, byte[] content) throws MessagingException {
this.headers = headers;
this.content = content;
}
public int getSize() throws MessagingException {
if (this.content != null)
return this.content.length;
if (this.contentStream != null)
try {
int size = this.contentStream.available();
if (size > 0)
return size;
} catch (IOException e) {}
return -1;
}
public int getLineCount() throws MessagingException {
return -1;
}
public String getContentType() throws MessagingException {
String s = getHeader("Content-Type", null);
s = MimeUtil.cleanContentType(this, s);
if (s == null)
s = "text/plain";
return s;
}
public boolean isMimeType(String mimeType) throws MessagingException {
return isMimeType(this, mimeType);
}
public String getDisposition() throws MessagingException {
return getDisposition(this);
}
public void setDisposition(String disposition) throws MessagingException {
setDisposition(this, disposition);
}
public String getEncoding() throws MessagingException {
return getEncoding(this);
}
public String getContentID() throws MessagingException {
return getHeader("Content-Id", null);
}
public void setContentID(String cid) throws MessagingException {
if (cid == null) {
removeHeader("Content-ID");
} else {
setHeader("Content-ID", cid);
}
}
public String getContentMD5() throws MessagingException {
return getHeader("Content-MD5", null);
}
public void setContentMD5(String md5) throws MessagingException {
setHeader("Content-MD5", md5);
}
public String[] getContentLanguage() throws MessagingException {
return getContentLanguage(this);
}
public void setContentLanguage(String[] languages) throws MessagingException {
setContentLanguage(this, languages);
}
public String getDescription() throws MessagingException {
return getDescription(this);
}
public void setDescription(String description) throws MessagingException {
setDescription(description, null);
}
public void setDescription(String description, String charset) throws MessagingException {
setDescription(this, description, charset);
}
public String getFileName() throws MessagingException {
return getFileName(this);
}
public void setFileName(String filename) throws MessagingException {
setFileName(this, filename);
}
public InputStream getInputStream() throws IOException, MessagingException {
return getDataHandler().getInputStream();
}
protected InputStream getContentStream() throws MessagingException {
if (this.contentStream != null)
return ((SharedInputStream)this.contentStream).newStream(0L, -1L);
if (this.content != null)
return new ByteArrayInputStream(this.content);
throw new MessagingException("No MimeBodyPart content");
}
public InputStream getRawInputStream() throws MessagingException {
return getContentStream();
}
public DataHandler getDataHandler() throws MessagingException {
if (this.dh == null)
this.dh = new MimePartDataHandler(this);
return this.dh;
}
public Object getContent() throws IOException, MessagingException {
Object c;
if (this.cachedContent != null)
return this.cachedContent;
try {
c = getDataHandler().getContent();
} catch (FolderClosedIOException fex) {
throw new FolderClosedException(fex.getFolder(), fex.getMessage());
} catch (MessageRemovedIOException mex) {
throw new MessageRemovedException(mex.getMessage());
}
if (cacheMultipart && (c instanceof Multipart || c instanceof javax.mail.Message) && (this.content != null || this.contentStream != null)) {
this.cachedContent = c;
if (c instanceof MimeMultipart)
((MimeMultipart)c).parse();
}
return c;
}
public void setDataHandler(DataHandler dh) throws MessagingException {
this.dh = dh;
this.cachedContent = null;
invalidateContentHeaders(this);
}
public void setContent(Object o, String type) throws MessagingException {
if (o instanceof Multipart) {
setContent((Multipart)o);
} else {
setDataHandler(new DataHandler(o, type));
}
}
public void setText(String text) throws MessagingException {
setText(text, null);
}
public void setText(String text, String charset) throws MessagingException {
setText(this, text, charset, "plain");
}
public void setText(String text, String charset, String subtype) throws MessagingException {
setText(this, text, charset, subtype);
}
public void setContent(Multipart mp) throws MessagingException {
setDataHandler(new DataHandler(mp, mp.getContentType()));
mp.setParent(this);
}
public void attachFile(File file) throws IOException, MessagingException {
FileDataSource fds = new FileDataSource(file);
setDataHandler(new DataHandler((DataSource)fds));
setFileName(fds.getName());
setDisposition("attachment");
}
public void attachFile(String file) throws IOException, MessagingException {
File f = new File(file);
attachFile(f);
}
public void attachFile(File file, String contentType, String encoding) throws IOException, MessagingException {
EncodedFileDataSource encodedFileDataSource = new EncodedFileDataSource(file, contentType, encoding);
setDataHandler(new DataHandler((DataSource)encodedFileDataSource));
setFileName(encodedFileDataSource.getName());
setDisposition("attachment");
}
public void attachFile(String file, String contentType, String encoding) throws IOException, MessagingException {
attachFile(new File(file), contentType, encoding);
}
private static class EncodedFileDataSource extends FileDataSource implements EncodingAware {
private String contentType;
private String encoding;
public EncodedFileDataSource(File file, String contentType, String encoding) {
super(file);
this.contentType = contentType;
this.encoding = encoding;
}
public String getContentType() {
return (this.contentType != null) ? this.contentType : super.getContentType();
}
public String getEncoding() {
return this.encoding;
}
}
public void saveFile(File file) throws IOException, MessagingException {
OutputStream out = null;
InputStream in = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file));
in = getInputStream();
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {}
try {
if (out != null)
out.close();
} catch (IOException e) {}
}
}
public void saveFile(String file) throws IOException, MessagingException {
File f = new File(file);
saveFile(f);
}
public void writeTo(OutputStream os) throws IOException, MessagingException {
writeTo(this, os, null);
}
public String[] getHeader(String name) throws MessagingException {
return this.headers.getHeader(name);
}
public String getHeader(String name, String delimiter) throws MessagingException {
return this.headers.getHeader(name, delimiter);
}
public void setHeader(String name, String value) throws MessagingException {
this.headers.setHeader(name, value);
}
public void addHeader(String name, String value) throws MessagingException {
this.headers.addHeader(name, value);
}
public void removeHeader(String name) throws MessagingException {
this.headers.removeHeader(name);
}
public Enumeration getAllHeaders() throws MessagingException {
return this.headers.getAllHeaders();
}
public Enumeration getMatchingHeaders(String[] names) throws MessagingException {
return this.headers.getMatchingHeaders(names);
}
public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException {
return this.headers.getNonMatchingHeaders(names);
}
public void addHeaderLine(String line) throws MessagingException {
this.headers.addHeaderLine(line);
}
public Enumeration getAllHeaderLines() throws MessagingException {
return this.headers.getAllHeaderLines();
}
public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
return this.headers.getMatchingHeaderLines(names);
}
public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException {
return this.headers.getNonMatchingHeaderLines(names);
}
protected void updateHeaders() throws MessagingException {
updateHeaders(this);
if (this.cachedContent != null) {
this.dh = new DataHandler(this.cachedContent, getContentType());
this.cachedContent = null;
this.content = null;
if (this.contentStream != null)
try {
this.contentStream.close();
} catch (IOException e) {}
this.contentStream = null;
}
}
static boolean isMimeType(MimePart part, String mimeType) throws MessagingException {
try {
ContentType ct = new ContentType(part.getContentType());
return ct.match(mimeType);
} catch (ParseException ex) {
return part.getContentType().equalsIgnoreCase(mimeType);
}
}
static void setText(MimePart part, String text, String charset, String subtype) throws MessagingException {
if (charset == null)
if (MimeUtility.checkAscii(text) != 1) {
charset = MimeUtility.getDefaultMIMECharset();
} else {
charset = "us-ascii";
}
part.setContent(text, "text/" + subtype + "; charset=" +
MimeUtility.quote(charset, "()<>@,;:\\\"\t []/?="));
}
static String getDisposition(MimePart part) throws MessagingException {
String s = part.getHeader("Content-Disposition", null);
if (s == null)
return null;
ContentDisposition cd = new ContentDisposition(s);
return cd.getDisposition();
}
static void setDisposition(MimePart part, String disposition) throws MessagingException {
if (disposition == null) {
part.removeHeader("Content-Disposition");
} else {
String s = part.getHeader("Content-Disposition", null);
if (s != null) {
ContentDisposition cd = new ContentDisposition(s);
cd.setDisposition(disposition);
disposition = cd.toString();
}
part.setHeader("Content-Disposition", disposition);
}
}
static String getDescription(MimePart part) throws MessagingException {
String rawvalue = part.getHeader("Content-Description", null);
if (rawvalue == null)
return null;
try {
return MimeUtility.decodeText(MimeUtility.unfold(rawvalue));
} catch (UnsupportedEncodingException ex) {
return rawvalue;
}
}
static void setDescription(MimePart part, String description, String charset) throws MessagingException {
if (description == null) {
part.removeHeader("Content-Description");
return;
}
try {
part.setHeader("Content-Description", MimeUtility.fold(21,
MimeUtility.encodeText(description, charset, null)));
} catch (UnsupportedEncodingException uex) {
throw new MessagingException("Encoding error", uex);
}
}
static String getFileName(MimePart part) throws MessagingException {
String filename = null;
String s = part.getHeader("Content-Disposition", null);
if (s != null) {
ContentDisposition cd = new ContentDisposition(s);
filename = cd.getParameter("filename");
}
if (filename == null) {
s = part.getHeader("Content-Type", null);
s = MimeUtil.cleanContentType(part, s);
if (s != null)
try {
ContentType ct = new ContentType(s);
filename = ct.getParameter("name");
} catch (ParseException e) {}
}
if (decodeFileName && filename != null)
try {
filename = MimeUtility.decodeText(filename);
} catch (UnsupportedEncodingException ex) {
throw new MessagingException("Can't decode filename", ex);
}
return filename;
}
static void setFileName(MimePart part, String name) throws MessagingException {
if (encodeFileName && name != null)
try {
name = MimeUtility.encodeText(name);
} catch (UnsupportedEncodingException ex) {
throw new MessagingException("Can't encode filename", ex);
}
String s = part.getHeader("Content-Disposition", null);
ContentDisposition cd = new ContentDisposition((s == null) ? "attachment" : s);
String charset = MimeUtility.getDefaultMIMECharset();
ParameterList p = cd.getParameterList();
if (p == null) {
p = new ParameterList();
cd.setParameterList(p);
}
p.set("filename", name, charset);
part.setHeader("Content-Disposition", cd.toString());
if (setContentTypeFileName) {
s = part.getHeader("Content-Type", null);
s = MimeUtil.cleanContentType(part, s);
if (s != null)
try {
ContentType cType = new ContentType(s);
p = cType.getParameterList();
if (p == null) {
p = new ParameterList();
cType.setParameterList(p);
}
p.set("name", name, charset);
part.setHeader("Content-Type", cType.toString());
} catch (ParseException e) {}
}
}
static String[] getContentLanguage(MimePart part) throws MessagingException {
String s = part.getHeader("Content-Language", null);
if (s == null)
return null;
HeaderTokenizer h = new HeaderTokenizer(s, "()<>@,;:\\\"\t []/?=");
Vector<String> v = new Vector();
while (true) {
HeaderTokenizer.Token tk = h.next();
int tkType = tk.getType();
if (tkType == -4)
break;
if (tkType == -1)
v.addElement(tk.getValue());
}
if (v.size() == 0)
return null;
String[] language = new String[v.size()];
v.copyInto(language);
return language;
}
static void setContentLanguage(MimePart part, String[] languages) throws MessagingException {
StringBuffer sb = new StringBuffer(languages[0]);
int len = "Content-Language".length() + 2 + languages[0].length();
for (int i = 1; i < languages.length; i++) {
sb.append(',');
len++;
if (len > 76) {
sb.append("\r\n\t");
len = 8;
}
sb.append(languages[i]);
len += languages[i].length();
}
part.setHeader("Content-Language", sb.toString());
}
static String getEncoding(MimePart part) throws MessagingException {
String s = part.getHeader("Content-Transfer-Encoding", null);
if (s == null)
return null;
s = s.trim();
if (s.equalsIgnoreCase("7bit") || s.equalsIgnoreCase("8bit") ||
s.equalsIgnoreCase("quoted-printable") ||
s.equalsIgnoreCase("binary") ||
s.equalsIgnoreCase("base64"))
return s;
HeaderTokenizer h = new HeaderTokenizer(s, "()<>@,;:\\\"\t []/?=");
while (true) {
HeaderTokenizer.Token tk = h.next();
int tkType = tk.getType();
if (tkType == -4)
break;
if (tkType == -1)
return tk.getValue();
}
return s;
}
static void setEncoding(MimePart part, String encoding) throws MessagingException {
part.setHeader("Content-Transfer-Encoding", encoding);
}
static String restrictEncoding(MimePart part, String encoding) throws MessagingException {
if (!ignoreMultipartEncoding || encoding == null)
return encoding;
if (encoding.equalsIgnoreCase("7bit") ||
encoding.equalsIgnoreCase("8bit") ||
encoding.equalsIgnoreCase("binary"))
return encoding;
String type = part.getContentType();
if (type == null)
return encoding;
try {
ContentType cType = new ContentType(type);
if (cType.match("multipart/*"))
return null;
if (cType.match("message/*") &&
!PropUtil.getBooleanSystemProperty("mail.mime.allowencodedmessages", false))
return null;
} catch (ParseException e) {}
return encoding;
}
static void updateHeaders(MimePart part) throws MessagingException {
DataHandler dh = part.getDataHandler();
if (dh == null)
return;
try {
String type = dh.getContentType();
boolean composite = false;
boolean needCTHeader = (part.getHeader("Content-Type") == null);
ContentType cType = new ContentType(type);
if (cType.match("multipart/*")) {
Object o;
composite = true;
if (part instanceof MimeBodyPart) {
MimeBodyPart mbp = (MimeBodyPart)part;
o = (mbp.cachedContent != null) ? mbp.cachedContent : dh.getContent();
} else if (part instanceof MimeMessage) {
MimeMessage msg = (MimeMessage)part;
o = (msg.cachedContent != null) ? msg.cachedContent : dh.getContent();
} else {
o = dh.getContent();
}
if (o instanceof MimeMultipart) {
((MimeMultipart)o).updateHeaders();
} else {
throw new MessagingException("MIME part of type \"" + type + "\" contains object of type " +
o.getClass().getName() + " instead of MimeMultipart");
}
} else if (cType.match("message/rfc822")) {
composite = true;
}
if (dh instanceof MimePartDataHandler) {
MimePartDataHandler mdh = (MimePartDataHandler)dh;
MimePart mpart = mdh.getPart();
if (mpart != part) {
if (needCTHeader)
part.setHeader("Content-Type", mpart.getContentType());
String enc = mpart.getEncoding();
if (enc != null) {
setEncoding(part, enc);
return;
}
} else {
return;
}
}
if (!composite) {
if (part.getHeader("Content-Transfer-Encoding") == null)
setEncoding(part, MimeUtility.getEncoding(dh));
if (needCTHeader && setDefaultTextCharset &&
cType.match("text/*") &&
cType.getParameter("charset") == null) {
String charset;
String enc = part.getEncoding();
if (enc != null && enc.equalsIgnoreCase("7bit")) {
charset = "us-ascii";
} else {
charset = MimeUtility.getDefaultMIMECharset();
}
cType.setParameter("charset", charset);
type = cType.toString();
}
}
if (needCTHeader) {
if (setContentTypeFileName) {
String s = part.getHeader("Content-Disposition", null);
if (s != null) {
ContentDisposition cd = new ContentDisposition(s);
String filename = cd.getParameter("filename");
if (filename != null) {
ParameterList p = cType.getParameterList();
if (p == null) {
p = new ParameterList();
cType.setParameterList(p);
}
p.set("name", filename,
MimeUtility.getDefaultMIMECharset());
type = cType.toString();
}
}
}
part.setHeader("Content-Type", type);
}
} catch (IOException ex) {
throw new MessagingException("IOException updating headers", ex);
}
}
static void invalidateContentHeaders(MimePart part) throws MessagingException {
part.removeHeader("Content-Type");
part.removeHeader("Content-Transfer-Encoding");
}
static void writeTo(MimePart part, OutputStream os, String[] ignoreList) throws IOException, MessagingException {
LineOutputStream los = null;
if (os instanceof LineOutputStream) {
los = (LineOutputStream)os;
} else {
los = new LineOutputStream(os);
}
Enumeration<String> hdrLines = part.getNonMatchingHeaderLines(ignoreList);
while (hdrLines.hasMoreElements())
los.writeln(hdrLines.nextElement());
los.writeln();
InputStream is = null;
byte[] buf = null;
try {
DataHandler dh = part.getDataHandler();
if (dh instanceof MimePartDataHandler) {
MimePartDataHandler mpdh = (MimePartDataHandler)dh;
MimePart mpart = mpdh.getPart();
if (mpart.getEncoding() != null)
is = mpdh.getContentStream();
}
if (is != null) {
buf = new byte[8192];
int len;
while ((len = is.read(buf)) > 0)
os.write(buf, 0, len);
} else {
os = MimeUtility.encode(os,
restrictEncoding(part, part.getEncoding()));
part.getDataHandler().writeTo(os);
}
} finally {
if (is != null)
is.close();
buf = null;
}
os.flush();
}
static class MimePartDataHandler extends DataHandler {
MimePart part;
public MimePartDataHandler(MimePart part) {
super(new MimePartDataSource(part));
this.part = part;
}
InputStream getContentStream() throws MessagingException {
InputStream is = null;
if (this.part instanceof MimeBodyPart) {
MimeBodyPart mbp = (MimeBodyPart)this.part;
is = mbp.getContentStream();
} else if (this.part instanceof MimeMessage) {
MimeMessage msg = (MimeMessage)this.part;
is = msg.getContentStream();
}
return is;
}
MimePart getPart() {
return this.part;
}
}
}

View file

@ -0,0 +1,798 @@
package javax.mail.internet;
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.FolderClosedIOException;
import com.sun.mail.util.LineOutputStream;
import com.sun.mail.util.MessageRemovedIOException;
import com.sun.mail.util.MimeUtil;
import com.sun.mail.util.PropUtil;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import javax.activation.DataHandler;
import javax.mail.Address;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.FolderClosedException;
import javax.mail.Message;
import javax.mail.MessageRemovedException;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.util.SharedByteArrayInputStream;
public class MimeMessage extends Message implements MimePart {
protected DataHandler dh;
protected byte[] content;
protected InputStream contentStream;
protected InternetHeaders headers;
protected Flags flags;
protected boolean modified;
protected boolean saved;
protected Object cachedContent;
private static final MailDateFormat mailDateFormat = new MailDateFormat();
private boolean strict;
public MimeMessage(Session session) {
super(session);
this.modified = false;
this.saved = false;
this.strict = true;
this.modified = true;
this.headers = new InternetHeaders();
this.flags = new Flags();
initStrict();
}
public MimeMessage(Session session, InputStream is) throws MessagingException {
super(session);
this.modified = false;
this.saved = false;
this.strict = true;
this.flags = new Flags();
initStrict();
parse(is);
this.saved = true;
}
public MimeMessage(MimeMessage source) throws MessagingException {
super(source.session);
ByteArrayOutputStream bos;
this.modified = false;
this.saved = false;
this.strict = true;
this.flags = source.getFlags();
if (this.flags == null)
this.flags = new Flags();
int size = source.getSize();
if (size > 0) {
bos = new ByteArrayOutputStream(size);
} else {
bos = new ByteArrayOutputStream();
}
try {
this.strict = source.strict;
source.writeTo(bos);
bos.close();
SharedByteArrayInputStream bis = new SharedByteArrayInputStream(
bos.toByteArray());
parse(bis);
bis.close();
this.saved = true;
} catch (IOException ex) {
throw new MessagingException("IOException while copying message", ex);
}
}
protected MimeMessage(Folder folder, int msgnum) {
super(folder, msgnum);
this.modified = false;
this.saved = false;
this.strict = true;
this.flags = new Flags();
this.saved = true;
initStrict();
}
protected MimeMessage(Folder folder, InputStream is, int msgnum) throws MessagingException {
this(folder, msgnum);
initStrict();
parse(is);
}
protected MimeMessage(Folder folder, InternetHeaders headers, byte[] content, int msgnum) throws MessagingException {
this(folder, msgnum);
this.headers = headers;
this.content = content;
initStrict();
}
private void initStrict() {
if (this.session != null)
this.strict = PropUtil.getBooleanSessionProperty(this.session, "mail.mime.address.strict", true);
}
protected void parse(InputStream is) throws MessagingException {
if (!(is instanceof java.io.ByteArrayInputStream) && !(is instanceof BufferedInputStream) && !(is instanceof SharedInputStream))
is = new BufferedInputStream(is);
this.headers = createInternetHeaders(is);
if (is instanceof SharedInputStream) {
SharedInputStream sis = (SharedInputStream)is;
this.contentStream = sis.newStream(sis.getPosition(), -1L);
} else {
try {
this.content = ASCIIUtility.getBytes(is);
} catch (IOException ioex) {
throw new MessagingException("IOException", ioex);
}
}
this.modified = false;
}
public Address[] getFrom() throws MessagingException {
Address[] a = getAddressHeader("From");
if (a == null)
a = getAddressHeader("Sender");
return a;
}
public void setFrom(Address address) throws MessagingException {
if (address == null) {
removeHeader("From");
} else {
setHeader("From", address.toString());
}
}
public void setFrom(String address) throws MessagingException {
if (address == null) {
removeHeader("From");
} else {
setAddressHeader("From", InternetAddress.parse(address));
}
}
public void setFrom() throws MessagingException {
InternetAddress me = null;
try {
me = InternetAddress._getLocalAddress(this.session);
} catch (Exception ex) {
throw new MessagingException("No From address", ex);
}
if (me != null) {
setFrom(me);
} else {
throw new MessagingException("No From address");
}
}
public void addFrom(Address[] addresses) throws MessagingException {
addAddressHeader("From", addresses);
}
public Address getSender() throws MessagingException {
Address[] a = getAddressHeader("Sender");
if (a == null || a.length == 0)
return null;
return a[0];
}
public void setSender(Address address) throws MessagingException {
if (address == null) {
removeHeader("Sender");
} else {
setHeader("Sender", address.toString());
}
}
public static class RecipientType extends Message.RecipientType {
private static final long serialVersionUID = -5468290701714395543L;
public static final RecipientType NEWSGROUPS = new RecipientType("Newsgroups");
protected RecipientType(String type) {
super(type);
}
protected Object readResolve() throws ObjectStreamException {
if (this.type.equals("Newsgroups"))
return NEWSGROUPS;
return super.readResolve();
}
}
public Address[] getRecipients(Message.RecipientType type) throws MessagingException {
if (type == RecipientType.NEWSGROUPS) {
String s = getHeader("Newsgroups", ",");
return (s == null) ? null : NewsAddress.parse(s);
}
return getAddressHeader(getHeaderName(type));
}
public Address[] getAllRecipients() throws MessagingException {
Address[] all = super.getAllRecipients();
Address[] ng = getRecipients(RecipientType.NEWSGROUPS);
if (ng == null)
return all;
if (all == null)
return ng;
Address[] addresses = new Address[all.length + ng.length];
System.arraycopy(all, 0, addresses, 0, all.length);
System.arraycopy(ng, 0, addresses, all.length, ng.length);
return addresses;
}
public void setRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException {
if (type == RecipientType.NEWSGROUPS) {
if (addresses == null || addresses.length == 0) {
removeHeader("Newsgroups");
} else {
setHeader("Newsgroups", NewsAddress.toString(addresses));
}
} else {
setAddressHeader(getHeaderName(type), addresses);
}
}
public void setRecipients(Message.RecipientType type, String addresses) throws MessagingException {
if (type == RecipientType.NEWSGROUPS) {
if (addresses == null || addresses.length() == 0) {
removeHeader("Newsgroups");
} else {
setHeader("Newsgroups", addresses);
}
} else {
setAddressHeader(getHeaderName(type), (addresses == null) ? null :
InternetAddress.parse(addresses));
}
}
public void addRecipients(Message.RecipientType type, Address[] addresses) throws MessagingException {
if (type == RecipientType.NEWSGROUPS) {
String s = NewsAddress.toString(addresses);
if (s != null)
addHeader("Newsgroups", s);
} else {
addAddressHeader(getHeaderName(type), addresses);
}
}
public void addRecipients(Message.RecipientType type, String addresses) throws MessagingException {
if (type == RecipientType.NEWSGROUPS) {
if (addresses != null && addresses.length() != 0)
addHeader("Newsgroups", addresses);
} else {
addAddressHeader(getHeaderName(type), InternetAddress.parse(addresses));
}
}
public Address[] getReplyTo() throws MessagingException {
Address[] a = getAddressHeader("Reply-To");
if (a == null || a.length == 0)
a = getFrom();
return a;
}
public void setReplyTo(Address[] addresses) throws MessagingException {
setAddressHeader("Reply-To", addresses);
}
private Address[] getAddressHeader(String name) throws MessagingException {
String s = getHeader(name, ",");
return (s == null) ? null : InternetAddress.parseHeader(s, this.strict);
}
private void setAddressHeader(String name, Address[] addresses) throws MessagingException {
String s = InternetAddress.toString(addresses, name.length() + 2);
if (s == null) {
removeHeader(name);
} else {
setHeader(name, s);
}
}
private void addAddressHeader(String name, Address[] addresses) throws MessagingException {
Address[] anew;
if (addresses == null || addresses.length == 0)
return;
Address[] a = getAddressHeader(name);
if (a == null || a.length == 0) {
anew = addresses;
} else {
anew = new Address[a.length + addresses.length];
System.arraycopy(a, 0, anew, 0, a.length);
System.arraycopy(addresses, 0, anew, a.length, addresses.length);
}
String s = InternetAddress.toString(anew, name.length() + 2);
if (s == null)
return;
setHeader(name, s);
}
public String getSubject() throws MessagingException {
String rawvalue = getHeader("Subject", null);
if (rawvalue == null)
return null;
try {
return MimeUtility.decodeText(MimeUtility.unfold(rawvalue));
} catch (UnsupportedEncodingException ex) {
return rawvalue;
}
}
public void setSubject(String subject) throws MessagingException {
setSubject(subject, null);
}
public void setSubject(String subject, String charset) throws MessagingException {
if (subject == null) {
removeHeader("Subject");
} else {
try {
setHeader("Subject", MimeUtility.fold(9,
MimeUtility.encodeText(subject, charset, null)));
} catch (UnsupportedEncodingException uex) {
throw new MessagingException("Encoding error", uex);
}
}
}
public Date getSentDate() throws MessagingException {
String s = getHeader("Date", null);
if (s != null)
try {
synchronized (mailDateFormat) {
return mailDateFormat.parse(s);
}
} catch (java.text.ParseException pex) {
return null;
}
return null;
}
public void setSentDate(Date d) throws MessagingException {
if (d == null) {
removeHeader("Date");
} else {
synchronized (mailDateFormat) {
setHeader("Date", mailDateFormat.format(d));
}
}
}
public Date getReceivedDate() throws MessagingException {
return null;
}
public int getSize() throws MessagingException {
if (this.content != null)
return this.content.length;
if (this.contentStream != null)
try {
int size = this.contentStream.available();
if (size > 0)
return size;
} catch (IOException e) {}
return -1;
}
public int getLineCount() throws MessagingException {
return -1;
}
public String getContentType() throws MessagingException {
String s = getHeader("Content-Type", null);
s = MimeUtil.cleanContentType(this, s);
if (s == null)
return "text/plain";
return s;
}
public boolean isMimeType(String mimeType) throws MessagingException {
return MimeBodyPart.isMimeType(this, mimeType);
}
public String getDisposition() throws MessagingException {
return MimeBodyPart.getDisposition(this);
}
public void setDisposition(String disposition) throws MessagingException {
MimeBodyPart.setDisposition(this, disposition);
}
public String getEncoding() throws MessagingException {
return MimeBodyPart.getEncoding(this);
}
public String getContentID() throws MessagingException {
return getHeader("Content-Id", null);
}
public void setContentID(String cid) throws MessagingException {
if (cid == null) {
removeHeader("Content-ID");
} else {
setHeader("Content-ID", cid);
}
}
public String getContentMD5() throws MessagingException {
return getHeader("Content-MD5", null);
}
public void setContentMD5(String md5) throws MessagingException {
setHeader("Content-MD5", md5);
}
public String getDescription() throws MessagingException {
return MimeBodyPart.getDescription(this);
}
public void setDescription(String description) throws MessagingException {
setDescription(description, null);
}
public void setDescription(String description, String charset) throws MessagingException {
MimeBodyPart.setDescription(this, description, charset);
}
public String[] getContentLanguage() throws MessagingException {
return MimeBodyPart.getContentLanguage(this);
}
public void setContentLanguage(String[] languages) throws MessagingException {
MimeBodyPart.setContentLanguage(this, languages);
}
public String getMessageID() throws MessagingException {
return getHeader("Message-ID", null);
}
public String getFileName() throws MessagingException {
return MimeBodyPart.getFileName(this);
}
public void setFileName(String filename) throws MessagingException {
MimeBodyPart.setFileName(this, filename);
}
private String getHeaderName(Message.RecipientType type) throws MessagingException {
String headerName;
if (type == Message.RecipientType.TO) {
headerName = "To";
} else if (type == Message.RecipientType.CC) {
headerName = "Cc";
} else if (type == Message.RecipientType.BCC) {
headerName = "Bcc";
} else if (type == RecipientType.NEWSGROUPS) {
headerName = "Newsgroups";
} else {
throw new MessagingException("Invalid Recipient Type");
}
return headerName;
}
public InputStream getInputStream() throws IOException, MessagingException {
return getDataHandler().getInputStream();
}
protected InputStream getContentStream() throws MessagingException {
if (this.contentStream != null)
return ((SharedInputStream)this.contentStream).newStream(0L, -1L);
if (this.content != null)
return new SharedByteArrayInputStream(this.content);
throw new MessagingException("No MimeMessage content");
}
public InputStream getRawInputStream() throws MessagingException {
return getContentStream();
}
public synchronized DataHandler getDataHandler() throws MessagingException {
if (this.dh == null)
this.dh = new MimeBodyPart.MimePartDataHandler(this);
return this.dh;
}
public Object getContent() throws IOException, MessagingException {
Object c;
if (this.cachedContent != null)
return this.cachedContent;
try {
c = getDataHandler().getContent();
} catch (FolderClosedIOException fex) {
throw new FolderClosedException(fex.getFolder(), fex.getMessage());
} catch (MessageRemovedIOException mex) {
throw new MessageRemovedException(mex.getMessage());
}
if (MimeBodyPart.cacheMultipart && (c instanceof Multipart || c instanceof Message) && (this.content != null || this.contentStream != null)) {
this.cachedContent = c;
if (c instanceof MimeMultipart)
((MimeMultipart)c).parse();
}
return c;
}
public synchronized void setDataHandler(DataHandler dh) throws MessagingException {
this.dh = dh;
this.cachedContent = null;
MimeBodyPart.invalidateContentHeaders(this);
}
public void setContent(Object o, String type) throws MessagingException {
if (o instanceof Multipart) {
setContent((Multipart)o);
} else {
setDataHandler(new DataHandler(o, type));
}
}
public void setText(String text) throws MessagingException {
setText(text, null);
}
public void setText(String text, String charset) throws MessagingException {
MimeBodyPart.setText(this, text, charset, "plain");
}
public void setText(String text, String charset, String subtype) throws MessagingException {
MimeBodyPart.setText(this, text, charset, subtype);
}
public void setContent(Multipart mp) throws MessagingException {
setDataHandler(new DataHandler(mp, mp.getContentType()));
mp.setParent(this);
}
public Message reply(boolean replyToAll) throws MessagingException {
return reply(replyToAll, true);
}
public Message reply(boolean replyToAll, boolean setAnswered) throws MessagingException {
MimeMessage reply = createMimeMessage(this.session);
String subject = getHeader("Subject", null);
if (subject != null) {
if (!subject.regionMatches(true, 0, "Re: ", 0, 4))
subject = "Re: " + subject;
reply.setHeader("Subject", subject);
}
Address[] a = getReplyTo();
reply.setRecipients(Message.RecipientType.TO, a);
if (replyToAll) {
Vector<InternetAddress> v = new Vector();
InternetAddress me = InternetAddress.getLocalAddress(this.session);
if (me != null)
v.addElement(me);
String alternates = null;
if (this.session != null)
alternates = this.session.getProperty("mail.alternates");
if (alternates != null)
eliminateDuplicates(v,
InternetAddress.parse(alternates, false));
String replyallccStr = null;
boolean replyallcc = false;
if (this.session != null)
replyallcc = PropUtil.getBooleanSessionProperty(this.session, "mail.replyallcc", false);
eliminateDuplicates(v, a);
a = getRecipients(Message.RecipientType.TO);
a = eliminateDuplicates(v, a);
if (a != null && a.length > 0)
if (replyallcc) {
reply.addRecipients(Message.RecipientType.CC, a);
} else {
reply.addRecipients(Message.RecipientType.TO, a);
}
a = getRecipients(Message.RecipientType.CC);
a = eliminateDuplicates(v, a);
if (a != null && a.length > 0)
reply.addRecipients(Message.RecipientType.CC, a);
a = getRecipients(RecipientType.NEWSGROUPS);
if (a != null && a.length > 0)
reply.setRecipients(RecipientType.NEWSGROUPS, a);
}
String msgId = getHeader("Message-Id", null);
if (msgId != null)
reply.setHeader("In-Reply-To", msgId);
String refs = getHeader("References", " ");
if (refs == null)
refs = getHeader("In-Reply-To", " ");
if (msgId != null)
if (refs != null) {
refs = MimeUtility.unfold(refs) + " " + msgId;
} else {
refs = msgId;
}
if (refs != null)
reply.setHeader("References", MimeUtility.fold(12, refs));
if (setAnswered)
try {
setFlags(answeredFlag, true);
} catch (MessagingException e) {}
return reply;
}
private static final Flags answeredFlag = new Flags(Flags.Flag.ANSWERED);
private Address[] eliminateDuplicates(Vector v, Address[] addrs) {
if (addrs == null)
return null;
int gone = 0;
for (int i = 0; i < addrs.length; i++) {
boolean found = false;
for (int j = 0; j < v.size(); j++) {
if (v.elementAt(j).equals(addrs[i])) {
found = true;
gone++;
addrs[i] = null;
break;
}
}
if (!found)
v.addElement(addrs[i]);
}
if (gone != 0) {
Address[] a;
if (addrs instanceof InternetAddress[]) {
a = new InternetAddress[addrs.length - gone];
} else {
a = new Address[addrs.length - gone];
}
for (int k = 0, j = 0; k < addrs.length; k++) {
if (addrs[k] != null)
a[j++] = addrs[k];
}
addrs = a;
}
return addrs;
}
public void writeTo(OutputStream os) throws IOException, MessagingException {
writeTo(os, null);
}
public void writeTo(OutputStream os, String[] ignoreList) throws IOException, MessagingException {
if (!this.saved)
saveChanges();
if (this.modified) {
MimeBodyPart.writeTo(this, os, ignoreList);
return;
}
Enumeration<String> hdrLines = getNonMatchingHeaderLines(ignoreList);
LineOutputStream los = new LineOutputStream(os);
while (hdrLines.hasMoreElements())
los.writeln(hdrLines.nextElement());
los.writeln();
if (this.content == null) {
InputStream is = null;
byte[] buf = new byte[8192];
try {
is = getContentStream();
int len;
while ((len = is.read(buf)) > 0)
os.write(buf, 0, len);
} finally {
if (is != null)
is.close();
buf = null;
}
} else {
os.write(this.content);
}
os.flush();
}
public String[] getHeader(String name) throws MessagingException {
return this.headers.getHeader(name);
}
public String getHeader(String name, String delimiter) throws MessagingException {
return this.headers.getHeader(name, delimiter);
}
public void setHeader(String name, String value) throws MessagingException {
this.headers.setHeader(name, value);
}
public void addHeader(String name, String value) throws MessagingException {
this.headers.addHeader(name, value);
}
public void removeHeader(String name) throws MessagingException {
this.headers.removeHeader(name);
}
public Enumeration getAllHeaders() throws MessagingException {
return this.headers.getAllHeaders();
}
public Enumeration getMatchingHeaders(String[] names) throws MessagingException {
return this.headers.getMatchingHeaders(names);
}
public Enumeration getNonMatchingHeaders(String[] names) throws MessagingException {
return this.headers.getNonMatchingHeaders(names);
}
public void addHeaderLine(String line) throws MessagingException {
this.headers.addHeaderLine(line);
}
public Enumeration getAllHeaderLines() throws MessagingException {
return this.headers.getAllHeaderLines();
}
public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
return this.headers.getMatchingHeaderLines(names);
}
public Enumeration getNonMatchingHeaderLines(String[] names) throws MessagingException {
return this.headers.getNonMatchingHeaderLines(names);
}
public synchronized Flags getFlags() throws MessagingException {
return (Flags)this.flags.clone();
}
public synchronized boolean isSet(Flags.Flag flag) throws MessagingException {
return this.flags.contains(flag);
}
public synchronized void setFlags(Flags flag, boolean set) throws MessagingException {
if (set) {
this.flags.add(flag);
} else {
this.flags.remove(flag);
}
}
public void saveChanges() throws MessagingException {
this.modified = true;
this.saved = true;
updateHeaders();
}
protected void updateMessageID() throws MessagingException {
setHeader("Message-ID", "<" +
UniqueValue.getUniqueMessageIDValue(this.session) + ">");
}
protected synchronized void updateHeaders() throws MessagingException {
MimeBodyPart.updateHeaders(this);
setHeader("MIME-Version", "1.0");
updateMessageID();
if (this.cachedContent != null) {
this.dh = new DataHandler(this.cachedContent, getContentType());
this.cachedContent = null;
this.content = null;
if (this.contentStream != null)
try {
this.contentStream.close();
} catch (IOException e) {}
this.contentStream = null;
}
}
protected InternetHeaders createInternetHeaders(InputStream is) throws MessagingException {
return new InternetHeaders(is);
}
protected MimeMessage createMimeMessage(Session session) throws MessagingException {
return new MimeMessage(session);
}
}

View file

@ -0,0 +1,457 @@
package javax.mail.internet;
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.LineInputStream;
import com.sun.mail.util.LineOutputStream;
import com.sun.mail.util.PropUtil;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.activation.DataSource;
import javax.mail.BodyPart;
import javax.mail.MessageAware;
import javax.mail.MessageContext;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.MultipartDataSource;
public class MimeMultipart extends Multipart {
protected DataSource ds = null;
protected boolean parsed = true;
protected boolean complete = true;
protected String preamble = null;
protected boolean ignoreMissingEndBoundary = true;
protected boolean ignoreMissingBoundaryParameter = true;
protected boolean ignoreExistingBoundaryParameter = false;
protected boolean allowEmpty = false;
public MimeMultipart() {
this("mixed");
}
public MimeMultipart(String subtype) {
String boundary = UniqueValue.getUniqueBoundaryValue();
ContentType cType = new ContentType("multipart", subtype, null);
cType.setParameter("boundary", boundary);
this.contentType = cType.toString();
initializeProperties();
}
public MimeMultipart(BodyPart... parts) throws MessagingException {
this();
for (BodyPart bp : parts)
super.addBodyPart(bp);
}
public MimeMultipart(String subtype, BodyPart... parts) throws MessagingException {
this(subtype);
for (BodyPart bp : parts)
super.addBodyPart(bp);
}
public MimeMultipart(DataSource ds) throws MessagingException {
if (ds instanceof MessageAware) {
MessageContext mc = ((MessageAware)ds).getMessageContext();
setParent(mc.getPart());
}
if (ds instanceof MultipartDataSource) {
setMultipartDataSource((MultipartDataSource)ds);
return;
}
this.parsed = false;
this.ds = ds;
this.contentType = ds.getContentType();
}
protected void initializeProperties() {
this.ignoreMissingEndBoundary = PropUtil.getBooleanSystemProperty("mail.mime.multipart.ignoremissingendboundary", true);
this.ignoreMissingBoundaryParameter = PropUtil.getBooleanSystemProperty("mail.mime.multipart.ignoremissingboundaryparameter", true);
this.ignoreExistingBoundaryParameter = PropUtil.getBooleanSystemProperty("mail.mime.multipart.ignoreexistingboundaryparameter", false);
this.allowEmpty = PropUtil.getBooleanSystemProperty("mail.mime.multipart.allowempty", false);
}
public synchronized void setSubType(String subtype) throws MessagingException {
ContentType cType = new ContentType(this.contentType);
cType.setSubType(subtype);
this.contentType = cType.toString();
}
public synchronized int getCount() throws MessagingException {
parse();
return super.getCount();
}
public synchronized BodyPart getBodyPart(int index) throws MessagingException {
parse();
return super.getBodyPart(index);
}
public synchronized BodyPart getBodyPart(String CID) throws MessagingException {
parse();
int count = getCount();
for (int i = 0; i < count; i++) {
MimeBodyPart part = (MimeBodyPart)getBodyPart(i);
String s = part.getContentID();
if (s != null && s.equals(CID))
return part;
}
return null;
}
public boolean removeBodyPart(BodyPart part) throws MessagingException {
parse();
return super.removeBodyPart(part);
}
public void removeBodyPart(int index) throws MessagingException {
parse();
super.removeBodyPart(index);
}
public synchronized void addBodyPart(BodyPart part) throws MessagingException {
parse();
super.addBodyPart(part);
}
public synchronized void addBodyPart(BodyPart part, int index) throws MessagingException {
parse();
super.addBodyPart(part, index);
}
public synchronized boolean isComplete() throws MessagingException {
parse();
return this.complete;
}
public synchronized String getPreamble() throws MessagingException {
parse();
return this.preamble;
}
public synchronized void setPreamble(String preamble) throws MessagingException {
this.preamble = preamble;
}
protected synchronized void updateHeaders() throws MessagingException {
parse();
for (int i = 0; i < this.parts.size(); i++)
this.parts.elementAt(i).updateHeaders();
}
public synchronized void writeTo(OutputStream os) throws IOException, MessagingException {
parse();
String boundary = "--" + new ContentType(this.contentType)
.getParameter("boundary");
LineOutputStream los = new LineOutputStream(os);
if (this.preamble != null) {
byte[] pb = ASCIIUtility.getBytes(this.preamble);
los.write(pb);
if (pb.length > 0 && pb[pb.length - 1] != 13 && pb[pb.length - 1] != 10)
los.writeln();
}
if (this.parts.size() == 0) {
if (this.allowEmpty) {
los.writeln(boundary);
los.writeln();
} else {
throw new MessagingException("Empty multipart: " + this.contentType);
}
} else {
for (int i = 0; i < this.parts.size(); i++) {
los.writeln(boundary);
this.parts.elementAt(i).writeTo(os);
los.writeln();
}
}
los.writeln(boundary + "--");
}
protected synchronized void parse() throws MessagingException {
if (this.parsed)
return;
initializeProperties();
InputStream in = null;
SharedInputStream sin = null;
long start = 0L, end = 0L;
try {
in = this.ds.getInputStream();
if (!(in instanceof java.io.ByteArrayInputStream) && !(in instanceof BufferedInputStream) && !(in instanceof SharedInputStream))
in = new BufferedInputStream(in);
} catch (Exception ex) {
throw new MessagingException("No inputstream from datasource", ex);
}
if (in instanceof SharedInputStream)
sin = (SharedInputStream)in;
ContentType cType = new ContentType(this.contentType);
String boundary = null;
if (!this.ignoreExistingBoundaryParameter) {
String bp = cType.getParameter("boundary");
if (bp != null)
boundary = "--" + bp;
}
if (boundary == null && !this.ignoreMissingBoundaryParameter && !this.ignoreExistingBoundaryParameter)
throw new MessagingException("Missing boundary parameter");
try {
LineInputStream lin = new LineInputStream(in);
StringBuffer preamblesb = null;
String lineSeparator = null;
String line;
while ((line = lin.readLine()) != null) {
int k;
for (k = line.length() - 1; k >= 0; k--) {
char c = line.charAt(k);
if (c != ' ' && c != '\t')
break;
}
line = line.substring(0, k + 1);
if (boundary != null) {
if (line.equals(boundary))
break;
if (line.length() == boundary.length() + 2 &&
line.startsWith(boundary) && line.endsWith("--")) {
line = null;
break;
}
} else if (line.length() > 2 && line.startsWith("--") && (
line.length() <= 4 || !allDashes(line))) {
boundary = line;
break;
}
if (line.length() > 0) {
if (lineSeparator == null)
try {
lineSeparator = System.getProperty("line.separator", "\n");
} catch (SecurityException ex) {
lineSeparator = "\n";
}
if (preamblesb == null)
preamblesb = new StringBuffer(line.length() + 2);
preamblesb.append(line).append(lineSeparator);
}
}
if (preamblesb != null)
this.preamble = preamblesb.toString();
if (line == null) {
if (this.allowEmpty)
return;
throw new MessagingException("Missing start boundary");
}
byte[] bndbytes = ASCIIUtility.getBytes(boundary);
int bl = bndbytes.length;
int[] bcs = new int[256];
for (int i = 0; i < bl; i++)
bcs[bndbytes[i] & 0xFF] = i + 1;
int[] gss = new int[bl];
for (int j = bl; j > 0; j--) {
int k = bl - 1;
while (true) {
if (k >= j) {
if (bndbytes[k] == bndbytes[k - j]) {
gss[k - 1] = j;
} else {
break;
}
k--;
continue;
}
while (k > 0)
gss[--k] = j;
break;
}
}
gss[bl - 1] = 1;
boolean done = false;
while (!done) {
int eolLen;
MimeBodyPart part;
InternetHeaders headers = null;
if (sin != null) {
start = sin.getPosition();
while ((line = lin.readLine()) != null && line.length() > 0);
if (line == null) {
if (!this.ignoreMissingEndBoundary)
throw new MessagingException("missing multipart end boundary");
this.complete = false;
break;
}
} else {
headers = createInternetHeaders(in);
}
if (!in.markSupported())
throw new MessagingException("Stream doesn't support mark");
ByteArrayOutputStream buf = null;
if (sin == null) {
buf = new ByteArrayOutputStream();
} else {
end = sin.getPosition();
}
byte[] inbuf = new byte[bl];
byte[] previnbuf = new byte[bl];
int inSize = 0;
int prevSize = 0;
boolean first = true;
while (true) {
in.mark(bl + 4 + 1000);
eolLen = 0;
inSize = readFully(in, inbuf, 0, bl);
if (inSize < bl) {
if (!this.ignoreMissingEndBoundary)
throw new MessagingException("missing multipart end boundary");
if (sin != null)
end = sin.getPosition();
this.complete = false;
done = true;
break;
}
int k;
for (k = bl - 1; k >= 0 &&
inbuf[k] == bndbytes[k]; k--);
if (k < 0) {
eolLen = 0;
if (!first) {
int b = previnbuf[prevSize - 1];
if (b == 13 || b == 10) {
eolLen = 1;
if (b == 10 && prevSize >= 2) {
b = previnbuf[prevSize - 2];
if (b == 13)
eolLen = 2;
}
}
}
if (first || eolLen > 0) {
if (sin != null)
end = sin.getPosition() - (long)bl - (long)eolLen;
int b2 = in.read();
if (b2 == 45 &&
in.read() == 45) {
this.complete = true;
done = true;
break;
}
while (b2 == 32 || b2 == 9)
b2 = in.read();
if (b2 == 10)
break;
if (b2 == 13) {
in.mark(1);
if (in.read() != 10) {
in.reset();
break;
}
break;
}
}
k = 0;
}
int skip = Math.max(k + 1 - bcs[inbuf[k] & Byte.MAX_VALUE], gss[k]);
if (skip < 2) {
if (sin == null && prevSize > 1)
buf.write(previnbuf, 0, prevSize - 1);
in.reset();
skipFully(in, 1L);
if (prevSize >= 1) {
previnbuf[0] = previnbuf[prevSize - 1];
previnbuf[1] = inbuf[0];
prevSize = 2;
} else {
previnbuf[0] = inbuf[0];
prevSize = 1;
}
} else {
if (prevSize > 0 && sin == null)
buf.write(previnbuf, 0, prevSize);
prevSize = skip;
in.reset();
skipFully(in, (long)prevSize);
byte[] tmp = inbuf;
inbuf = previnbuf;
previnbuf = tmp;
}
first = false;
}
if (sin != null) {
part = createMimeBodyPartIs(sin.newStream(start, end));
} else {
if (prevSize - eolLen > 0)
buf.write(previnbuf, 0, prevSize - eolLen);
if (!this.complete && inSize > 0)
buf.write(inbuf, 0, inSize);
part = createMimeBodyPart(headers, buf.toByteArray());
}
super.addBodyPart(part);
}
} catch (IOException ioex) {
throw new MessagingException("IO Error", ioex);
} finally {
try {
in.close();
} catch (IOException e) {}
}
this.parsed = true;
}
private static boolean allDashes(String s) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != '-')
return false;
}
return true;
}
private static int readFully(InputStream in, byte[] buf, int off, int len) throws IOException {
if (len == 0)
return 0;
int total = 0;
while (len > 0) {
int bsize = in.read(buf, off, len);
if (bsize <= 0)
break;
off += bsize;
total += bsize;
len -= bsize;
}
return (total > 0) ? total : -1;
}
private void skipFully(InputStream in, long offset) throws IOException {
while (offset > 0L) {
long cur = in.skip(offset);
if (cur <= 0L)
throw new EOFException("can't skip");
offset -= cur;
}
}
protected InternetHeaders createInternetHeaders(InputStream is) throws MessagingException {
return new InternetHeaders(is);
}
protected MimeBodyPart createMimeBodyPart(InternetHeaders headers, byte[] content) throws MessagingException {
return new MimeBodyPart(headers, content);
}
protected MimeBodyPart createMimeBodyPart(InputStream is) throws MessagingException {
return new MimeBodyPart(is);
}
private MimeBodyPart createMimeBodyPartIs(InputStream is) throws MessagingException {
try {
return createMimeBodyPart(is);
} finally {
try {
is.close();
} catch (IOException e) {}
}
}
}

View file

@ -0,0 +1,35 @@
package javax.mail.internet;
import java.util.Enumeration;
import javax.mail.MessagingException;
import javax.mail.Part;
public interface MimePart extends Part {
String getHeader(String paramString1, String paramString2) throws MessagingException;
void addHeaderLine(String paramString) throws MessagingException;
Enumeration getAllHeaderLines() throws MessagingException;
Enumeration getMatchingHeaderLines(String[] paramArrayOfString) throws MessagingException;
Enumeration getNonMatchingHeaderLines(String[] paramArrayOfString) throws MessagingException;
String getEncoding() throws MessagingException;
String getContentID() throws MessagingException;
String getContentMD5() throws MessagingException;
void setContentMD5(String paramString) throws MessagingException;
String[] getContentLanguage() throws MessagingException;
void setContentLanguage(String[] paramArrayOfString) throws MessagingException;
void setText(String paramString) throws MessagingException;
void setText(String paramString1, String paramString2) throws MessagingException;
void setText(String paramString1, String paramString2, String paramString3) throws MessagingException;
}

View file

@ -0,0 +1,70 @@
package javax.mail.internet;
import com.sun.mail.util.FolderClosedIOException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownServiceException;
import javax.activation.DataSource;
import javax.mail.FolderClosedException;
import javax.mail.MessageAware;
import javax.mail.MessageContext;
import javax.mail.MessagingException;
public class MimePartDataSource implements DataSource, MessageAware {
protected MimePart part;
private MessageContext context;
public MimePartDataSource(MimePart part) {
this.part = part;
}
public InputStream getInputStream() throws IOException {
try {
InputStream is;
if (this.part instanceof MimeBodyPart) {
is = ((MimeBodyPart)this.part).getContentStream();
} else if (this.part instanceof MimeMessage) {
is = ((MimeMessage)this.part).getContentStream();
} else {
throw new MessagingException("Unknown part");
}
String encoding = MimeBodyPart.restrictEncoding(this.part, this.part.getEncoding());
if (encoding != null)
return MimeUtility.decode(is, encoding);
return is;
} catch (FolderClosedException fex) {
throw new FolderClosedIOException(fex.getFolder(),
fex.getMessage());
} catch (MessagingException mex) {
throw new IOException(mex.getMessage());
}
}
public OutputStream getOutputStream() throws IOException {
throw new UnknownServiceException("Writing not supported");
}
public String getContentType() {
try {
return this.part.getContentType();
} catch (MessagingException mex) {
return "application/octet-stream";
}
}
public String getName() {
try {
if (this.part instanceof MimeBodyPart)
return ((MimeBodyPart)this.part).getFileName();
} catch (MessagingException e) {}
return "";
}
public synchronized MessageContext getMessageContext() {
if (this.context == null)
this.context = new MessageContext(this.part);
return this.context;
}
}

View file

@ -0,0 +1,820 @@
package javax.mail.internet;
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.BASE64DecoderStream;
import com.sun.mail.util.BASE64EncoderStream;
import com.sun.mail.util.BEncoderStream;
import com.sun.mail.util.LineInputStream;
import com.sun.mail.util.PropUtil;
import com.sun.mail.util.QDecoderStream;
import com.sun.mail.util.QEncoderStream;
import com.sun.mail.util.QPDecoderStream;
import com.sun.mail.util.QPEncoderStream;
import com.sun.mail.util.UUDecoderStream;
import com.sun.mail.util.UUEncoderStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.EncodingAware;
import javax.mail.MessagingException;
public class MimeUtility {
private static final Map nonAsciiCharsetMap = new HashMap();
private static final boolean decodeStrict = PropUtil.getBooleanSystemProperty("mail.mime.decodetext.strict", true);
private static final boolean encodeEolStrict = PropUtil.getBooleanSystemProperty("mail.mime.encodeeol.strict", false);
private static final boolean ignoreUnknownEncoding = PropUtil.getBooleanSystemProperty("mail.mime.ignoreunknownencoding", false);
private static final boolean foldEncodedWords = PropUtil.getBooleanSystemProperty("mail.mime.foldencodedwords", false);
private static final boolean foldText = PropUtil.getBooleanSystemProperty("mail.mime.foldtext", true);
public static String getEncoding(DataSource ds) {
ContentType cType = null;
InputStream is = null;
String encoding = null;
if (ds instanceof EncodingAware) {
encoding = ((EncodingAware)ds).getEncoding();
if (encoding != null)
return encoding;
}
try {
cType = new ContentType(ds.getContentType());
is = ds.getInputStream();
boolean isText = cType.match("text/*");
int i = checkAscii(is, -1, !isText);
switch (i) {
case 1:
encoding = "7bit";
break;
case 2:
if (isText && nonAsciiCharset(cType)) {
encoding = "base64";
} else {
encoding = "quoted-printable";
}
break;
default:
encoding = "base64";
break;
}
} catch (Exception ex) {
return "base64";
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {}
}
return encoding;
}
private static boolean nonAsciiCharset(ContentType ct) {
Boolean bool;
String charset = ct.getParameter("charset");
if (charset == null)
return false;
charset = charset.toLowerCase(Locale.ENGLISH);
synchronized (nonAsciiCharsetMap) {
bool = (Boolean)nonAsciiCharsetMap.get(charset);
}
if (bool == null) {
try {
byte[] b = "\r\n".getBytes(charset);
bool = (b.length != 2 || b[0] != 13 || b[1] != 10);
} catch (UnsupportedEncodingException uex) {
bool = Boolean.FALSE;
} catch (RuntimeException ex) {
bool = Boolean.TRUE;
}
synchronized (nonAsciiCharsetMap) {
nonAsciiCharsetMap.put(charset, bool);
}
}
return bool;
}
public static String getEncoding(DataHandler dh) {
ContentType cType = null;
String encoding = null;
if (dh.getName() != null)
return getEncoding(dh.getDataSource());
try {
cType = new ContentType(dh.getContentType());
} catch (Exception ex) {
return "base64";
}
if (cType.match("text/*")) {
AsciiOutputStream aos = new AsciiOutputStream(false, false);
try {
dh.writeTo(aos);
} catch (IOException e) {}
switch (aos.getAscii()) {
case 1:
encoding = "7bit";
break;
case 2:
encoding = "quoted-printable";
break;
default:
encoding = "base64";
break;
}
} else {
AsciiOutputStream aos = new AsciiOutputStream(true, encodeEolStrict);
try {
dh.writeTo(aos);
} catch (IOException e) {}
if (aos.getAscii() == 1) {
encoding = "7bit";
} else {
encoding = "base64";
}
}
return encoding;
}
public static InputStream decode(InputStream is, String encoding) throws MessagingException {
if (encoding.equalsIgnoreCase("base64"))
return new BASE64DecoderStream(is);
if (encoding.equalsIgnoreCase("quoted-printable"))
return new QPDecoderStream(is);
if (encoding.equalsIgnoreCase("uuencode") ||
encoding.equalsIgnoreCase("x-uuencode") ||
encoding.equalsIgnoreCase("x-uue"))
return new UUDecoderStream(is);
if (encoding.equalsIgnoreCase("binary") ||
encoding.equalsIgnoreCase("7bit") ||
encoding.equalsIgnoreCase("8bit"))
return is;
if (!ignoreUnknownEncoding)
throw new MessagingException("Unknown encoding: " + encoding);
return is;
}
public static OutputStream encode(OutputStream os, String encoding) throws MessagingException {
if (encoding == null)
return os;
if (encoding.equalsIgnoreCase("base64"))
return new BASE64EncoderStream(os);
if (encoding.equalsIgnoreCase("quoted-printable"))
return new QPEncoderStream(os);
if (encoding.equalsIgnoreCase("uuencode") ||
encoding.equalsIgnoreCase("x-uuencode") ||
encoding.equalsIgnoreCase("x-uue"))
return new UUEncoderStream(os);
if (encoding.equalsIgnoreCase("binary") ||
encoding.equalsIgnoreCase("7bit") ||
encoding.equalsIgnoreCase("8bit"))
return os;
throw new MessagingException("Unknown encoding: " + encoding);
}
public static OutputStream encode(OutputStream os, String encoding, String filename) throws MessagingException {
if (encoding == null)
return os;
if (encoding.equalsIgnoreCase("base64"))
return new BASE64EncoderStream(os);
if (encoding.equalsIgnoreCase("quoted-printable"))
return new QPEncoderStream(os);
if (encoding.equalsIgnoreCase("uuencode") ||
encoding.equalsIgnoreCase("x-uuencode") ||
encoding.equalsIgnoreCase("x-uue"))
return new UUEncoderStream(os, filename);
if (encoding.equalsIgnoreCase("binary") ||
encoding.equalsIgnoreCase("7bit") ||
encoding.equalsIgnoreCase("8bit"))
return os;
throw new MessagingException("Unknown encoding: " + encoding);
}
public static String encodeText(String text) throws UnsupportedEncodingException {
return encodeText(text, null, null);
}
public static String encodeText(String text, String charset, String encoding) throws UnsupportedEncodingException {
return encodeWord(text, charset, encoding, false);
}
public static String decodeText(String etext) throws UnsupportedEncodingException {
String lwsp = " \t\n\r";
if (etext.indexOf("=?") == -1)
return etext;
StringTokenizer st = new StringTokenizer(etext, lwsp, true);
StringBuffer sb = new StringBuffer();
StringBuffer wsb = new StringBuffer();
boolean prevWasEncoded = false;
while (st.hasMoreTokens()) {
String word;
String s = st.nextToken();
char c;
if ((c = s.charAt(0)) == ' ' || c == '\t' || c == '\r' || c == '\n') {
wsb.append(c);
continue;
}
try {
word = decodeWord(s);
if (!prevWasEncoded && wsb.length() > 0)
sb.append(wsb);
prevWasEncoded = true;
} catch (ParseException pex) {
word = s;
if (!decodeStrict) {
String dword = decodeInnerWords(word);
if (dword != word) {
if (!prevWasEncoded || !word.startsWith("=?"))
if (wsb.length() > 0)
sb.append(wsb);
prevWasEncoded = word.endsWith("?=");
word = dword;
} else {
if (wsb.length() > 0)
sb.append(wsb);
prevWasEncoded = false;
}
} else {
if (wsb.length() > 0)
sb.append(wsb);
prevWasEncoded = false;
}
}
sb.append(word);
wsb.setLength(0);
}
sb.append(wsb);
return sb.toString();
}
public static String encodeWord(String word) throws UnsupportedEncodingException {
return encodeWord(word, null, null);
}
public static String encodeWord(String word, String charset, String encoding) throws UnsupportedEncodingException {
return encodeWord(word, charset, encoding, true);
}
private static String encodeWord(String string, String charset, String encoding, boolean encodingWord) throws UnsupportedEncodingException {
String jcharset;
boolean b64;
int ascii = checkAscii(string);
if (ascii == 1)
return string;
if (charset == null) {
jcharset = getDefaultJavaCharset();
charset = getDefaultMIMECharset();
} else {
jcharset = javaCharset(charset);
}
if (encoding == null)
if (ascii != 3) {
encoding = "Q";
} else {
encoding = "B";
}
if (encoding.equalsIgnoreCase("B")) {
b64 = true;
} else if (encoding.equalsIgnoreCase("Q")) {
b64 = false;
} else {
throw new UnsupportedEncodingException("Unknown transfer encoding: " + encoding);
}
StringBuffer outb = new StringBuffer();
doEncode(string, b64, jcharset, 68 -
charset.length(), "=?" + charset + "?" + encoding + "?", true, encodingWord, outb);
return outb.toString();
}
private static void doEncode(String string, boolean b64, String jcharset, int avail, String prefix, boolean first, boolean encodingWord, StringBuffer buf) throws UnsupportedEncodingException {
int len;
byte[] bytes = string.getBytes(jcharset);
if (b64) {
len = BEncoderStream.encodedLength(bytes);
} else {
len = QEncoderStream.encodedLength(bytes, encodingWord);
}
int size;
if (len > avail && (size = string.length()) > 1) {
int split = size / 2;
if (Character.isHighSurrogate(string.charAt(split - 1)))
split--;
if (split > 0)
doEncode(string.substring(0, split), b64, jcharset, avail, prefix, first, encodingWord, buf);
doEncode(string.substring(split, size), b64, jcharset, avail, prefix, false, encodingWord, buf);
} else {
OutputStream eos;
ByteArrayOutputStream os = new ByteArrayOutputStream();
if (b64) {
eos = new BEncoderStream(os);
} else {
eos = new QEncoderStream(os, encodingWord);
}
try {
eos.write(bytes);
eos.close();
} catch (IOException e) {}
byte[] encodedBytes = os.toByteArray();
if (!first)
if (foldEncodedWords) {
buf.append("\r\n ");
} else {
buf.append(" ");
}
buf.append(prefix);
for (int i = 0; i < encodedBytes.length; i++)
buf.append((char)encodedBytes[i]);
buf.append("?=");
}
}
public static String decodeWord(String eword) throws ParseException, UnsupportedEncodingException {
if (!eword.startsWith("=?"))
throw new ParseException("encoded word does not start with \"=?\": " + eword);
int start = 2;
int pos;
if ((pos = eword.indexOf('?', start)) == -1)
throw new ParseException("encoded word does not include charset: " + eword);
String charset = eword.substring(start, pos);
int lpos = charset.indexOf('*');
if (lpos >= 0)
charset = charset.substring(0, lpos);
charset = javaCharset(charset);
start = pos + 1;
if ((pos = eword.indexOf('?', start)) == -1)
throw new ParseException("encoded word does not include encoding: " + eword);
String encoding = eword.substring(start, pos);
start = pos + 1;
if ((pos = eword.indexOf("?=", start)) == -1)
throw new ParseException("encoded word does not end with \"?=\": " + eword);
String word = eword.substring(start, pos);
try {
String decodedWord;
if (word.length() > 0) {
InputStream is;
ByteArrayInputStream bis = new ByteArrayInputStream(
ASCIIUtility.getBytes(word));
if (encoding.equalsIgnoreCase("B")) {
is = new BASE64DecoderStream(bis);
} else if (encoding.equalsIgnoreCase("Q")) {
is = new QDecoderStream(bis);
} else {
throw new UnsupportedEncodingException("unknown encoding: " + encoding);
}
int count = bis.available();
byte[] bytes = new byte[count];
count = is.read(bytes, 0, count);
decodedWord = (count <= 0) ? "" : new String(bytes, 0, count, charset);
} else {
decodedWord = "";
}
if (pos + 2 < eword.length()) {
String rest = eword.substring(pos + 2);
if (!decodeStrict)
rest = decodeInnerWords(rest);
decodedWord = decodedWord + rest;
}
return decodedWord;
} catch (UnsupportedEncodingException uex) {
throw uex;
} catch (IOException ioex) {
throw new ParseException(ioex.toString());
} catch (IllegalArgumentException iex) {
throw new UnsupportedEncodingException(charset);
}
}
private static String decodeInnerWords(String word) throws UnsupportedEncodingException {
int start = 0;
StringBuffer buf = new StringBuffer();
int i;
while ((i = word.indexOf("=?", start)) >= 0) {
buf.append(word.substring(start, i));
int end = word.indexOf('?', i + 2);
if (end < 0)
break;
end = word.indexOf('?', end + 1);
if (end < 0)
break;
end = word.indexOf("?=", end + 1);
if (end < 0)
break;
String s = word.substring(i, end + 2);
try {
s = decodeWord(s);
} catch (ParseException e) {}
buf.append(s);
start = end + 2;
}
if (start == 0)
return word;
if (start < word.length())
buf.append(word.substring(start));
return buf.toString();
}
public static String quote(String word, String specials) {
int len = (word == null) ? 0 : word.length();
if (len == 0)
return "\"\"";
boolean needQuoting = false;
for (int i = 0; i < len; i++) {
char c = word.charAt(i);
if (c == '"' || c == '\\' || c == '\r' || c == '\n') {
StringBuffer sb = new StringBuffer(len + 3);
sb.append('"');
sb.append(word.substring(0, i));
int lastc = 0;
for (int j = i; j < len; j++) {
char cc = word.charAt(j);
if (cc == '"' || cc == '\\' || cc == '\r' || cc == '\n')
if (cc != '\n' || lastc != 13)
sb.append('\\');
sb.append(cc);
lastc = cc;
}
sb.append('"');
return sb.toString();
}
if (c < ' ' || c >= '\u007F' || specials.indexOf(c) >= 0)
needQuoting = true;
}
if (needQuoting) {
StringBuffer sb = new StringBuffer(len + 2);
sb.append('"').append(word).append('"');
return sb.toString();
}
return word;
}
public static String fold(int used, String s) {
if (!foldText)
return s;
int end;
for (end = s.length() - 1; end >= 0; end--) {
char c = s.charAt(end);
if (c != ' ' && c != '\t' && c != '\r' && c != '\n')
break;
}
if (end != s.length() - 1)
s = s.substring(0, end + 1);
if (used + s.length() <= 76)
return s;
StringBuffer sb = new StringBuffer(s.length() + 4);
char lastc = '\000';
while (used + s.length() > 76) {
int lastspace = -1;
for (int i = 0; i < s.length() && (
lastspace == -1 || used + i <= 76); i++) {
char c = s.charAt(i);
if ((c == ' ' || c == '\t') &&
lastc != ' ' && lastc != '\t')
lastspace = i;
lastc = c;
}
if (lastspace == -1) {
sb.append(s);
s = "";
used = 0;
break;
}
sb.append(s.substring(0, lastspace));
sb.append("\r\n");
lastc = s.charAt(lastspace);
sb.append(lastc);
s = s.substring(lastspace + 1);
used = 1;
}
sb.append(s);
return sb.toString();
}
public static String unfold(String s) {
if (!foldText)
return s;
StringBuffer sb = null;
int i;
while ((i = indexOfAny(s, "\r\n")) >= 0) {
int start = i;
int l = s.length();
i++;
if (i < l && s.charAt(i - 1) == '\r' && s.charAt(i) == '\n')
i++;
if (start == 0 || s.charAt(start - 1) != '\\') {
char c;
if (i < l && ((c = s.charAt(i)) == ' ' || c == '\t')) {
i++;
while (i < l && ((c = s.charAt(i)) == ' ' || c == '\t'))
i++;
if (sb == null)
sb = new StringBuffer(s.length());
if (start != 0) {
sb.append(s.substring(0, start));
sb.append(' ');
}
s = s.substring(i);
continue;
}
if (sb == null)
sb = new StringBuffer(s.length());
sb.append(s.substring(0, i));
s = s.substring(i);
continue;
}
if (sb == null)
sb = new StringBuffer(s.length());
sb.append(s.substring(0, start - 1));
sb.append(s.substring(start, i));
s = s.substring(i);
}
if (sb != null) {
sb.append(s);
return sb.toString();
}
return s;
}
private static int indexOfAny(String s, String any) {
return indexOfAny(s, any, 0);
}
private static int indexOfAny(String s, String any, int start) {
try {
int len = s.length();
for (int i = start; i < len; i++) {
if (any.indexOf(s.charAt(i)) >= 0)
return i;
}
return -1;
} catch (StringIndexOutOfBoundsException e) {
return -1;
}
}
public static String javaCharset(String charset) {
if (mime2java == null || charset == null)
return charset;
String alias = (String)
mime2java.get(charset.toLowerCase(Locale.ENGLISH));
return (alias == null) ? charset : alias;
}
public static String mimeCharset(String charset) {
if (java2mime == null || charset == null)
return charset;
String alias = (String)
java2mime.get(charset.toLowerCase(Locale.ENGLISH));
return (alias == null) ? charset : alias;
}
public static String getDefaultJavaCharset() {
if (defaultJavaCharset == null) {
String mimecs = null;
try {
mimecs = System.getProperty("mail.mime.charset");
} catch (SecurityException e) {}
if (mimecs != null && mimecs.length() > 0) {
defaultJavaCharset = javaCharset(mimecs);
return defaultJavaCharset;
}
try {
defaultJavaCharset = System.getProperty("file.encoding", "8859_1");
} catch (SecurityException sex) {
InputStreamReader reader = new InputStreamReader(new NullInputStream());
defaultJavaCharset = reader.getEncoding();
if (defaultJavaCharset == null)
defaultJavaCharset = "8859_1";
}
}
class NullInputStream extends InputStream {
public int read() {
return 0;
}
};
return defaultJavaCharset;
}
static String getDefaultMIMECharset() {
if (defaultMIMECharset == null)
try {
defaultMIMECharset = System.getProperty("mail.mime.charset");
} catch (SecurityException e) {}
if (defaultMIMECharset == null)
defaultMIMECharset = mimeCharset(getDefaultJavaCharset());
return defaultMIMECharset;
}
private static Hashtable java2mime = new Hashtable(40);
private static Hashtable mime2java = new Hashtable(10);
public static final int ALL = -1;
private static String defaultJavaCharset;
private static String defaultMIMECharset;
static final int ALL_ASCII = 1;
static final int MOSTLY_ASCII = 2;
static final int MOSTLY_NONASCII = 3;
static {
try {
InputStream is = MimeUtility.class
.getResourceAsStream("/META-INF/javamail.charset.map");
if (is != null)
try {
is = new LineInputStream(is);
loadMappings((LineInputStream)is, java2mime);
loadMappings((LineInputStream)is, mime2java);
} finally {
try {
is.close();
} catch (Exception e) {}
}
} catch (Exception e) {}
if (java2mime.isEmpty()) {
java2mime.put("8859_1", "ISO-8859-1");
java2mime.put("iso8859_1", "ISO-8859-1");
java2mime.put("iso8859-1", "ISO-8859-1");
java2mime.put("8859_2", "ISO-8859-2");
java2mime.put("iso8859_2", "ISO-8859-2");
java2mime.put("iso8859-2", "ISO-8859-2");
java2mime.put("8859_3", "ISO-8859-3");
java2mime.put("iso8859_3", "ISO-8859-3");
java2mime.put("iso8859-3", "ISO-8859-3");
java2mime.put("8859_4", "ISO-8859-4");
java2mime.put("iso8859_4", "ISO-8859-4");
java2mime.put("iso8859-4", "ISO-8859-4");
java2mime.put("8859_5", "ISO-8859-5");
java2mime.put("iso8859_5", "ISO-8859-5");
java2mime.put("iso8859-5", "ISO-8859-5");
java2mime.put("8859_6", "ISO-8859-6");
java2mime.put("iso8859_6", "ISO-8859-6");
java2mime.put("iso8859-6", "ISO-8859-6");
java2mime.put("8859_7", "ISO-8859-7");
java2mime.put("iso8859_7", "ISO-8859-7");
java2mime.put("iso8859-7", "ISO-8859-7");
java2mime.put("8859_8", "ISO-8859-8");
java2mime.put("iso8859_8", "ISO-8859-8");
java2mime.put("iso8859-8", "ISO-8859-8");
java2mime.put("8859_9", "ISO-8859-9");
java2mime.put("iso8859_9", "ISO-8859-9");
java2mime.put("iso8859-9", "ISO-8859-9");
java2mime.put("sjis", "Shift_JIS");
java2mime.put("jis", "ISO-2022-JP");
java2mime.put("iso2022jp", "ISO-2022-JP");
java2mime.put("euc_jp", "euc-jp");
java2mime.put("koi8_r", "koi8-r");
java2mime.put("euc_cn", "euc-cn");
java2mime.put("euc_tw", "euc-tw");
java2mime.put("euc_kr", "euc-kr");
}
if (mime2java.isEmpty()) {
mime2java.put("iso-2022-cn", "ISO2022CN");
mime2java.put("iso-2022-kr", "ISO2022KR");
mime2java.put("utf-8", "UTF8");
mime2java.put("utf8", "UTF8");
mime2java.put("ja_jp.iso2022-7", "ISO2022JP");
mime2java.put("ja_jp.eucjp", "EUCJIS");
mime2java.put("euc-kr", "KSC5601");
mime2java.put("euckr", "KSC5601");
mime2java.put("us-ascii", "ISO-8859-1");
mime2java.put("x-us-ascii", "ISO-8859-1");
}
}
private static void loadMappings(LineInputStream is, Hashtable table) {
while (true) {
String currLine;
try {
currLine = is.readLine();
} catch (IOException ioex) {
break;
}
if (currLine == null)
break;
if (currLine.startsWith("--") && currLine.endsWith("--"))
break;
if (currLine.trim().length() == 0 || currLine.startsWith("#"))
continue;
StringTokenizer tk = new StringTokenizer(currLine, " \t");
try {
String key = tk.nextToken();
String value = tk.nextToken();
table.put(key.toLowerCase(Locale.ENGLISH), value);
} catch (NoSuchElementException e) {}
}
}
static int checkAscii(String s) {
int ascii = 0, non_ascii = 0;
int l = s.length();
for (int i = 0; i < l; i++) {
if (nonascii(s.charAt(i))) {
non_ascii++;
} else {
ascii++;
}
}
if (non_ascii == 0)
return 1;
if (ascii > non_ascii)
return 2;
return 3;
}
static int checkAscii(byte[] b) {
int ascii = 0, non_ascii = 0;
for (int i = 0; i < b.length; i++) {
if (nonascii(b[i] & 0xFF)) {
non_ascii++;
} else {
ascii++;
}
}
if (non_ascii == 0)
return 1;
if (ascii > non_ascii)
return 2;
return 3;
}
static int checkAscii(InputStream is, int max, boolean breakOnNonAscii) {
int ascii = 0, non_ascii = 0;
int block = 4096;
int linelen = 0;
boolean longLine = false, badEOL = false;
boolean checkEOL = (encodeEolStrict && breakOnNonAscii);
byte[] buf = null;
if (max != 0) {
block = (max == -1) ? 4096 : Math.min(max, 4096);
buf = new byte[block];
}
while (max != 0) {
int len;
try {
if ((len = is.read(buf, 0, block)) == -1)
break;
int lastb = 0;
for (int i = 0; i < len; i++) {
int b = buf[i] & 0xFF;
if (checkEOL && ((lastb == 13 && b != 10) || (lastb != 13 && b == 10)))
badEOL = true;
if (b == 13 || b == 10) {
linelen = 0;
} else {
linelen++;
if (linelen > 998)
longLine = true;
}
if (nonascii(b)) {
if (breakOnNonAscii)
return 3;
non_ascii++;
} else {
ascii++;
}
lastb = b;
}
} catch (IOException ioex) {
break;
}
if (max != -1)
max -= len;
}
if (max == 0 && breakOnNonAscii)
return 3;
if (non_ascii == 0) {
if (badEOL)
return 3;
if (longLine)
return 2;
return 1;
}
if (ascii > non_ascii)
return 2;
return 3;
}
static final boolean nonascii(int b) {
return (b >= 127 || (b < 32 && b != 13 && b != 10 && b != 9));
}
}

View file

@ -0,0 +1,92 @@
package javax.mail.internet;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.mail.Address;
public class NewsAddress extends Address {
protected String newsgroup;
protected String host;
private static final long serialVersionUID = -4203797299824684143L;
public NewsAddress() {}
public NewsAddress(String newsgroup) {
this(newsgroup, null);
}
public NewsAddress(String newsgroup, String host) {
this.newsgroup = newsgroup;
this.host = host;
}
public String getType() {
return "news";
}
public void setNewsgroup(String newsgroup) {
this.newsgroup = newsgroup;
}
public String getNewsgroup() {
return this.newsgroup;
}
public void setHost(String host) {
this.host = host;
}
public String getHost() {
return this.host;
}
public String toString() {
return this.newsgroup;
}
public boolean equals(Object a) {
if (!(a instanceof NewsAddress))
return false;
NewsAddress s = (NewsAddress)a;
return (((this.newsgroup == null && s.newsgroup == null) || (this.newsgroup != null &&
this.newsgroup.equals(s.newsgroup))) && ((this.host == null && s.host == null) || (this.host != null && s.host != null &&
this.host.equalsIgnoreCase(s.host))));
}
public int hashCode() {
int hash = 0;
if (this.newsgroup != null)
hash += this.newsgroup.hashCode();
if (this.host != null)
hash += this.host.toLowerCase(Locale.ENGLISH).hashCode();
return hash;
}
public static String toString(Address[] addresses) {
if (addresses == null || addresses.length == 0)
return null;
StringBuffer s = new StringBuffer(((NewsAddress)addresses[0])
.toString());
for (int i = 1; i < addresses.length; i++)
s.append(",").append(((NewsAddress)addresses[i]).toString());
return s.toString();
}
public static NewsAddress[] parse(String newsgroups) throws AddressException {
StringTokenizer st = new StringTokenizer(newsgroups, ",");
Vector<NewsAddress> nglist = new Vector();
while (st.hasMoreTokens()) {
String ng = st.nextToken();
nglist.addElement(new NewsAddress(ng));
}
int size = nglist.size();
NewsAddress[] na = new NewsAddress[size];
if (size > 0)
nglist.copyInto(na);
return na;
}
}

View file

@ -0,0 +1,517 @@
package javax.mail.internet;
import com.sun.mail.util.ASCIIUtility;
import com.sun.mail.util.PropUtil;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class ParameterList {
private Map list = new LinkedHashMap();
private Set multisegmentNames;
private Map slist;
private String lastName = null;
private static final boolean encodeParameters = PropUtil.getBooleanSystemProperty("mail.mime.encodeparameters", true);
private static final boolean decodeParameters = PropUtil.getBooleanSystemProperty("mail.mime.decodeparameters", true);
private static final boolean decodeParametersStrict = PropUtil.getBooleanSystemProperty("mail.mime.decodeparameters.strict", false);
private static final boolean applehack = PropUtil.getBooleanSystemProperty("mail.mime.applefilenames", false);
private static final boolean windowshack = PropUtil.getBooleanSystemProperty("mail.mime.windowsfilenames", false);
private static final boolean parametersStrict = PropUtil.getBooleanSystemProperty("mail.mime.parameters.strict", true);
private static final boolean splitLongParameters = PropUtil.getBooleanSystemProperty("mail.mime.splitlongparameters", true);
private static class Value {
String value;
String charset;
String encodedValue;
private Value() {}
}
private static class MultiValue extends ArrayList {
private static final long serialVersionUID = 699561094618751023L;
String value;
private MultiValue() {}
}
private static class ParamEnum implements Enumeration {
private Iterator it;
ParamEnum(Iterator it) {
this.it = it;
}
public boolean hasMoreElements() {
return this.it.hasNext();
}
public Object nextElement() {
return this.it.next();
}
}
public ParameterList() {
if (decodeParameters) {
this.multisegmentNames = new HashSet();
this.slist = new HashMap();
}
}
public ParameterList(String s) throws ParseException {
this();
HeaderTokenizer h = new HeaderTokenizer(s, "()<>@,;:\\\"\t []/?=");
while (true) {
HeaderTokenizer.Token tk = h.next();
int type = tk.getType();
if (type == -4)
break;
if ((char)type == ';') {
tk = h.next();
if (tk.getType() == -4)
break;
if (tk.getType() != -1)
throw new ParseException("In parameter list <" + s + ">" + ", expected parameter name, " + "got \"" +
tk.getValue() + "\"");
String name = tk.getValue().toLowerCase(Locale.ENGLISH);
tk = h.next();
if ((char)tk.getType() != '=')
throw new ParseException("In parameter list <" + s + ">" + ", expected '=', " + "got \"" +
tk.getValue() + "\"");
if (windowshack && (
name.equals("name") || name.equals("filename"))) {
tk = h.next(';', true);
} else if (parametersStrict) {
tk = h.next();
} else {
tk = h.next(';');
}
type = tk.getType();
if (type != -1 && type != -2)
throw new ParseException("In parameter list <" + s + ">" + ", expected parameter value, " + "got \"" +
tk.getValue() + "\"");
String value = tk.getValue();
this.lastName = name;
if (decodeParameters) {
putEncodedName(name, value);
continue;
}
this.list.put(name, value);
continue;
}
if (type == -1 && this.lastName != null && ((applehack && (
this.lastName.equals("name") ||
this.lastName.equals("filename"))) || !parametersStrict)) {
String lastValue = (String)this.list.get(this.lastName);
String value = lastValue + " " + tk.getValue();
this.list.put(this.lastName, value);
continue;
}
throw new ParseException("In parameter list <" + s + ">" + ", expected ';', got \"" +
tk.getValue() + "\"");
}
if (decodeParameters)
combineMultisegmentNames(false);
}
public void combineSegments() {
if (decodeParameters && this.multisegmentNames.size() > 0)
try {
combineMultisegmentNames(true);
} catch (ParseException e) {}
}
private void putEncodedName(String name, String value) throws ParseException {
int star = name.indexOf('*');
if (star < 0) {
this.list.put(name, value);
} else if (star == name.length() - 1) {
name = name.substring(0, star);
Value v = extractCharset(value);
try {
v.value = decodeBytes(v.value, v.charset);
} catch (UnsupportedEncodingException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
}
this.list.put(name, v);
} else {
Object v;
String rname = name.substring(0, star);
this.multisegmentNames.add(rname);
this.list.put(rname, "");
if (name.endsWith("*")) {
if (name.endsWith("*0*")) {
v = extractCharset(value);
} else {
v = new Value();
((Value)v).encodedValue = value;
((Value)v).value = value;
}
name = name.substring(0, name.length() - 1);
} else {
v = value;
}
this.slist.put(name, v);
}
}
private void combineMultisegmentNames(boolean keepConsistentOnFailure) throws ParseException {
boolean success = false;
try {
Iterator<String> it = this.multisegmentNames.iterator();
while (it.hasNext()) {
String name = it.next();
MultiValue mv = new MultiValue();
String charset = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int segment;
for (segment = 0;; segment++) {
String sname = name + "*" + segment;
Object v = this.slist.get(sname);
if (v == null)
break;
mv.add(v);
try {
if (v instanceof Value) {
Value vv = (Value)v;
if (segment == 0) {
charset = vv.charset;
} else if (charset == null) {
this.multisegmentNames.remove(name);
break;
}
decodeBytes(vv.value, bos);
} else {
bos.write(ASCIIUtility.getBytes((String)v));
}
} catch (IOException e) {}
this.slist.remove(sname);
}
if (segment == 0) {
this.list.remove(name);
continue;
}
try {
if (charset != null)
charset = MimeUtility.javaCharset(charset);
if (charset == null || charset.length() == 0)
charset = MimeUtility.getDefaultJavaCharset();
if (charset != null) {
mv.value = bos.toString(charset);
} else {
mv.value = bos.toString();
}
} catch (UnsupportedEncodingException uex) {
if (decodeParametersStrict)
throw new ParseException(uex.toString());
try {
mv.value = bos.toString("iso-8859-1");
} catch (UnsupportedEncodingException e) {}
}
this.list.put(name, mv);
}
success = true;
} finally {
if (keepConsistentOnFailure || success) {
if (this.slist.size() > 0) {
Iterator sit = this.slist.values().iterator();
while (sit.hasNext()) {
Object v = sit.next();
if (v instanceof Value) {
Value vv = (Value)v;
try {
vv
.value = decodeBytes(vv.value, vv.charset);
} catch (UnsupportedEncodingException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
}
}
}
this.list.putAll(this.slist);
}
this.multisegmentNames.clear();
this.slist.clear();
}
}
}
public int size() {
return this.list.size();
}
public String get(String name) {
String value;
Object v = this.list.get(name.trim().toLowerCase(Locale.ENGLISH));
if (v instanceof MultiValue) {
value = ((MultiValue)v).value;
} else if (v instanceof Value) {
value = ((Value)v).value;
} else {
value = (String)v;
}
return value;
}
public void set(String name, String value) {
name = name.trim().toLowerCase(Locale.ENGLISH);
if (decodeParameters) {
try {
putEncodedName(name, value);
} catch (ParseException pex) {
this.list.put(name, value);
}
} else {
this.list.put(name, value);
}
}
public void set(String name, String value, String charset) {
if (encodeParameters) {
Value ev = encodeValue(value, charset);
if (ev != null) {
this.list.put(name.trim().toLowerCase(Locale.ENGLISH), ev);
} else {
set(name, value);
}
} else {
set(name, value);
}
}
public void remove(String name) {
this.list.remove(name.trim().toLowerCase(Locale.ENGLISH));
}
public Enumeration getNames() {
return new ParamEnum(this.list.keySet().iterator());
}
public String toString() {
return toString(0);
}
public String toString(int used) {
ToStringBuffer sb = new ToStringBuffer(used);
Iterator<Map.Entry> e = this.list.entrySet().iterator();
while (e.hasNext()) {
Map.Entry ent = e.next();
String name = (String)ent.getKey();
Object v = ent.getValue();
if (v instanceof MultiValue) {
MultiValue vv = (MultiValue)v;
name = name + "*";
for (int i = 0; i < vv.size(); i++) {
String str1, ns;
Object va = vv.get(i);
if (va instanceof Value) {
ns = name + i + "*";
str1 = ((Value)va).encodedValue;
} else {
ns = name + i;
str1 = (String)va;
}
sb.addNV(ns, quote(str1));
}
continue;
}
if (v instanceof Value) {
name = name + "*";
String str = ((Value)v).encodedValue;
sb.addNV(name, quote(str));
continue;
}
String value = (String)v;
if (value.length() > 60 && splitLongParameters && encodeParameters) {
int seg = 0;
name = name + "*";
while (value.length() > 60) {
sb.addNV(name + seg, quote(value.substring(0, 60)));
value = value.substring(60);
seg++;
}
if (value.length() > 0)
sb.addNV(name + seg, quote(value));
continue;
}
sb.addNV(name, quote(value));
}
return sb.toString();
}
private static class ToStringBuffer {
private int used;
private StringBuffer sb = new StringBuffer();
public ToStringBuffer(int used) {
this.used = used;
}
public void addNV(String name, String value) {
this.sb.append("; ");
this.used += 2;
int len = name.length() + value.length() + 1;
if (this.used + len > 76) {
this.sb.append("\r\n\t");
this.used = 8;
}
this.sb.append(name).append('=');
this.used += name.length() + 1;
if (this.used + value.length() > 76) {
String s = MimeUtility.fold(this.used, value);
this.sb.append(s);
int lastlf = s.lastIndexOf('\n');
if (lastlf >= 0) {
this.used += s.length() - lastlf - 1;
} else {
this.used += s.length();
}
} else {
this.sb.append(value);
this.used += value.length();
}
}
public String toString() {
return this.sb.toString();
}
}
private static String quote(String value) {
return MimeUtility.quote(value, "()<>@,;:\\\"\t []/?=");
}
private static final char[] hex = new char[] {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
private static Value encodeValue(String value, String charset) {
byte[] b;
if (MimeUtility.checkAscii(value) == 1)
return null;
try {
b = value.getBytes(MimeUtility.javaCharset(charset));
} catch (UnsupportedEncodingException ex) {
return null;
}
StringBuffer sb = new StringBuffer(b.length + charset.length() + 2);
sb.append(charset).append("''");
for (int i = 0; i < b.length; i++) {
char c = (char)(b[i] & 0xFF);
if (c <= ' ' || c >= '\u007F' || c == '*' || c == '\'' || c == '%' || "()<>@,;:\\\"\t []/?="
.indexOf(c) >= 0) {
sb.append('%').append(hex[c >> 4]).append(hex[c & 0xF]);
} else {
sb.append(c);
}
}
Value v = new Value();
v.charset = charset;
v.value = value;
v.encodedValue = sb.toString();
return v;
}
private static Value extractCharset(String value) throws ParseException {
Value v = new Value();
v.value = v.encodedValue = value;
try {
int i = value.indexOf('\'');
if (i < 0) {
if (decodeParametersStrict)
throw new ParseException("Missing charset in encoded value: " + value);
return v;
}
String charset = value.substring(0, i);
int li = value.indexOf('\'', i + 1);
if (li < 0) {
if (decodeParametersStrict)
throw new ParseException("Missing language in encoded value: " + value);
return v;
}
v.value = value.substring(li + 1);
v.charset = charset;
} catch (NumberFormatException nex) {
if (decodeParametersStrict)
throw new ParseException(nex.toString());
} catch (StringIndexOutOfBoundsException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
}
return v;
}
private static String decodeBytes(String value, String charset) throws ParseException, UnsupportedEncodingException {
byte[] b = new byte[value.length()];
int bi;
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '%')
try {
String hex = value.substring(i + 1, i + 3);
c = (char)Integer.parseInt(hex, 16);
i += 2;
} catch (NumberFormatException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
} catch (StringIndexOutOfBoundsException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
}
b[bi++] = (byte)c;
}
if (charset != null)
charset = MimeUtility.javaCharset(charset);
if (charset == null || charset.length() == 0)
charset = MimeUtility.getDefaultJavaCharset();
return new String(b, 0, bi, charset);
}
private static void decodeBytes(String value, OutputStream os) throws ParseException, IOException {
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '%')
try {
String hex = value.substring(i + 1, i + 3);
c = (char)Integer.parseInt(hex, 16);
i += 2;
} catch (NumberFormatException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
} catch (StringIndexOutOfBoundsException ex) {
if (decodeParametersStrict)
throw new ParseException(ex.toString());
}
os.write((byte)c);
}
}
}

View file

@ -0,0 +1,13 @@
package javax.mail.internet;
import javax.mail.MessagingException;
public class ParseException extends MessagingException {
private static final long serialVersionUID = 7649991205183658089L;
public ParseException() {}
public ParseException(String s) {
super(s);
}
}

View file

@ -0,0 +1,39 @@
package javax.mail.internet;
import com.sun.mail.util.LineOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import javax.mail.MessagingException;
public class PreencodedMimeBodyPart extends MimeBodyPart {
private String encoding;
public PreencodedMimeBodyPart(String encoding) {
this.encoding = encoding;
}
public String getEncoding() throws MessagingException {
return this.encoding;
}
public void writeTo(OutputStream os) throws IOException, MessagingException {
LineOutputStream los = null;
if (os instanceof LineOutputStream) {
los = (LineOutputStream)os;
} else {
los = new LineOutputStream(os);
}
Enumeration<String> hdrLines = getAllHeaderLines();
while (hdrLines.hasMoreElements())
los.writeln(hdrLines.nextElement());
los.writeln();
getDataHandler().writeTo(os);
os.flush();
}
protected void updateHeaders() throws MessagingException {
super.updateHeaders();
MimeBodyPart.setEncoding(this, this.encoding);
}
}

View file

@ -0,0 +1,9 @@
package javax.mail.internet;
import java.io.InputStream;
public interface SharedInputStream {
long getPosition();
InputStream newStream(long paramLong1, long paramLong2);
}

View file

@ -0,0 +1,36 @@
package javax.mail.internet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.mail.Session;
class UniqueValue {
private static AtomicInteger id = new AtomicInteger();
public static String getUniqueBoundaryValue() {
StringBuffer s = new StringBuffer();
long hash = (long)s.hashCode();
s.append("----=_Part_").append(id.getAndIncrement()).append("_")
.append(hash).append('.')
.append(System.currentTimeMillis());
return s.toString();
}
public static String getUniqueMessageIDValue(Session ssn) {
String suffix = null;
InternetAddress addr = InternetAddress.getLocalAddress(ssn);
if (addr != null) {
suffix = addr.getAddress();
} else {
suffix = "javamailuser@localhost";
}
int at = suffix.lastIndexOf('@');
if (at >= 0)
suffix = suffix.substring(at);
StringBuffer s = new StringBuffer();
s.append(s.hashCode()).append('.')
.append(id.getAndIncrement()).append('.')
.append(System.currentTimeMillis())
.append(suffix);
return s.toString();
}
}