public static class HTTPException extends IOException { public HTTPException(String s) { super(s); } }
+ public static HTTP stdio = new HTTP("stdio:");
+
// Statics ///////////////////////////////////////////////////////////////////////////////////////////////
// Instance Data ///////////////////////////////////////////////////////////////////////////////////////////////
final String originalUrl; ///< the URL as passed to the original constructor; this is never changed
- URL url = null; ///< the URL to connect to; this is munged when the url is parsed */
+ String url = null; ///< the URL to connect to; this is munged when the url is parsed */
String host = null; ///< the host to connect to
int port = -1; ///< the port to connect on
boolean ssl = false; ///< true if SSL (HTTPS) should be used
// previous call wrecked the socket connection, but we already sent our request, so we can't just retry --
// this could cause the server to receive the request twice, which could be bad (think of the case where the
// server call causes Amazon.com to ship you an item with one-click purchasing).
- if (sock == null)
+ if (in == null)
throw new HTTPException("a previous pipelined call messed up the socket");
Hashtable h = in == null ? null : parseHeaders(in);
if (Log.verbose) Log.info(this, "evaluating PAC script");
String pac = null;
try {
- org.ibex.js.JSArray args = new org.ibex.js.JSArray();
- Object obj = pacFunc.call(url.toString(), url.getHost(), null, null, 2);
+ Object obj = pacFunc.call(url, host, null, null, 2);
if (Log.verbose) Log.info(this, " PAC script returned \"" + obj + "\"");
pac = obj.toString();
} catch (Throwable e) {
}
if (url.startsWith("https:")) {
- this.url = new URL("http" + url.substring(5));
ssl = true;
} else if (!url.startsWith("http:")) {
- throw new MalformedURLException("HTTP only supports http/https urls");
+ throw new IOException("HTTP only supports http/https urls");
+ }
+ if (url.indexOf("://") == -1) throw new IOException("URLs must contain a ://");
+ String temphost = url.substring(url.indexOf("://") + 1);
+ path = temphost.substring(temphost.indexOf('/'));
+ temphost = temphost.substring(0, temphost.indexOf('/'));
+ if (temphost.indexOf(':') != -1) {
+ port = Integer.parseInt(temphost.substring(temphost.indexOf(':')+1));
+ temphost = temphost.substring(0, temphost.indexOf(':'));
} else {
- this.url = new URL(url);
+ port = ssl ? 443 : 80;
}
- if (!skipResolveCheck) resolveAndCheckIfFirewalled(this.url.getHost());
- port = this.url.getPort();
- path = this.url.getFile();
- if (port == -1) port = ssl ? 443 : 80;
- host = this.url.getHost();
+ if (!skipResolveCheck) resolveAndCheckIfFirewalled(temphost);
+ host = temphost;
if (Log.verbose) Log.info(this, "creating HTTP object for connection to " + host + ":" + port);
Proxy pi = Platform.detectProxy();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(originalUrl.equals("stdio:") ?
System.out : sock.getOutputStream()));
if (content != null) {
- pw.print("POST " + path + " HTTP/1.1\r\n");
+ pw.print("POST " + path + " HTTP/1.0\r\n"); // FIXME chunked encoding
int contentLength = content.substring(0, 2).equals("\r\n") ?
content.length() - 2 :
(content.length() - content.indexOf("\r\n\r\n") - 4);
if (h.get("AUTHTYPE").equals("Basic")) {
if (authCache.get(originalUrl) != null) throw new HTTPException("username/password rejected");
- authCache.put(originalUrl, "Basic " + new String(Base64.encode(userInfo.getBytes("US-ASCII"))));
+ authCache.put(originalUrl, "Basic " + new String(Base64.encode(userInfo.getBytes("UTF8"))));
} else if (h.get("AUTHTYPE").equals("Digest")) {
if (authCache.get(originalUrl) != null && !"true".equals(h.get("stale")))
if (style.equals("Basic")) {
Proxy.Authorization.authorization2 =
- "Basic " + new String(Base64.encode(Proxy.Authorization.authorization.getBytes("US-ASCII")));
+ "Basic " + new String(Base64.encode(Proxy.Authorization.authorization.getBytes("UTF8")));
} else if (style.equals("Digest")) {
String A1 = Proxy.Authorization.authorization.substring(0, userInfo.indexOf(':')) + ":" + h.get("realm") + ":" +
if (buflen >= 4 && buf[buflen - 4] == '\r' && buf[buflen - 3] == '\n' &&
buf[buflen - 2] == '\r' && buf[buflen - 1] == '\n')
break;
+ if (buflen >=2 && buf[buflen - 1] == '\n' && buf[buflen - 2] == '\n')
+ break; // nice for people using stdio
if (buflen == buf.length) {
byte[] newbuf = new byte[buf.length * 2];
System.arraycopy(buf, 0, newbuf, 0, buflen);
}
private String H(String s) throws IOException {
- byte[] b = s.getBytes("US-ASCII");
+ byte[] b = s.getBytes("UTF8");
MD5Digest md5 = new MD5Digest();
md5.update(b, 0, b.length);
byte[] out = new byte[md5.getDigestSize()];
/** encapsulates most of the proxy logic; some is shared in HTTP.java */
public static class Proxy {
- public Proxy() { }
-
public String httpProxyHost = null; ///< the HTTP Proxy host to use
public int httpProxyPort = -1; ///< the HTTP Proxy port to use
public String httpsProxyHost = null; ///< seperate proxy for HTTPS
static public Semaphore waitingForUser = new Semaphore();
public static synchronized void getPassword(final String realm, final String style,
- final String proxyIP, String oldAuth) {
+ final String proxyIP, String oldAuth) throws IOException {
// this handles cases where multiple threads hit the proxy auth at the same time -- all but one will block on the
// synchronized keyword. If 'authorization' changed while the thread was blocked, it means that the user entered
if (authorization != oldAuth) return;
if (Log.on) Log.info(Authorization.class, "displaying proxy authorization dialog");
Scheduler.add(new Scheduler.Task() {
- public void perform() throws Exception {
+ public void perform() throws IOException, JSExn {
Box b = new Box();
- Template t = Template.buildTemplate(Stream.getInputStream((JS)Main.builtin.get("org/ibex/builtin/proxy_authorization.ibex")), new Ibex(null));
+ Template t = null;
+ // FIXME
+ //Template.buildTemplate("org/ibex/builtin/proxy_authorization.ibex", Stream.getInputStream((JS)Main.builtin.get("org/ibex/builtin/proxy_authorization.ibex")), new Ibex(null));
t.apply(b);
b.put("realm", realm);
b.put("proxyIP", proxyIP);
* @return The NTLM Response.
*/
public static byte[] getNTLMResponse(String password, byte[] challenge)
- throws Exception {
+ throws UnsupportedEncodingException {
byte[] ntlmHash = ntlmHash(password);
return lmResponse(ntlmHash, challenge);
}
* @return The LM Response.
*/
public static byte[] getLMResponse(String password, byte[] challenge)
- throws Exception {
+ {
byte[] lmHash = lmHash(password);
return lmResponse(lmHash, challenge);
}
*/
public static byte[] getNTLMv2Response(String target, String user,
String password, byte[] targetInformation, byte[] challenge,
- byte[] clientChallenge) throws Exception {
+ byte[] clientChallenge) throws UnsupportedEncodingException {
byte[] ntlmv2Hash = ntlmv2Hash(target, user, password);
byte[] blob = createBlob(targetInformation, clientChallenge);
return lmv2Response(ntlmv2Hash, blob, challenge);
*/
public static byte[] getLMv2Response(String target, String user,
String password, byte[] challenge, byte[] clientChallenge)
- throws Exception {
+ throws UnsupportedEncodingException {
byte[] ntlmv2Hash = ntlmv2Hash(target, user, password);
return lmv2Response(ntlmv2Hash, clientChallenge, challenge);
}
* the client challenge, null-padded to 24 bytes.
*/
public static byte[] getNTLM2SessionResponse(String password,
- byte[] challenge, byte[] clientChallenge) throws Exception {
+ byte[] challenge, byte[] clientChallenge) throws UnsupportedEncodingException {
byte[] ntlmHash = ntlmHash(password);
MD5Digest md5 = new MD5Digest();
md5.update(challenge, 0, challenge.length);
* @return The LM Hash of the given password, used in the calculation
* of the LM Response.
*/
- private static byte[] lmHash(String password) throws Exception {
+ private static byte[] lmHash(String password) {
/*
- byte[] oemPassword = password.toUpperCase().getBytes("US-ASCII");
+ byte[] oemPassword = password.toUpperCase().getBytes("UTF8");
int length = java.lang.Math.min(oemPassword.length, 14);
byte[] keyBytes = new byte[14];
System.arraycopy(oemPassword, 0, keyBytes, 0, length);
Key lowKey = createDESKey(keyBytes, 0);
Key highKey = createDESKey(keyBytes, 7);
- byte[] magicConstant = "KGS!@#$%".getBytes("US-ASCII");
+ byte[] magicConstant = "KGS!@#$%".getBytes("UTF8");
Cipher des = Cipher.getInstance("DES/ECB/NoPadding");
des.init(Cipher.ENCRYPT_MODE, lowKey);
byte[] lowHash = des.doFinal(magicConstant);
* @return The NTLM Hash of the given password, used in the calculation
* of the NTLM Response and the NTLMv2 and LMv2 Hashes.
*/
- private static byte[] ntlmHash(String password) throws Exception {
+ private static byte[] ntlmHash(String password) throws UnsupportedEncodingException {
byte[] unicodePassword = password.getBytes("UnicodeLittleUnmarked");
MD4Digest md4 = new MD4Digest();
md4.update(unicodePassword, 0, unicodePassword.length);
* and LMv2 Responses.
*/
private static byte[] ntlmv2Hash(String target, String user,
- String password) throws Exception {
+ String password) throws UnsupportedEncodingException {
byte[] ntlmHash = ntlmHash(password);
String identity = user.toUpperCase() + target.toUpperCase();
return hmacMD5(identity.getBytes("UnicodeLittleUnmarked"), ntlmHash);
* hash).
*/
private static byte[] lmResponse(byte[] hash, byte[] challenge)
- throws Exception {
+ {
/*
byte[] keyBytes = new byte[21];
System.arraycopy(hash, 0, keyBytes, 0, 16);
* client data).
*/
private static byte[] lmv2Response(byte[] hash, byte[] clientData,
- byte[] challenge) throws Exception {
+ byte[] challenge) {
byte[] data = new byte[challenge.length + clientData.length];
System.arraycopy(challenge, 0, data, 0, challenge.length);
System.arraycopy(clientData, 0, data, challenge.length,
*
* @return The HMAC-MD5 hash of the given data.
*/
- private static byte[] hmacMD5(byte[] data, byte[] key) throws Exception {
+ private static byte[] hmacMD5(byte[] data, byte[] key) {
byte[] ipad = new byte[64];
byte[] opad = new byte[64];
for (int i = 0; i < 64; i++) {