377 lines
10 KiB
Java
377 lines
10 KiB
Java
|
|
package javax.mail;
|
||
|
|
|
||
|
|
import java.io.ByteArrayOutputStream;
|
||
|
|
import java.io.IOException;
|
||
|
|
import java.io.OutputStreamWriter;
|
||
|
|
import java.io.UnsupportedEncodingException;
|
||
|
|
import java.net.InetAddress;
|
||
|
|
import java.net.MalformedURLException;
|
||
|
|
import java.net.URL;
|
||
|
|
import java.net.UnknownHostException;
|
||
|
|
import java.util.BitSet;
|
||
|
|
import java.util.Locale;
|
||
|
|
|
||
|
|
public class URLName {
|
||
|
|
protected String fullURL;
|
||
|
|
|
||
|
|
private String protocol;
|
||
|
|
|
||
|
|
private String username;
|
||
|
|
|
||
|
|
private String password;
|
||
|
|
|
||
|
|
private String host;
|
||
|
|
|
||
|
|
private InetAddress hostAddress;
|
||
|
|
|
||
|
|
private boolean hostAddressKnown = false;
|
||
|
|
|
||
|
|
private int port = -1;
|
||
|
|
|
||
|
|
private String file;
|
||
|
|
|
||
|
|
private String ref;
|
||
|
|
|
||
|
|
private int hashCode = 0;
|
||
|
|
|
||
|
|
private static boolean doEncode = true;
|
||
|
|
|
||
|
|
static {
|
||
|
|
try {
|
||
|
|
doEncode = !Boolean.getBoolean("mail.URLName.dontencode");
|
||
|
|
} catch (Exception e) {}
|
||
|
|
}
|
||
|
|
|
||
|
|
public URLName(String protocol, String host, int port, String file, String username, String password) {
|
||
|
|
this.protocol = protocol;
|
||
|
|
this.host = host;
|
||
|
|
this.port = port;
|
||
|
|
int refStart;
|
||
|
|
if (file != null && (refStart = file.indexOf('#')) != -1) {
|
||
|
|
this.file = file.substring(0, refStart);
|
||
|
|
this.ref = file.substring(refStart + 1);
|
||
|
|
} else {
|
||
|
|
this.file = file;
|
||
|
|
this.ref = null;
|
||
|
|
}
|
||
|
|
this.username = doEncode ? encode(username) : username;
|
||
|
|
this.password = doEncode ? encode(password) : password;
|
||
|
|
}
|
||
|
|
|
||
|
|
public URLName(URL url) {
|
||
|
|
this(url.toString());
|
||
|
|
}
|
||
|
|
|
||
|
|
public URLName(String url) {
|
||
|
|
parseString(url);
|
||
|
|
}
|
||
|
|
|
||
|
|
public String toString() {
|
||
|
|
if (this.fullURL == null) {
|
||
|
|
StringBuffer tempURL = new StringBuffer();
|
||
|
|
if (this.protocol != null) {
|
||
|
|
tempURL.append(this.protocol);
|
||
|
|
tempURL.append(":");
|
||
|
|
}
|
||
|
|
if (this.username != null || this.host != null) {
|
||
|
|
tempURL.append("//");
|
||
|
|
if (this.username != null) {
|
||
|
|
tempURL.append(this.username);
|
||
|
|
if (this.password != null) {
|
||
|
|
tempURL.append(":");
|
||
|
|
tempURL.append(this.password);
|
||
|
|
}
|
||
|
|
tempURL.append("@");
|
||
|
|
}
|
||
|
|
if (this.host != null)
|
||
|
|
tempURL.append(this.host);
|
||
|
|
if (this.port != -1) {
|
||
|
|
tempURL.append(":");
|
||
|
|
tempURL.append(Integer.toString(this.port));
|
||
|
|
}
|
||
|
|
if (this.file != null)
|
||
|
|
tempURL.append("/");
|
||
|
|
}
|
||
|
|
if (this.file != null)
|
||
|
|
tempURL.append(this.file);
|
||
|
|
if (this.ref != null) {
|
||
|
|
tempURL.append("#");
|
||
|
|
tempURL.append(this.ref);
|
||
|
|
}
|
||
|
|
this.fullURL = tempURL.toString();
|
||
|
|
}
|
||
|
|
return this.fullURL;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected void parseString(String url) {
|
||
|
|
this.protocol = this.file = this.ref = this.host = this.username = this.password = null;
|
||
|
|
this.port = -1;
|
||
|
|
int len = url.length();
|
||
|
|
int protocolEnd = url.indexOf(':');
|
||
|
|
if (protocolEnd != -1)
|
||
|
|
this.protocol = url.substring(0, protocolEnd);
|
||
|
|
if (url.regionMatches(protocolEnd + 1, "//", 0, 2)) {
|
||
|
|
int portindex;
|
||
|
|
String fullhost = null;
|
||
|
|
int fileStart = url.indexOf('/', protocolEnd + 3);
|
||
|
|
if (fileStart != -1) {
|
||
|
|
fullhost = url.substring(protocolEnd + 3, fileStart);
|
||
|
|
if (fileStart + 1 < len) {
|
||
|
|
this.file = url.substring(fileStart + 1);
|
||
|
|
} else {
|
||
|
|
this.file = "";
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
fullhost = url.substring(protocolEnd + 3);
|
||
|
|
}
|
||
|
|
int i = fullhost.indexOf('@');
|
||
|
|
if (i != -1) {
|
||
|
|
String fulluserpass = fullhost.substring(0, i);
|
||
|
|
fullhost = fullhost.substring(i + 1);
|
||
|
|
int passindex = fulluserpass.indexOf(':');
|
||
|
|
if (passindex != -1) {
|
||
|
|
this.username = fulluserpass.substring(0, passindex);
|
||
|
|
this.password = fulluserpass.substring(passindex + 1);
|
||
|
|
} else {
|
||
|
|
this.username = fulluserpass;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (fullhost.length() > 0 && fullhost.charAt(0) == '[') {
|
||
|
|
portindex = fullhost.indexOf(':', fullhost.indexOf(']'));
|
||
|
|
} else {
|
||
|
|
portindex = fullhost.indexOf(':');
|
||
|
|
}
|
||
|
|
if (portindex != -1) {
|
||
|
|
String portstring = fullhost.substring(portindex + 1);
|
||
|
|
if (portstring.length() > 0)
|
||
|
|
try {
|
||
|
|
this.port = Integer.parseInt(portstring);
|
||
|
|
} catch (NumberFormatException nfex) {
|
||
|
|
this.port = -1;
|
||
|
|
}
|
||
|
|
this.host = fullhost.substring(0, portindex);
|
||
|
|
} else {
|
||
|
|
this.host = fullhost;
|
||
|
|
}
|
||
|
|
} else if (protocolEnd + 1 < len) {
|
||
|
|
this.file = url.substring(protocolEnd + 1);
|
||
|
|
}
|
||
|
|
int refStart;
|
||
|
|
if (this.file != null && (refStart = this.file.indexOf('#')) != -1) {
|
||
|
|
this.ref = this.file.substring(refStart + 1);
|
||
|
|
this.file = this.file.substring(0, refStart);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public int getPort() {
|
||
|
|
return this.port;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String getProtocol() {
|
||
|
|
return this.protocol;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String getFile() {
|
||
|
|
return this.file;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String getRef() {
|
||
|
|
return this.ref;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String getHost() {
|
||
|
|
return this.host;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String getUsername() {
|
||
|
|
return doEncode ? decode(this.username) : this.username;
|
||
|
|
}
|
||
|
|
|
||
|
|
public String getPassword() {
|
||
|
|
return doEncode ? decode(this.password) : this.password;
|
||
|
|
}
|
||
|
|
|
||
|
|
public URL getURL() throws MalformedURLException {
|
||
|
|
return new URL(getProtocol(), getHost(), getPort(), getFile());
|
||
|
|
}
|
||
|
|
|
||
|
|
public boolean equals(Object obj) {
|
||
|
|
if (!(obj instanceof URLName))
|
||
|
|
return false;
|
||
|
|
URLName u2 = (URLName)obj;
|
||
|
|
if (this.protocol != u2.protocol && (this.protocol == null ||
|
||
|
|
!this.protocol.equals(u2.protocol)))
|
||
|
|
return false;
|
||
|
|
InetAddress a1 = getHostAddress(), a2 = u2.getHostAddress();
|
||
|
|
if (a1 != null && a2 != null) {
|
||
|
|
if (!a1.equals(a2))
|
||
|
|
return false;
|
||
|
|
} else if (this.host != null && u2.host != null) {
|
||
|
|
if (!this.host.equalsIgnoreCase(u2.host))
|
||
|
|
return false;
|
||
|
|
} else if (this.host != u2.host) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (this.username != u2.username && (this.username == null ||
|
||
|
|
!this.username.equals(u2.username)))
|
||
|
|
return false;
|
||
|
|
String f1 = (this.file == null) ? "" : this.file;
|
||
|
|
String f2 = (u2.file == null) ? "" : u2.file;
|
||
|
|
if (!f1.equals(f2))
|
||
|
|
return false;
|
||
|
|
if (this.port != u2.port)
|
||
|
|
return false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int hashCode() {
|
||
|
|
if (this.hashCode != 0)
|
||
|
|
return this.hashCode;
|
||
|
|
if (this.protocol != null)
|
||
|
|
this.hashCode += this.protocol.hashCode();
|
||
|
|
InetAddress addr = getHostAddress();
|
||
|
|
if (addr != null) {
|
||
|
|
this.hashCode += addr.hashCode();
|
||
|
|
} else if (this.host != null) {
|
||
|
|
this.hashCode += this.host.toLowerCase(Locale.ENGLISH).hashCode();
|
||
|
|
}
|
||
|
|
if (this.username != null)
|
||
|
|
this.hashCode += this.username.hashCode();
|
||
|
|
if (this.file != null)
|
||
|
|
this.hashCode += this.file.hashCode();
|
||
|
|
this.hashCode += this.port;
|
||
|
|
return this.hashCode;
|
||
|
|
}
|
||
|
|
|
||
|
|
private synchronized InetAddress getHostAddress() {
|
||
|
|
if (this.hostAddressKnown)
|
||
|
|
return this.hostAddress;
|
||
|
|
if (this.host == null)
|
||
|
|
return null;
|
||
|
|
try {
|
||
|
|
this.hostAddress = InetAddress.getByName(this.host);
|
||
|
|
} catch (UnknownHostException ex) {
|
||
|
|
this.hostAddress = null;
|
||
|
|
}
|
||
|
|
this.hostAddressKnown = true;
|
||
|
|
return this.hostAddress;
|
||
|
|
}
|
||
|
|
|
||
|
|
static BitSet dontNeedEncoding = new BitSet(256);
|
||
|
|
|
||
|
|
static final int caseDiff = 32;
|
||
|
|
|
||
|
|
static {
|
||
|
|
for (int k = 97; k <= 122; k++)
|
||
|
|
dontNeedEncoding.set(k);
|
||
|
|
for (int j = 65; j <= 90; j++)
|
||
|
|
dontNeedEncoding.set(j);
|
||
|
|
for (int i = 48; i <= 57; i++)
|
||
|
|
dontNeedEncoding.set(i);
|
||
|
|
dontNeedEncoding.set(32);
|
||
|
|
dontNeedEncoding.set(45);
|
||
|
|
dontNeedEncoding.set(95);
|
||
|
|
dontNeedEncoding.set(46);
|
||
|
|
dontNeedEncoding.set(42);
|
||
|
|
}
|
||
|
|
|
||
|
|
static String encode(String s) {
|
||
|
|
if (s == null)
|
||
|
|
return null;
|
||
|
|
for (int i = 0; i < s.length(); i++) {
|
||
|
|
int c = s.charAt(i);
|
||
|
|
if (c == 32 || !dontNeedEncoding.get(c))
|
||
|
|
return _encode(s);
|
||
|
|
}
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static String _encode(String s) {
|
||
|
|
int maxBytesPerChar = 10;
|
||
|
|
StringBuffer out = new StringBuffer(s.length());
|
||
|
|
ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar);
|
||
|
|
OutputStreamWriter writer = new OutputStreamWriter(buf);
|
||
|
|
for (int i = 0; i < s.length(); i++) {
|
||
|
|
int c = s.charAt(i);
|
||
|
|
if (dontNeedEncoding.get(c)) {
|
||
|
|
if (c == 32)
|
||
|
|
c = 43;
|
||
|
|
out.append((char)c);
|
||
|
|
} else {
|
||
|
|
try {
|
||
|
|
writer.write(c);
|
||
|
|
writer.flush();
|
||
|
|
} catch (IOException e) {
|
||
|
|
buf.reset();
|
||
|
|
}
|
||
|
|
byte[] ba = buf.toByteArray();
|
||
|
|
for (int j = 0; j < ba.length; j++) {
|
||
|
|
out.append('%');
|
||
|
|
char ch = Character.forDigit(ba[j] >> 4 & 0xF, 16);
|
||
|
|
if (Character.isLetter(ch))
|
||
|
|
ch = (char)(ch - 32);
|
||
|
|
out.append(ch);
|
||
|
|
ch = Character.forDigit(ba[j] & 0xF, 16);
|
||
|
|
if (Character.isLetter(ch))
|
||
|
|
ch = (char)(ch - 32);
|
||
|
|
out.append(ch);
|
||
|
|
}
|
||
|
|
buf.reset();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return out.toString();
|
||
|
|
}
|
||
|
|
|
||
|
|
static String decode(String s) {
|
||
|
|
if (s == null)
|
||
|
|
return null;
|
||
|
|
if (indexOfAny(s, "+%") == -1)
|
||
|
|
return s;
|
||
|
|
StringBuffer sb = new StringBuffer();
|
||
|
|
for (int i = 0; i < s.length(); i++) {
|
||
|
|
char c = s.charAt(i);
|
||
|
|
switch (c) {
|
||
|
|
case '+':
|
||
|
|
sb.append(' ');
|
||
|
|
break;
|
||
|
|
case '%':
|
||
|
|
try {
|
||
|
|
sb.append((char)Integer.parseInt(
|
||
|
|
s.substring(i + 1, i + 3), 16));
|
||
|
|
} catch (NumberFormatException e) {
|
||
|
|
throw new IllegalArgumentException("Illegal URL encoded value: " +
|
||
|
|
|
||
|
|
s.substring(i, i + 3));
|
||
|
|
}
|
||
|
|
i += 2;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
sb.append(c);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
String result = sb.toString();
|
||
|
|
try {
|
||
|
|
byte[] inputBytes = result.getBytes("8859_1");
|
||
|
|
result = new String(inputBytes);
|
||
|
|
} catch (UnsupportedEncodingException e) {}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|