org.htmlparser.http.ConnectionManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bboss-htmlparser Show documentation
Show all versions of bboss-htmlparser Show documentation
bboss is a j2ee framework include aop/ioc,mvc,persistent,taglib,rpc,event ,bean-xml serializable and so on.http://www.bbossgroups.com
The newest version!
// HTMLParser Library $Name: v1_5 $ - A java-based parser for HTML
// http://sourceforge.org/projects/htmlparser
// Copyright (C) 2004 Derrick Oswald
//
// Revision Control Information
//
// $Source: /cvsroot/htmlparser/htmlparser/src/org/htmlparser/http/ConnectionManager.java,v $
// $Author: derrickoswald $
// $Date: 2005/05/15 11:49:04 $
// $Revision: 1.4 $
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
package org.htmlparser.http;
import org.htmlparser.util.ParserException;
import java.io.File;
import java.io.IOException;
import java.net.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
/**
* Handles proxies, password protected URLs and request properties
* including cookies.
*/
public class ConnectionManager
{
/**
* Default Request header fields.
* So far this is just "User-Agent" and "Accept-Encoding".
*/
protected static HashMap mDefaultRequestProperties = new HashMap ();
static
{
mDefaultRequestProperties.put ("User-Agent", "HTMLParser/"
+ org.htmlparser.Parser.VERSION_NUMBER);
mDefaultRequestProperties.put ("Accept-Encoding", "gzip, deflate");
}
/**
* Messages for page not there (404).
*/
private static final String[] FOUR_OH_FOUR =
{
"The web site you seek cannot be located,"
+ " but countless more exist",
"You step in the stream, but the water has moved on."
+ " This page is not here.",
"Yesterday the page existed. Today it does not."
+ " The internet is like that.",
"That page was so big. It might have been very useful."
+ " But now it is gone.",
"Three things are certain: death, taxes and broken links."
+ " Guess which has occured.",
"Chaos reigns within. Reflect, repent and enter the correct URL."
+ " Order shall return.",
"Stay the patient course. Of little worth is your ire."
+ " The page is not found.",
"A non-existant URL reduces your expensive computer to a simple stone.",
"Many people have visited that page."
+ " Today, you are not one of the lucky ones.",
"Cutting the wind with a knife. Bookmarking a URL."
+ " Both are ephemeral.",
};
/**
* Base 64 character translation table.
*/
private static final char[] BASE64_CHAR_TABLE =
("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz0123456789+/").toCharArray ();
/**
* Request header fields.
*/
protected HashMap mRequestProperties;
/**
* The proxy server name.
*/
protected String mProxyHost;
/**
* The proxy port number.
*/
protected int mProxyPort;
/**
* The proxy username name.
*/
protected String mProxyUser;
/**
* The proxy user password.
*/
protected String mProxyPassword;
/**
* The username name for accessing the URL.
*/
protected String mUser;
/**
* The user password for accessing the URL.
*/
protected String mPassword;
/**
* Cookie storage, a HashMap (by site or host) of Lists of Cookies.
* This will be null if cookie processing is disabled (default).
*/
protected HashMap mCookieJar;
/**
* The object to be notified prior to and after each connection.
*/
protected ConnectionMonitor mMonitor;
/**
* Create a connection manager.
*/
public ConnectionManager ()
{
this (getDefaultRequestProperties ());
}
/**
* Create a connection manager with the given connection properties.
* @param properties Name/value pairs to be added to the HTTP request.
*/
public ConnectionManager (HashMap properties)
{
mRequestProperties = properties;
mProxyHost = null;
mProxyPort = 0;
mProxyUser = null;
mProxyPassword = null;
mUser = null;
mPassword = null;
mCookieJar = null;
mMonitor = null;
}
//
// static methods
//
/**
* Get the current default request header properties.
* A String-to-String map of header keys and values.
* These fields are set by the parser when creating a connection.
* @return The default set of request header properties that will
* currently be used.
* @see #mDefaultRequestProperties
* @see #setRequestProperties
*/
public static HashMap getDefaultRequestProperties ()
{
return (mDefaultRequestProperties);
}
/**
* Set the default request header properties.
* A String-to-String map of header keys and values.
* These fields are set by the parser when creating a connection.
* Some of these can be set directly on a URLConnection
,
* i.e. If-Modified-Since is set with setIfModifiedSince(long),
* but since the parser transparently opens the connection on behalf
* of the developer, these properties are not available before the
* connection is fetched. Setting these request header fields affects all
* subsequent connections opened by the parser. For more direct control
* create a URLConnection
massage it the way you want and
* then set it on the parser.
* From
* RFC 2616 Hypertext Transfer Protocol -- HTTP/1.1:
*
* 5.3 Request Header Fields
*
* The request-header fields allow the client to pass additional
* information about the request, and about the client itself, to the
* server. These fields act as request modifiers, with semantics
* equivalent to the parameters on a programming language method
* invocation.
*
* request-header = Accept ; Section 14.1
* | Accept-Charset ; Section 14.2
* | Accept-Encoding ; Section 14.3
* | Accept-Language ; Section 14.4
* | Authorization ; Section 14.8
* | Expect ; Section 14.20
* | From ; Section 14.22
* | Host ; Section 14.23
* | If-Match ; Section 14.24
* | If-Modified-Since ; Section 14.25
* | If-None-Match ; Section 14.26
* | If-Range ; Section 14.27
* | If-Unmodified-Since ; Section 14.28
* | Max-Forwards ; Section 14.31
* | Proxy-Authorization ; Section 14.34
* | Range ; Section 14.35
* | Referer ; Section 14.36
* | TE ; Section 14.39
* | User-Agent ; Section 14.43
*
* Request-header field names can be extended reliably only in
* combination with a change in the protocol version. However, new or
* experimental header fields MAY be given the semantics of request-
* header fields if all parties in the communication recognize them to
* be request-header fields. Unrecognized header fields are treated as
* entity-header fields.
*
* @param properties The new set of default request header properties to
* use. This affects all subsequently created connections.
* @see #mDefaultRequestProperties
* @see #setRequestProperties
*/
public static void setDefaultRequestProperties (HashMap properties)
{
mDefaultRequestProperties = properties;
}
/**
* Gets the request header for the connection.
* This header is generated from the contents of the connection
* and may not be exactly the same as the request that will be sent.
* @param connection The connection to convert into an HTTP request header.
* @return The string that would be sent by the HTTP request.
*/
public static String getRequestHeader (HttpURLConnection connection)
{
// dump it
StringBuilder buffer;
Map map;
String key;
List items;
buffer = new StringBuilder (1024);
buffer.append (connection.getRequestMethod ());
buffer.append (" ");
buffer.append (connection.getURL ());
buffer.append (" HTTP/1.1\n");
map = connection.getRequestProperties ();
for (Iterator iter = map.keySet ().iterator (); iter.hasNext (); )
{
key = (String)iter.next ();
items = (List)map.get (key);
buffer.append (key);
buffer.append (": ");
for (int i = 0; i < items.size (); i++)
{
if (0 != i)
buffer.append (", ");
buffer.append (items.get (i));
}
buffer.append ("\n");
}
return (buffer.toString ());
}
/**
* Gets the response header for the connection.
* Calling this method on an un-connected connection will
* generate an error, as will an attempt to get information
* from a connected but invalid connection.
* This header is generated from the contents of the connection
* and may not be exactly the same as the response that was received.
* @param conn The connection to convert into an HTTP response header.
* @return The string that was sent as the HTTP response.
*/
public static String getResponseHeader (HttpURLConnection conn)
{
// dump it
StringBuilder buffer;
int code;
String message;
String key;
String value;
buffer = new StringBuilder (1024);
try
{
code = conn.getResponseCode ();
if (-1 != code)
{
message = conn.getResponseMessage ();
buffer.append ("HTTP/1.1 ");
buffer.append (code);
buffer.append (" ");
buffer.append (message);
buffer.append ("\n");
for (int i = 0; null != (value = conn.getHeaderField (i)); i++)
{
key = conn.getHeaderFieldKey (i);
if (null != key)
{
buffer.append (key);
buffer.append (": ");
buffer.append (value);
buffer.append ("\n");
}
}
}
}
catch (IOException ioe)
{
buffer.append (ioe.toString ());
}
return (buffer.toString ());
}
/**
* Get the current request header properties.
* A String-to-String map of header keys and values,
* excluding proxy items, cookies and URL authorization.
* @return The request header properties for this connection manager.
*/
public HashMap getRequestProperties ()
{
return (mRequestProperties);
}
/**
* Set the current request properties.
* Replaces the current set of fixed request properties with the given set.
* This does not replace the Proxy-Authorization property which is
* constructed from the values of {@link #setProxyUser}
* and {@link #setProxyPassword} values or the Authorization property
* which is constructed from the {@link #setUser}
* and {@link #setPassword} values. Nor does it replace the
* Cookie property which is constructed from the current cookie jar.
* @param properties The new fixed properties.
*/
public void setRequestProperties (HashMap properties)
{
mRequestProperties = properties;
}
/**
* Get the proxy host name, if any.
* @return Returns the proxy host.
*/
public String getProxyHost ()
{
return (mProxyHost);
}
/**
* Set the proxy host to use.
* @param host The host to use for proxy access.
* Note: You must also set the proxy {@link #setProxyPort port}.
*/
public void setProxyHost (String host)
{
mProxyHost = host;
}
/**
* Get the proxy port number.
* @return Returns the proxy port.
*/
public int getProxyPort ()
{
return (mProxyPort);
}
/**
* Set the proxy port number.
* @param port The proxy port.
* Note: You must also set the proxy {@link #setProxyHost host}.
*/
public void setProxyPort (int port)
{
mProxyPort = port;
}
/**
* Get the user name for proxy authorization, if any.
* @return Returns the proxy user,
* or null
if no proxy authorization is required.
*/
public String getProxyUser ()
{
return (mProxyUser);
}
/**
* Set the user name for proxy authorization.
* @param user The proxy user name.
* Note: You must also set the proxy {@link #setProxyPassword password}.
*/
public void setProxyUser (String user)
{
mProxyUser = user;
}
/**
* Set the proxy user's password.
* @return Returns the proxy password.
*/
public String getProxyPassword ()
{
return (mProxyPassword);
}
/**
* Get the proxy user's password.
* @param password The password for the proxy user.
* Note: You must also set the proxy {@link #setProxyUser user}.
*/
public void setProxyPassword (String password)
{
mProxyPassword = password;
}
/**
* Get the user name to access the URL.
* @return Returns the username that will be used to access the URL,
* or null
if no authorization is required.
*/
public String getUser ()
{
return (mUser);
}
/**
* Set the user name to access the URL.
* @param user The user name for accessing the URL.
* Note: You must also set the {@link #setPassword password}.
*/
public void setUser (String user)
{
mUser = user;
}
/**
* Get the URL users's password.
* @return Returns the URL password.
*/
public String getPassword ()
{
return (mPassword);
}
/**
* Set the URL users's password.
* @param password The password for the URL.
*/
public void setPassword (String password)
{
mPassword = password;
}
/**
* Predicate to determine if cookie processing is currently enabled.
* @return true
if cookies are being processed.
*/
public boolean getCookieProcessingEnabled ()
{
return (null != mCookieJar);
}
/**
* Enables and disabled cookie processing.
* @param enable if true
cookie processing will occur,
* else cookie processing will be turned off.
*/
public void setCookieProcessingEnabled (boolean enable)
{
if (enable)
mCookieJar = (null == mCookieJar) ? new HashMap () : mCookieJar;
else
mCookieJar = null;
}
/**
* Adds a cookie to the cookie jar.
* @param cookie The cookie to add.
* @param domain The domain to use in case the cookie has no domain attribute.
*/
public void setCookie (Cookie cookie, String domain)
{
String path;
List cookies;
Cookie probe;
if (null != cookie.getDomain ())
domain = cookie.getDomain ();
path = cookie.getPath ();
if (null == mCookieJar)
mCookieJar = new HashMap (); // turn on cookie processing
cookies = (List)mCookieJar.get (domain);
if (null != cookies)
{
for (int j = 0; j < cookies.size (); j++)
{
probe = (Cookie)cookies.get (j);
if (probe.getName ().equalsIgnoreCase (cookie.getName ()))
{
// we keep paths sorted most specific to least
if (probe.getPath ().equals (path))
{
cookies.set (j,cookie); // replace
break;
}
else if (path.startsWith (probe.getPath ()))
{
cookies.add (j,cookie);
break;
}
}
}
}
else
{ // new cookie list needed
cookies = new ArrayList ();
cookies.add (cookie);
mCookieJar.put (domain, cookies);
}
}
/**
* Get the monitoring object, if any.
* @return Returns the monitor, or null if none has been assigned.
*/
public ConnectionMonitor getMonitor ()
{
return (mMonitor);
}
/**
* Set the monitoring object.
* @param monitor The monitor to set.
*/
public void setMonitor (ConnectionMonitor monitor)
{
mMonitor = monitor;
}
/**
* Opens a connection using the given url.
* @param url The url to open.
* @return The connection.
* @exception ParserException if an i/o exception occurs accessing the url.
*/
public URLConnection openConnection (URL url)
throws
ParserException
{
Properties sysprops;
HashMap properties;
Iterator enumeration;
String key;
String value;
String set = null; // old proxySet value
String host = null; // old proxyHost value
String port = null; // old proxyPort value
String host2 = null; // old http.proxyHost value
String port2 = null; // old http.proxyPort value
HttpURLConnection http;
String auth;
String encoded;
URLConnection ret;
try
{
try
{
// set up for proxy
if ((null != getProxyHost ()) && (0 != getProxyPort ()))
{
sysprops = System.getProperties ();
set = (String)sysprops.put ("proxySet", "true");
host = (String)sysprops.put ("proxyHost", getProxyHost ());
port = (String)sysprops.put ("proxyPort",
Integer.toString (getProxyPort ()));
// see http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
host2 = (String)sysprops.put ("http.proxyHost",
getProxyHost ());
port2 = (String)sysprops.put ("http.proxyPort",
Integer.toString (getProxyPort ()));
System.setProperties (sysprops);
}
// open the connection... but don't connect yet
ret = url.openConnection ();
if (ret instanceof HttpURLConnection)
{
http = (HttpURLConnection)ret;
// set the fixed request properties
properties = getRequestProperties ();
if (null != properties)
for (enumeration = properties.entrySet().iterator();
enumeration.hasNext();)
{
Map.Entry entry = (Entry) enumeration.next();
key = (String)entry.getKey();
value = (String)entry.getValue();
ret.setRequestProperty (key, value);
}
// set the proxy name and password
if ((null != getProxyUser ())
&& (null != getProxyPassword ()))
{
auth = getProxyUser () + ":" + getProxyPassword ();
encoded = encode (auth.getBytes("ISO-8859-1"));
ret.setRequestProperty ("Proxy-Authorization", encoded);
}
// set the URL name and password
if ((null != getUser ()) && (null != getPassword ()))
{
auth = getUser () + ":" + getPassword ();
encoded = encode (auth.getBytes("ISO-8859-1"));
ret.setRequestProperty ("Authorization",
"Basic " + encoded);
}
// set the cookies based on the url
addCookies (ret);
if (null != getMonitor ())
getMonitor ().preConnect (http);
}
else
http = null;
try
{
ret.connect ();
if (null != http)
{
if (null != getMonitor ())
getMonitor ().postConnect (http);
parseCookies (ret);
}
}
catch (UnknownHostException uhe)
{
int message = (int)(Math.random () * FOUR_OH_FOUR.length);
throw new ParserException (FOUR_OH_FOUR[message], uhe);
}
catch (IOException ioe)
{
throw new ParserException (ioe.getMessage (), ioe);
}
}
finally
{
if ((null != getProxyHost ()) && (0 != getProxyPort ()))
{
sysprops = System.getProperties ();
if (null != set)
sysprops.put ("proxySet", set);
else
sysprops.remove ("proxySet");
if (null != host)
sysprops.put ("proxyHost", host);
else
sysprops.remove ("proxyHost");
if (null != port)
sysprops.put ("proxyPort", port);
else
sysprops.remove ("proxyPort");
if (null != host2)
sysprops.put ("http.proxyHost", host2);
else
sysprops.remove ("http.proxyHost");
if (null != port2)
sysprops.put ("http.proxyPort", port2);
else
sysprops.remove ("http.proxyPort");
System.setProperties (sysprops);
}
}
}
catch (IOException ioe)
{
String msg = "Error in opening a connection to "
+ url.toExternalForm ();
ParserException ex = new ParserException (msg, ioe);
throw ex;
}
return (ret);
}
/**
* Encodes a byte array into BASE64 in accordance with
* RFC 2045.
* @param array The bytes to convert.
* @return A BASE64 encoded string.
*/
public final static String encode (byte[] array)
{
int last; // last byte
int count; // character count
int separators; // line separator count
int length; // length of returned string
char[] encoded; // encoded characters
int left; // bytes left
int end;
int block; // encoding buffer
int r; // shift count
int n; // byte to encode
int index; // index into output array
String ret;
if ((null != array) && (0 != array.length))
{
last = array.length - 1;
count = (last / 3 + 1) << 2;
separators = (count - 1) / 76;
length = count + separators;
encoded = new char[length];
index = 0;
separators = 0;
for (int i = 0; i <= last; i += 3)
{
left = last - i;
end = (left > 1 ? 2 : left);
// collect 1 to 3 bytes to encode
block = 0;
r = 16;
for (int j = 0; j <= end; j++)
{
n = array[i + j];
block += (n < 0 ? n + 256 : n) << r;
r -= 8;
}
// encode into 2-4 chars padding with '=' if no data left
encoded[index++] = BASE64_CHAR_TABLE[(block >>> 18) & 0x3f];
encoded[index++] = BASE64_CHAR_TABLE[(block >>> 12) & 0x3f];
encoded[index++] = left > 0 ?
BASE64_CHAR_TABLE[(block >>> 6) & 0x3f] :
'=';
encoded[index++] = left > 1 ?
BASE64_CHAR_TABLE[block & 0x3f] :
'=';
if ((0 == (index - separators) % 76) && (index < length))
{
encoded[index++] = '\n';
separators += 1;
}
}
ret = new String (encoded);
}
else
ret = "";
return (ret);
}
/**
* Turn spaces into %20.
* ToDo: make this more generic
* (see RFE #1010593 provide URL encoding/decoding utilities).
* @param url The url containing spaces.
* @return The URL with spaces as %20 sequences.
*/
public String fixSpaces (String url)
{
int index;
int length;
char ch;
StringBuilder buffer;
index = url.indexOf (' ');
if (-1 != index)
{
length = url.length ();
buffer = new StringBuilder (length * 3);
buffer.append (url.substring (0, index));
for (int i = index; i < length; i++)
{
ch = url.charAt (i);
if (ch==' ')
buffer.append ("%20");
else
buffer.append (ch);
}
url = buffer.toString ();
}
return (url);
}
/**
* Opens a connection based on a given string.
* The string is either a file, in which case file://localhost
* is prepended to a canonical path derived from the string, or a url that
* begins with one of the known protocol strings, i.e. http://
.
* Embedded spaces are silently converted to %20 sequences.
* @param string The name of a file or a url.
* @return The connection.
* @exception ParserException if the string is not a valid url or file.
*/
public URLConnection openConnection (String string)
throws
ParserException
{
final String prefix = "file://localhost";
String resource;
URL url;
StringBuilder buffer;
URLConnection ret;
try
{
url = new URL (fixSpaces (string));
ret = openConnection (url);
}
catch (MalformedURLException murle)
{ // try it as a file
try
{
File file = new File (string);
resource = file.getCanonicalPath ();
buffer = new StringBuilder (prefix.length ()
+ resource.length ());
buffer.append (prefix);
if (!resource.startsWith ("/"))
buffer.append ("/");
buffer.append (resource);
url = new URL (fixSpaces (buffer.toString ()));
ret = openConnection (url);
}
catch (MalformedURLException murle2)
{
String msg = "Error in opening a connection to " + string;
ParserException ex = new ParserException (msg, murle2);
throw ex;
}
catch (IOException ioe)
{
String msg = "Error in opening a connection to " + string;
ParserException ex = new ParserException (msg, ioe);
throw ex;
}
}
return (ret);
}
/**
* Generate a HTTP cookie header value string from the cookie jar.
*
* The syntax for the header is:
*
* cookie = "Cookie:" cookie-version
* 1*((";" | ",") cookie-value)
* cookie-value = NAME "=" VALUE [";" path] [";" domain]
* cookie-version = "$Version" "=" value
* NAME = attr
* VALUE = value
* path = "$Path" "=" value
* domain = "$Domain" "=" value
*
*
* @param connection The connection being accessed.
* @see RFC 2109
* @see RFC 2396
*/
public void addCookies (URLConnection connection)
{
List list;
URL url;
String host;
String path;
String domain;
if (null != mCookieJar)
{
list = null;
// get the site from the URL
url = connection.getURL ();
host = url.getHost ();
path = url.getPath ();
if (0 == path.length ())
path = "/";
if (null != host)
{ // http://www.objectsdevelopment.com/portal/modules/freecontent/content/javawebserver.html
list = addCookies ((List)mCookieJar.get (host), path, list);
domain = getDomain (host);
if (null != domain)
list = addCookies ((List)mCookieJar.get (domain),
path, list);
else
// maybe it is the domain we're accessing
list = addCookies ((List)mCookieJar.get ("." + host),
path, list);
}
if (null != list)
connection.setRequestProperty ("Cookie",
generateCookieProperty (list));
}
}
/**
* Add qualified cookies from cookies into list.
* @param cookies The list of cookies to check (may be null).
* @param path The path being accessed.
* @param list The list of qualified cookies.
* @return The list of qualified cookies.
*/
protected List addCookies (List cookies, String path, List list)
{
Cookie cookie;
Date expires;
Date now;
if (null != cookies)
{
now = new Date ();
for (int i = 0; i < cookies.size (); i++)
{
cookie = (Cookie)cookies.get (i);
expires = cookie.getExpiryDate ();
if ((null != expires) && expires.before (now))
{
cookies.remove (i);
i--; // dick with the loop variable
}
else
if (path.startsWith (cookie.getPath ()))
{
if (null == list)
list = new ArrayList ();
list.add (cookie);
}
}
}
return (list);
}
/**
* Get the domain from a host.
* @param host The supposed host name.
* @return The domain (with the leading dot),
* or null if the domain cannot be determined.
*/
protected String getDomain (String host)
{
StringTokenizer tokenizer;
int count;
String server;
int length;
boolean ok;
char c;
String ret;
ret = null;
tokenizer = new StringTokenizer (host, ".");
count = tokenizer.countTokens ();
if (3 <= count)
{
// have at least two dots,
// check if we were handed an IP address by mistake
length = host.length ();
ok = false;
for (int i = 0; i < length && !ok; i++)
{
c = host.charAt (i);
if (!(Character.isDigit (c) || (c == '.')))
ok = true;
}
if (ok)
{
// so take everything after the first token
server = tokenizer.nextToken ();
length = server.length ();
ret = host.substring (length);
}
}
return (ret);
}
/**
* Creates the cookie request property value from the list of
* valid cookies for the domain.
* @param cookies The list of valid cookies to be encoded in the request.
* @return A string suitable for inclusion as the value of
* the "Cookie:" request property.
*/
protected String generateCookieProperty (List cookies)
{
int version;
Cookie cookie;
StringBuilder buffer;
String ret;
ret = null;
buffer = new StringBuilder ();
version = 0;
for (int i = 0; i < cookies.size (); i++)
version = Math.max (version,
((Cookie)cookies.get (i)).getVersion ());
if (0 != version)
{
buffer.append ("$Version=\"");
buffer.append (version);
buffer.append ("\"");
}
for (int i = 0; i < cookies.size (); i++)
{
cookie = (Cookie)cookies.get (i);
if (0 != buffer.length ())
buffer.append ("; ");
buffer.append (cookie.getName ());
buffer.append ("=");
if (0 != version)
buffer.append ("\"");
buffer.append (cookie.getValue ());
if (0 != version)
buffer.append ("\"");
if (0 != version)
{
if ((null != cookie.getPath ())
&& (0 != cookie.getPath ().length ()))
{
buffer.append ("; $Path=\"");
buffer.append (cookie.getPath ());
buffer.append ("\"");
}
if ((null != cookie.getDomain ())
&& (0 != cookie.getDomain ().length ()))
{
buffer.append ("; $Domain=\"");
buffer.append (cookie.getDomain ());
buffer.append ("\"");
}
}
}
if (0 != buffer.length ())
ret = buffer.toString ();
return (ret);
}
/**
* Check for cookie and parse into cookie jar.
* @param connection The connection to extract cookie information from.
*/
public void parseCookies (URLConnection connection)
{
String string;
List cookies;
StringTokenizer tokenizer;
String token;
int index;
String name;
String key;
String value;
Cookie cookie;
string = connection.getHeaderField ("Set-Cookie");
if (null != string)
{
// set-cookie = "Set-Cookie:" cookies
// cookies = 1#cookie
// cookie = NAME "=" VALUE *(";" cookie-av)
// NAME = attr
// VALUE = value
// cookie-av = "Comment" "=" value
// | "Domain" "=" value
// | "Max-Age" "=" value
// | "Path" "=" value
// | "Secure"
// | "Version" "=" 1*DIGIT
cookies = new ArrayList ();
tokenizer = new StringTokenizer (string, ";,", true);
cookie = null;
while (tokenizer.hasMoreTokens ())
{
token = tokenizer.nextToken ().trim ();
if (token.equals (";"))
continue;
else if (token.equals (","))
{
cookie = null;
continue;
}
index = token.indexOf ('=');
if (-1 == index)
{
name = token;
value = null;
if (null == cookie)
throw new IllegalStateException ("no cookie value");
key = name.toLowerCase ();
}
else
{
name = token.substring (0, index);
value = token.substring (index + 1);
key = name.toLowerCase ();
}
if (null == cookie)
{
cookie = new Cookie (name, value);
cookies.add (cookie);
}
else
{
if (key.equals ("expires")) // Wdy, DD-Mon-YY HH:MM:SS GMT
{
String comma = tokenizer.nextToken ();
String rest = tokenizer.nextToken ();
SimpleDateFormat format = new SimpleDateFormat (
"EEE, dd-MMM-yy kk:mm:ss z");
try
{
Date date = format.parse (value + comma + rest);
cookie.setExpiryDate (date);
}
catch (ParseException pe)
{
// ok now what
cookie.setExpiryDate (null);
}
}
else
if (key.equals ("domain"))
cookie.setDomain (value);
else
if (key.equals ("path"))
cookie.setPath (value);
else
if (key.equals ("secure"))
cookie.setSecure (true);
else
if (key.equals ("comment"))
cookie.setComment (value);
else
if (key.equals ("version"))
cookie.setVersion (
Integer.parseInt (value));
else
if (key.equals ("max-age"))
{
Date date = new Date ();
long then = date.getTime ()
+ Integer.parseInt (value)
* 1000;
date.setTime (then);
cookie.setExpiryDate (date);
}
else
{ // error,? unknown attribute,
// maybe just another cookie
// not separated by a comma
cookie = new Cookie (name,
value);
cookies.add (cookie);
}
}
}
if (0 != cookies.size ())
saveCookies (cookies, connection);
}
}
/**
* Save the cookies received in the response header.
* @param list The list of cookies extracted from the response header.
* @param connection The connection (used when a cookie has no domain).
*/
protected void saveCookies (List list, URLConnection connection)
{
Cookie cookie;
String domain;
for (int i = 0; i < list.size (); i++)
{
cookie = (Cookie)list.get (i);
domain = cookie.getDomain ();
if (null == domain)
domain = connection.getURL ().getHost ();
setCookie (cookie, domain);
}
}
}