HTTPClient.CookieModule Maven / Gradle / Ivy
Show all versions of grinder-httpclient Show documentation
/*
* @(#)CookieModule.java 0.3-3 06/05/2001
*
* This file is part of the HTTPClient package
* Copyright (C) 1996-2001 Ronald Tschalär
*
* 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 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
*
* For questions, suggestions, bug-reports, enhancement-requests etc.
* I may be contacted at:
*
* [email protected]
*
* The HTTPClient's home page is located at:
*
* http://www.innovation.ch/java/HTTPClient/
*
*/
package HTTPClient;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ProtocolException;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.Label;
import java.awt.Color;
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.GridLayout;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
/**
* This module handles Netscape cookies (also called Version 0 cookies)
* and Version 1 cookies. Specifically is reads the Set-Cookie
* and Set-Cookie2 response headers and sets the Cookie
* and Cookie2 headers as neccessary.
*
* The accepting and sending of cookies is controlled by a
* CookiePolicyHandler. This allows you to fine tune your privacy
* preferences. A cookie is only added to the cookie list if the handler
* allows it, and a cookie from the cookie list is only sent if the handler
* allows it.
*
*
This module expects to be the only one handling cookies. Specifically, it
* will remove any Cookie and Cookie2 header fields found
* in the request, and it will remove the Set-Cookie and
* Set-Cookie2 header fields in the response (after processing them).
* In order to add cookies to a request or to prevent cookies from being sent,
* you can use the {@link #addCookie(HTTPClient.Cookie) addCookie} and {@link
* #removeCookie(HTTPClient.Cookie) removeCookie} methods to manipulate the
* module's list of cookies.
*
*
A cookie jar can be used to store cookies between sessions. This file is
* read when this class is loaded and is written when the application exits;
* only cookies from the default context are saved. The name of the file is
* controlled by the system property HTTPClient.cookies.jar and
* defaults to a system dependent name. The reading and saving of cookies is
* enabled by setting the system property HTTPClient.cookies.save
* to true.
*
* @see Netscape's cookie spec
* @see HTTP State Management Mechanism spec
* @version 0.3-3 06/05/2001
* @author Ronald Tschalär
* @since V0.3
*
* This file contains modifications for use with "The Grinder"
* (http://grinder.sourceforge.net) under the terms of the LGPL. They
* are marked below with the comment "GRINDER MODIFICATION".
*/
public class CookieModule implements HTTPClientModule
{
/** the list of known cookies */
private static Hashtable cookie_cntxt_list = new Hashtable();
/** the file to use for persistent cookie storage */
private static File cookie_jar = null;
/** an object, whose finalizer will save the cookies to the jar */
private static Object cookieSaver = null;
/** the cookie policy handler */
private static CookiePolicyHandler cookie_handler =
new DefaultCookiePolicyHandler();
// read in cookies from disk at startup
static
{
boolean persist;
try
{ persist = Boolean.getBoolean("HTTPClient.cookies.save"); }
catch (Exception e)
{ persist = false; }
if (persist)
{
loadCookies();
// the nearest thing to atexit() I know of...
cookieSaver = new Object()
{
public void finalize() { saveCookies(); }
};
try
{ System.runFinalizersOnExit(true); }
catch (Throwable t)
{ }
}
}
private static void loadCookies()
{
// The isFile() etc need to be protected by the catch as signed
// applets may be allowed to read properties but not do IO
try
{
cookie_jar = new File(getCookieJarName());
if (cookie_jar.isFile() && cookie_jar.canRead())
{
ObjectInputStream ois =
new ObjectInputStream(new FileInputStream(cookie_jar));
cookie_cntxt_list.put(HTTPConnection.getDefaultContext(),
(Hashtable) ois.readObject());
ois.close();
}
}
catch (Throwable t)
{ cookie_jar = null; }
}
private static void saveCookies()
{
if (cookie_jar != null && (!cookie_jar.exists() ||
cookie_jar.isFile() && cookie_jar.canWrite()))
{
/** ++GRINDER MODICIFATION **/
// Hashtable cookie_list = new Hashtable();
// Enumeration enum = Util.getList(cookie_cntxt_list,
// HTTPConnection.getDefaultContext())
// .elements();
//
// // discard cookies which are not to be kept across sessions
//
// while (enum.hasMoreElements())
// {
// Cookie cookie = (Cookie) enum.nextElement();
// if (!cookie.discard())
// cookie_list.put(cookie, cookie);
// }
Hashtable cookie_list = new Hashtable();
Enumeration e = Util.getList(cookie_cntxt_list,
HTTPConnection.getDefaultContext())
.elements();
// discard cookies which are not to be kept across sessions
while (e.hasMoreElements())
{
Cookie cookie = (Cookie) e.nextElement();
if (!cookie.discard())
cookie_list.put(cookie, cookie);
}
/** --GRINDER MODICIFATION **/
// save any remaining cookies in jar
if (cookie_list.size() > 0)
{
try
{
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream(cookie_jar));
oos.writeObject(cookie_list);
oos.close();
}
catch (Throwable t)
{ }
}
}
}
private static String getCookieJarName()
{
String file = null;
try
{ file = System.getProperty("HTTPClient.cookies.jar"); }
catch (Exception e)
{ }
if (file == null)
{
// default to something reasonable
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") ||
os.equalsIgnoreCase("16-bit Windows") ||
os.equalsIgnoreCase("Windows"))
{
file = System.getProperty("java.home") +
File.separator + ".httpclient_cookies";
}
else if (os.equalsIgnoreCase("Windows NT"))
{
file = System.getProperty("user.home") +
File.separator + ".httpclient_cookies";
}
else if (os.equalsIgnoreCase("OS/2"))
{
file = System.getProperty("user.home") +
File.separator + ".httpclient_cookies";
}
else if (os.equalsIgnoreCase("Mac OS") ||
os.equalsIgnoreCase("MacOS"))
{
file = "System Folder" + File.separator +
"Preferences" + File.separator +
"HTTPClientCookies";
}
else // it's probably U*IX or VMS
{
file = System.getProperty("user.home") +
File.separator + ".httpclient_cookies";
}
}
return file;
}
// Constructors
CookieModule()
{
}
// Methods
/**
* Invoked by the HTTPClient.
*/
public int requestHandler(Request req, Response[] resp)
{
// First remove any Cookie headers we might have set for a previous
// request
NVPair[] hdrs = req.getHeaders();
int length = hdrs.length;
for (int idx=0; idx 0)
{
length -= idx-beg;
System.arraycopy(hdrs, idx, hdrs, beg, length-beg);
}
}
if (length < hdrs.length)
{
hdrs = Util.resizeArray(hdrs, length);
req.setHeaders(hdrs);
}
// Now set any new cookie headers
Hashtable cookie_list =
Util.getList(cookie_cntxt_list, req.getConnection().getContext());
if (cookie_list.size() == 0)
return REQ_CONTINUE; // no need to create a lot of objects
Vector names = new Vector();
Vector lens = new Vector();
int version = 0;
synchronized (cookie_list)
{
Enumeration list = cookie_list.elements();
Vector remove_list = null;
while (list.hasMoreElements())
{
Cookie cookie = (Cookie) list.nextElement();
if (cookie.hasExpired())
{
Log.write(Log.COOKI, "CookM: cookie has expired and is " +
"being removed: " + cookie);
if (remove_list == null) remove_list = new Vector();
remove_list.addElement(cookie);
continue;
}
if (cookie.sendWith(req) && (cookie_handler == null ||
cookie_handler.sendCookie(cookie, req)))
{
int len = cookie.getPath().length();
int idx;
// insert in correct position
for (idx=0; idx 0)
value.append("$Version=\"" + version + "\"; ");
value.append((String) names.elementAt(0));
for (int idx=1; idxCookie.equals())
* already exists in the list then it is replaced with the new cookie.
*
* @param cookie the Cookie to add
* @since V0.3-1
*/
public static void addCookie(Cookie cookie)
{
Hashtable cookie_list =
Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
cookie_list.put(cookie, cookie);
}
/**
* Add the specified cookie to the list of cookies for the specified
* context. If a compatible cookie (as defined by
* Cookie.equals()) already exists in the list then it is
* replaced with the new cookie.
*
* @param cookie the cookie to add
* @param context the context Object.
* @since V0.3-1
*/
public static void addCookie(Cookie cookie, Object context)
{
Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
cookie_list.put(cookie, cookie);
}
/**
* Remove the specified cookie from the list of cookies in the default
* context. If the cookie is not found in the list then this method does
* nothing.
*
* @param cookie the Cookie to remove
* @since V0.3-1
*/
public static void removeCookie(Cookie cookie)
{
Hashtable cookie_list =
Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
cookie_list.remove(cookie);
}
/**
* Remove the specified cookie from the list of cookies for the specified
* context. If the cookie is not found in the list then this method does
* nothing.
*
* @param cookie the cookie to remove
* @param context the context Object
* @since V0.3-1
*/
public static void removeCookie(Cookie cookie, Object context)
{
Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
cookie_list.remove(cookie);
}
/**
* Sets a new cookie policy handler. This handler will be called for each
* cookie that a server wishes to set and for each cookie that this
* module wishes to send with a request. In either case the handler may
* allow or reject the operation. If you wish to blindly accept and send
* all cookies then just disable the handler with
* CookieModule.setCookiePolicyHandler(null);
.
*
* At initialization time a default handler is installed. This
* handler allows all cookies to be sent. For any cookie that a server
* wishes to be set two lists are consulted. If the server matches any
* host or domain in the reject list then the cookie is rejected; if
* the server matches any host or domain in the accept list then the
* cookie is accepted (in that order). If no host or domain match is
* found in either of these two lists and user interaction is allowed
* then a dialog box is poped up to ask the user whether to accept or
* reject the cookie; if user interaction is not allowed the cookie is
* accepted.
*
*
The accept and reject lists in the default handler are initialized
* at startup from the two properties
* HTTPClient.cookies.hosts.accept and
* HTTPClient.cookies.hosts.reject. These properties must
* contain a "|" separated list of host and domain names. All names
* beginning with a "." are treated as domain names, all others as host
* names. An empty string will match all hosts. The two lists are
* further expanded if the user chooses one of the "Accept All from
* Domain" or "Reject All from Domain" buttons in the dialog box.
*
*
Note: the default handler does not implement the rules concerning
* unverifiable transactions (section 3.3.6, RFC-2965). The reason
* for this is simple: the default handler knows nothing about the
* application using this client, and it therefore does not have enough
* information to determine when a request is verifiable and when not. You
* are therefore encouraged to provide your own handler which implements
* section 3.3.6 (use the CookiePolicyHandler.sendCookie
* method for this).
*
* @param handler the new policy handler
* @return the previous policy handler
*/
public static synchronized CookiePolicyHandler
setCookiePolicyHandler(CookiePolicyHandler handler)
{
CookiePolicyHandler old = cookie_handler;
cookie_handler = handler;
return old;
}
}
/**
* A simple cookie policy handler.
*/
class DefaultCookiePolicyHandler implements CookiePolicyHandler
{
/** a list of all hosts and domains from which to silently accept cookies */
private String[] accept_domains = new String[0];
/** a list of all hosts and domains from which to silently reject cookies */
private String[] reject_domains = new String[0];
/** the query popup */
private BasicCookieBox popup = null;
DefaultCookiePolicyHandler()
{
// have all cookies been accepted or rejected?
String list;
try
{ list = System.getProperty("HTTPClient.cookies.hosts.accept"); }
catch (Exception e)
{ list = null; }
String[] domains = Util.splitProperty(list);
for (int idx=0; idx 0)
domain += ".local";
for (int idx=0; idx 0)
domain += ".local";
for (int idx=0; idx