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 java.net.*;
import java.util.*;
import java.io.IOException;
public class CookieJar {
private Map<String, Cookie> mCookies;
private boolean mIgnoreRedirectCookies = false;
private final static boolean sUberDebug = false;
public CookieJar() {
mCookies = new TreeMap<String, Cookie>();
}
public Cookie getCookie(String keyName) {
return mCookies.get(keyName);
}
public String dump() {
StringBuffer rval = new StringBuffer();
for(String cookieName : mCookies.keySet()) {
Cookie value = mCookies.get(cookieName);
rval.append(cookieName).append(": ").append(value.getValue()).append('\n');
}
return rval.toString();
}
public static class CookieException extends Exception {
public CookieException(String text, Throwable trigger) {
super(text, trigger);
}
}
public static class CookieRedirectException extends RuntimeException {
public CookieRedirectException(String text, Throwable trigger) {
super(text, trigger);
}
}
/**
* Get all the cookies and the page data itself, using post or get.
*
* @param page - The URL to retrieve.
* @param body - The body of the POST to send, if we want to do a POST operation.
* @param referer - The URL that referred us to this page (can be null).
* @return - A StringBuffer containing the data at the provided URL, or returned from the POST operation.
*
* @throws com.jbidwatcher.util.http.CookieJar.CookieException - If the connection is refused.
*/
public StringBuffer getPage(String page, String body, String referer) throws CookieException {
URLConnection uc = connect(page, body, referer, body != null, null);
if(uc == null) return null;
StringBuffer sb = null;
try {
sb = Http.net().receivePage(uc);
} catch(ConnectException ce) {
logException(page, ce);
if(ce.toString().indexOf("Connection refused") != -1) {
throw new CookieException("Connection refused", ce);
}
} catch(IOException e) {
logException(page, e);
return null;
}
return sb;
}
private void logException(String pageName, Exception e) {
int qLoc = pageName.indexOf('?');
String errmsg = "Error loading page: ";
if(qLoc == -1) {
errmsg += pageName;
} else {
errmsg += pageName.substring(0,qLoc);
}
JConfig.log().handleException(errmsg, e);
}
/**
* Retrieve any cookies from the provided page via GET or POST, but only return
* the URLConnection letting the caller do what they want to with it.
*
* @param page - The page to load.
* @return - A URLConnection connected to the response from the server for the given request.
*/
public URLConnection connect(String page) {
return connect(page, null, null, false, null);
}
private Map<String, Integer> mRedirections;
public URLConnection connect(String page, String body, String referer, boolean post, List<String> pages) {
URLConnection rval;
mRedirections = new HashMap<String, Integer>();
rval = internal_connect(page, body, referer, post, pages);
mRedirections = null;
return rval;
}
private URLConnection internal_connect(String page, String body, String referer, boolean post, List<String> pages) {
if(handleInfiniteRedirection(page)) {
// If we're posting, and we hit an infloop, maybe we don't want to re-submit the data...
if(post) {
post = false;
body = null;
} else {
throw new CookieRedirectException("Looped redirect to " + page, null);
}
}
if(pages != null) pages.add(page);
HttpURLConnection uc = initiateRequest(post, page, body, referer);
if(uc != null) {
String redirect = handleRedirect(uc, page);
if(redirect != null) {
if (JConfig.debugging()) {
// Don't log passwords in redirection messages.
if(!page.contains("pass")) JConfig.log().logMessage("Redirecting from: " + page);
if(!page.contains("pass")) JConfig.log().logMessage("Redirecting to: " + redirect);
try {
if(JConfig.queryConfiguration("debug.urls", "false").equals("true")) {
JConfig.log().logMessage("Content: " + Http.net().receivePage(uc));
}
} catch (IOException ignored) {
// If there's no content or it's an unrecognized type, ignore it.
}
}
return internal_connect(redirect, body, referer, post, pages);
}
}
return uc;
}
private boolean handleInfiniteRedirection(String page) {
Integer pageCount = mRedirections.get(page);
if(pageCount == null) pageCount = 0;
if(pageCount >= 2) return true;
mRedirections.put(page, pageCount+1);
return false;
}
private String handleRedirect(HttpURLConnection uc, String pageName) {
int i = 1;
String redirect = null;
String nextKey;
do {
nextKey = uc.getHeaderFieldKey(i);
if(nextKey != null) {
if(sUberDebug) {
JConfig.log().logDebug(nextKey+": " + uc.getHeaderField(i));
}
// If we're redirected, shortcut to loading the new page.
if(nextKey.startsWith("Location") ||
nextKey.startsWith("location")) {
redirect = uc.getHeaderField(i);
redirect = stripQuotedAmpersands(redirect);
if(!redirect.startsWith("http")) {
redirect = fixRelativeRedirect(pageName, redirect);
}
}
if(nextKey.startsWith("Set-Cookie") ||
nextKey.startsWith("Set-cookie")) {
Cookie newCookie = new Cookie(uc.getHeaderField(i));
mCookies.put(newCookie.getKey(), newCookie);
}
}
i++;
} while(nextKey != null);
return redirect;
}
private String fixRelativeRedirect(String pageName, String redirect) {
String slash = "";
int serverEnd = pageName.indexOf(".com/");
if(!redirect.startsWith("/")) {
slash = "/";
}
String prefix;
if(serverEnd == -1) {
prefix = pageName;
} else {
prefix = pageName.substring(0, serverEnd+4);
}
redirect = prefix + slash + redirect;
return redirect;
}
private String stripQuotedAmpersands(String redirect) {
int amploc = redirect.indexOf("&");
while(amploc != -1) {
redirect = redirect.substring(0, amploc) + "&" +
redirect.substring(amploc+5);
amploc = redirect.indexOf("&");
}
return redirect;
}
private HttpURLConnection initiateRequest(boolean post, String sendRequest, String cgi, String referer) {
URLConnection uc;
String cookies = mCookies.isEmpty() ? null : this.toString();
if(post) {
uc = Http.net().postFormPage(sendRequest, cgi, cookies, referer, mIgnoreRedirectCookies);
} else {
uc = Http.net().getPage(sendRequest, cookies, referer, mIgnoreRedirectCookies);
}
return (HttpURLConnection)uc;
}
public String toString() {
boolean firstThrough = true;
StringBuffer outBuf = null;
for (Cookie cookie : mCookies.values()) {
if (cookie.getValue().length() != 0) {
if (!firstThrough) {
outBuf.append("; ");
} else {
firstThrough = false;
outBuf = new StringBuffer();
}
outBuf.append(cookie.getKey());
outBuf.append("=");
outBuf.append(cookie.getValue());
}
}
if(outBuf != null) {
return outBuf.toString();
} else {
return null;
}
}
}