package com.jbidwatcher.util.http;
/*
* Copyright (c) 2000-2007, CyberFOX Software, Inc. All Rights Reserved.
*
* Developed by mrs (Morgan Schweers)
*/
import com.jbidwatcher.util.config.JConfig;
import com.cyberfox.util.config.Base64;
import com.jbidwatcher.util.ByteBuffer;
import com.jbidwatcher.util.Constants;
import com.jbidwatcher.util.Parameters;
import com.jbidwatcher.util.StringTools;
import java.net.*;
import java.io.*;
import java.util.Map;
import java.util.zip.GZIPInputStream;
public class Http implements HttpInterface {
private String mUsername = null;
private String mPassword = null;
private static HttpInterface sInstance = new Http();
public static HttpInterface net() { return sInstance; }
public void setAuthInfo(String user, String pass) {
mUsername = user;
mPassword = pass;
}
private void setConnectionInfo(URLConnection huc) {
if(mUsername != null && mPassword != null) {
huc.setRequestProperty("Authorization", "Basic " + Base64.encodeString(mUsername + ':' + mPassword, false));
}
setConnectionProxyInfo(huc);
}
private void setConnectionProxyInfo(URLConnection huc) {
if(JConfig.queryConfiguration("proxyfirewall", "none").equals("proxy")) {
String proxyHost = JConfig.queryConfiguration("proxy.host", null);
if(proxyHost != null) {
String user = JConfig.queryConfiguration("proxy.user", null);
String pass = JConfig.queryConfiguration("proxy.pass", null);
System.setProperty("http.proxyUser", user);
System.setProperty("http.proxyPassword", pass);
if (user != null && pass != null) {
String str = user + ':' + pass;
String encoded = "Basic " + Base64.encodeString(str);
huc.setRequestProperty("Proxy-Authorization", encoded);
}
}
}
}
public URLConnection postFormPage(String url, String cgiData, String cookie, String referer, boolean followRedirects) {
URLConnection huc;
try {
if(JConfig.queryConfiguration("debug.urls", "false").equals("true")) {
JConfig.log().logDebug("postFormPage: " + url);
}
URL authURL = JConfig.getURL(url);
huc = authURL.openConnection();
setConnectionInfo(huc);
huc.setDoOutput(true);
if(huc instanceof HttpURLConnection) {
HttpURLConnection conn = (HttpURLConnection)huc;
conn.setRequestMethod("POST");
if(!followRedirects) conn.setInstanceFollowRedirects(false);
}
if(JConfig.queryConfiguration("debug.uber", "false").equals("true") && JConfig.debugging) {
dumpFormHeaders(System.err, cgiData, cookie);
}
huc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
huc.setRequestProperty("Content-Length", Integer.toString(cgiData.length()));
setAgentAndEncoding(huc);
if(referer != null) huc.setRequestProperty("Referer", referer);
if(cookie != null) {
huc.setRequestProperty("Cookie", cookie);
}
PrintStream obw = new PrintStream(huc.getOutputStream());
obw.print(cgiData);
obw.close();
} catch(ConnectException ce) {
JConfig.log().logMessage("postFormPage: " + ce);
huc = null;
} catch(Exception e) {
JConfig.log().handleException("postFormPage: " + e, e);
huc = null;
}
return(huc);
}
private static void dumpFormHeaders(PrintStream out, String cgiData, String cookie) {
if(cgiData != null) {
out.println("Content-Type: application/x-www-form-urlencoded");
out.println("Content-Length: " + Integer.toString(cgiData.length()));
out.println("User-Agent: " + Constants.FAKE_BROWSER);
out.println("Cookie: " + cookie);
} else {
out.println("CGI Data is null!");
}
}
private void setAgentAndEncoding(URLConnection uc) {
// We fake our user-agent, since some auction servers only let
// you bid/read if we are a 'supported' browser.
uc.setRequestProperty("User-Agent", Constants.FAKE_BROWSER);
uc.setRequestProperty("Accept-Encoding", "gzip");
}
public URLConnection makeRequest(URL source, String cookie) throws java.io.IOException {
if(JConfig.queryConfiguration("debug.urls", "false").equals("true")) {
JConfig.log().logDebug("makeRequest: " + source.toString());
}
URLConnection uc = source.openConnection();
setConnectionInfo(uc);
if(cookie != null) {
uc.setRequestProperty("Cookie", cookie);
}
setAgentAndEncoding(uc);
return uc;
}
public ByteBuffer getURL(URL url) {
return getURL(url, null);
}
/**
* @brief Retrieve data from HTTP in raw byte form.
*
* @param url - The URL of the raw data to retrieve.
* @param inCookie - Any cookie needed to be passed along.
*
* @return - A result with raw data and the length.
*/
private ByteBuffer getURL(URL url, String inCookie) {
ByteBuffer rval;
try {
URLConnection uc = makeRequest(url, inCookie);
rval = receiveData(uc);
} catch(FileNotFoundException fnfe) {
// It'd be great if we could pass along something that said, 'not here, never will be'.
rval = null;
} catch(IOException e) {
// Mostly ignore HTTP 504 error, it's just a temporary 'gateway down' error.
if(e.getMessage().indexOf("HTTP response code: 504")==-1) {
JConfig.log().handleException("Error loading data URL (" + url.toString() + ')', e);
} else {
JConfig.log().logMessage("HTTP 504 error loading URL (" + url.toString() + ')');
}
rval = null;
}
return rval;
}
/**
* @brief Retrieve raw data from an already existing URL connection.
*
* @param uc - The URLConnection to pull the data from.
*
* @return - A structure containing the raw data and the length.
* @throws java.io.IOException if an error occurs while reading the data.
*/
private ByteBuffer receiveData(URLConnection uc) throws IOException {
InputStream is = uc.getInputStream();
if("gzip".equals(uc.getContentEncoding())) {
is = new GZIPInputStream(is);
}
return receiveStream(is);
}
/**
* Receive all the data available on an InputStream. Sadly, over the
* network this typically reads 1460 bytes at a time (MTU-TCP/IP overhead),
* at about 22ms/read. This means a 100K page loads in about 1.5 seconds. :(
*
* @param is - The InputStream to read from.
* @return - A ByteBuffer containing the data read from the InputStream.
* @throws IOException - If any problems occur while reading.
*/
private ByteBuffer receiveStream(InputStream is) throws IOException {
int curMax = 111821; // A prime; no good reason.
byte[] mainBuf = new byte[curMax];
int count = is.read(mainBuf, 0, curMax);
int offset = 0;
while(count != -1) {
if(offset+count == curMax) {
curMax *= 3;
byte[] tmp = new byte[curMax];
System.arraycopy(mainBuf, 0, tmp, 0, offset+count);
mainBuf = tmp;
}
offset += count;
try {
count = is.read(mainBuf, offset, curMax-offset);
} catch(EOFException badEnd) {
JConfig.log().logDebug("Got a bad end of compressed input stream.");
count = -1;
}
}
is.close();
return new ByteBuffer(mainBuf, offset);
}
public StringBuffer get(String url) {
try {
HttpURLConnection huc = (HttpURLConnection)getPage(url);
InputStream is = getStream(huc);
if("gzip".equals(huc.getContentEncoding())) {
is = new GZIPInputStream(is);
}
ByteBuffer results = receiveStream(is);
StringBuffer sb = convertByteBufferToStringBuffer(huc, results);
if((huc.getResponseCode() / 100) > 3) {
JConfig.log().logMessage("Failed to get " + url + ": " + sb);
return null;
}
return sb;
} catch (IOException ioe) {
JConfig.log().logDebug("Got an exception reading " + url + ": " + ioe.getMessage());
return null;
}
}
public StringBuffer receivePage(URLConnection uc) throws IOException {
if(uc == null) return null;
ByteBuffer buff = receiveData(uc);
return convertByteBufferToStringBuffer(uc, buff);
}
private StringBuffer convertByteBufferToStringBuffer(URLConnection uc, ByteBuffer buff) throws UnsupportedEncodingException {
if(buff == null) return null;
String charset = uc.getContentType();
if(charset != null && charset.matches(".*charset=([^;]*).*")) {
charset = charset.replaceFirst(".*charset=([^;]*).*", "$1");
return new StringBuffer(new String(buff.getData(), 0, buff.getLength(), charset));
}
return new StringBuffer(new String(buff.getData(), 0, buff.getLength()));
}
/**
* Simplest request, load a URL, no cookie, no referer, follow redirects blindly.
*
* @param url - The URL to load.
* @return - A URLConnection usable to retrieve the page requested.
*/
public URLConnection getPage(String url) {
return(getPage(url, null, null, true));
}
public URLConnection getPage(String url, String cookie, String referer, boolean followRedirects) {
HttpURLConnection huc;
try {
if(JConfig.queryConfiguration("debug.urls", "false").equals("true")) {
JConfig.log().logDebug("getPage: " + url);
}
URL authURL = JConfig.getURL(url);
URLConnection uc = authURL.openConnection();
if(!(uc instanceof HttpURLConnection)) {
return uc;
}
huc = (HttpURLConnection)uc;
huc.setInstanceFollowRedirects(followRedirects);
setConnectionInfo(huc);
setAgentAndEncoding(huc);
if(referer != null) huc.setRequestProperty("Referer", referer);
if(cookie != null) huc.setRequestProperty("Cookie", cookie);
} catch(Exception e) {
JConfig.log().handleException("getPage: " + e, e);
huc = null;
}
return(huc);
}
public String putTo(String url, String sb) {
HttpURLConnection huc = null;
String result = null;
try {
huc = (HttpURLConnection) JConfig.getURL(url).openConnection();
setConnectionInfo(huc);
huc.setRequestProperty("Content-Type", "application/octet-stream");
huc.setRequestProperty("Content-Length", Integer.toString(sb.length() - 1));
huc.setRequestProperty("User-Agent", Constants.FAKE_BROWSER);
huc.setRequestMethod("PUT");
huc.setDoOutput(true);
huc.getOutputStream().write(sb.getBytes());
result = StringTools.cat(huc.getInputStream());
} catch (MalformedURLException murle) {
JConfig.log().logMessage("Invalid URL!? (" + url + "): " + murle.getMessage());
} catch (IOException ioe) {
try { if(huc != null) result = StringTools.cat(huc.getErrorStream()); } catch (Exception ignored) { }
}
return result;
}
public String postTo(String url, Parameters params) {
StringBuffer postData = null;
try {
postData = createCGIData(params);
URLConnection uc = postFormPage(url, postData.toString(), null, null, false);
StringBuffer sb = receivePage(uc);
return sb == null ? null : sb.toString();
} catch (IOException e) {
int length = 0;
if (postData != null) length = postData.length();
JConfig.log().logDebug("Couldn't send params (length: " + length + ") to " + url);
JConfig.log().logDebug(e.getMessage());
return null;
}
}
private static StringBuffer createCGIData(Parameters data) throws UnsupportedEncodingException {
StringBuffer postData = new StringBuffer();
boolean first = true;
for (Map.Entry<Object, Object> param : data.entrySet()) {
Object key = param.getKey();
Object value = param.getValue();
if (value != null) {
if (!first)
postData.append('&');
else
first = false;
postData.append(key.toString());
postData.append('=');
postData.append(URLEncoder.encode(value.toString(), "UTF-8"));
}
}
return postData;
}
public InputStream getStream(HttpURLConnection huc) {
if(huc == null) return null;
InputStream rval;
try {
int status = huc.getResponseCode();
if (status / 100 == 4) {
rval = huc.getErrorStream();
} else if (status / 100 == 3) {
String location = huc.getHeaderField("Location");
huc = (HttpURLConnection)getPage(location);
rval = huc.getInputStream();
} else {
rval = huc.getInputStream();
}
} catch (IOException e) {
JConfig.log().logDebug("Error getting the stream from " + huc.getURL() + ": " + e.getMessage());
rval = null;
}
return rval;
}
}