CookieModule.java
Upload User: demmber
Upload Date: 2007-12-22
Package Size: 717k
Code Size: 31k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * @(#)CookieModule.java 0.3-3 06/05/2001
  3.  *
  4.  *  This file is part of the HTTPClient package
  5.  *  Copyright (C) 1996-2001 Ronald Tschal鋜
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Lesser General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Lesser General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU Lesser General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20.  *  MA 02111-1307, USA
  21.  *
  22.  *  For questions, suggestions, bug-reports, enhancement-requests etc.
  23.  *  I may be contacted at:
  24.  *
  25.  *  ronald@innovation.ch
  26.  *
  27.  *  The HTTPClient's home page is located at:
  28.  *
  29.  *  http://www.innovation.ch/java/HTTPClient/ 
  30.  *
  31.  */
  32. package HTTPClient;
  33. import java.io.File;
  34. import java.io.IOException;
  35. import java.io.FileInputStream;
  36. import java.io.FileOutputStream;
  37. import java.io.ObjectInputStream;
  38. import java.io.ObjectOutputStream;
  39. import java.net.ProtocolException;
  40. import java.util.Vector;
  41. import java.util.Hashtable;
  42. import java.util.Enumeration;
  43. import java.awt.Frame;
  44. import java.awt.Panel;
  45. import java.awt.Label;
  46. import java.awt.Color;
  47. import java.awt.Button;
  48. import java.awt.Graphics;
  49. import java.awt.Dimension;
  50. import java.awt.TextArea;
  51. import java.awt.TextField;
  52. import java.awt.GridLayout;
  53. import java.awt.GridBagLayout;
  54. import java.awt.GridBagConstraints;
  55. import java.awt.event.ActionEvent;
  56. import java.awt.event.ActionListener;
  57. import java.awt.event.WindowEvent;
  58. import java.awt.event.WindowAdapter;
  59. /**
  60.  * This module handles Netscape cookies (also called Version 0 cookies)
  61.  * and Version 1 cookies. Specifically is reads the <var>Set-Cookie</var>
  62.  * and <var>Set-Cookie2</var> response headers and sets the <var>Cookie</var>
  63.  * and <var>Cookie2</var> headers as neccessary.
  64.  *
  65.  * <P>The accepting and sending of cookies is controlled by a
  66.  * <var>CookiePolicyHandler</var>. This allows you to fine tune your privacy
  67.  * preferences. A cookie is only added to the cookie list if the handler
  68.  * allows it, and a cookie from the cookie list is only sent if the handler
  69.  * allows it.
  70.  *
  71.  * <P>This module expects to be the only one handling cookies. Specifically, it
  72.  * will remove any <var>Cookie</var> and <var>Cookie2</var> header fields found
  73.  * in the request, and it will remove the <var>Set-Cookie</var> and
  74.  * <var>Set-Cookie2</var> header fields in the response (after processing them).
  75.  * In order to add cookies to a request or to prevent cookies from being sent,
  76.  * you can use the {@link #addCookie(HTTPClient.Cookie) addCookie} and {@link
  77.  * #removeCookie(HTTPClient.Cookie) removeCookie} methods to manipulate the
  78.  * module's list of cookies.
  79.  *
  80.  * <P>A cookie jar can be used to store cookies between sessions. This file is
  81.  * read when this class is loaded and is written when the application exits;
  82.  * only cookies from the default context are saved. The name of the file is
  83.  * controlled by the system property <var>HTTPClient.cookies.jar</var> and
  84.  * defaults to a system dependent name. The reading and saving of cookies is
  85.  * enabled by setting the system property <var>HTTPClient.cookies.save</var>
  86.  * to <var>true</var>.
  87.  *
  88.  * @see <a href="http://home.netscape.com/newsref/std/cookie_spec.html">Netscape's cookie spec</a>
  89.  * @see <a href="http://www.ietf.org/rfc/rfc2965.txt">HTTP State Management Mechanism spec</a>
  90.  * @version 0.3-3  06/05/2001
  91.  * @author Ronald Tschal鋜
  92.  * @since V0.3
  93.  */
  94. public class CookieModule implements HTTPClientModule
  95. {
  96.     /** the list of known cookies */
  97.     private static Hashtable cookie_cntxt_list = new Hashtable();
  98.     /** the file to use for persistent cookie storage */
  99.     private static File cookie_jar = null;
  100.     /** an object, whose finalizer will save the cookies to the jar */
  101.     private static Object cookieSaver = null;
  102.     /** the cookie policy handler */
  103.     private static CookiePolicyHandler cookie_handler =
  104.     new DefaultCookiePolicyHandler();
  105.     // read in cookies from disk at startup
  106.     static
  107.     {
  108. boolean persist;
  109. try
  110.     { persist = Boolean.getBoolean("HTTPClient.cookies.save"); }
  111. catch (Exception e)
  112.     { persist = false; }
  113. if (persist)
  114. {
  115.     loadCookies();
  116.     // the nearest thing to atexit() I know of...
  117.     cookieSaver = new Object()
  118. {
  119.     public void finalize() { saveCookies(); }
  120. };
  121.     try
  122. { System.runFinalizersOnExit(true); }
  123.     catch (Throwable t)
  124. { }
  125. }
  126.     }
  127.     private static void loadCookies()
  128.     {
  129. // The isFile() etc need to be protected by the catch as signed
  130. // applets may be allowed to read properties but not do IO
  131. try
  132. {
  133.     cookie_jar = new File(getCookieJarName());
  134.     if (cookie_jar.isFile()  &&  cookie_jar.canRead())
  135.     {
  136. ObjectInputStream ois =
  137.     new ObjectInputStream(new FileInputStream(cookie_jar));
  138. cookie_cntxt_list.put(HTTPConnection.getDefaultContext(),
  139.       (Hashtable) ois.readObject());
  140. ois.close();
  141.     }
  142. }
  143. catch (Throwable t)
  144.     { cookie_jar = null; }
  145.     }
  146.     private static void saveCookies()
  147.     {
  148. if (cookie_jar != null  &&  (!cookie_jar.exists()  ||
  149.      cookie_jar.isFile()  &&  cookie_jar.canWrite()))
  150. {
  151.     Hashtable cookie_list = new Hashtable();
  152.     Enumeration enum = Util.getList(cookie_cntxt_list,
  153.     HTTPConnection.getDefaultContext())
  154.    .elements();
  155.     // discard cookies which are not to be kept across sessions
  156.     while (enum.hasMoreElements())
  157.     {
  158. Cookie cookie = (Cookie) enum.nextElement();
  159. if (!cookie.discard())
  160.     cookie_list.put(cookie, cookie);
  161.     }
  162.     // save any remaining cookies in jar
  163.     if (cookie_list.size() > 0)
  164.     {
  165. try
  166. {
  167.     ObjectOutputStream oos =
  168. new ObjectOutputStream(new FileOutputStream(cookie_jar));
  169.     oos.writeObject(cookie_list);
  170.     oos.close();
  171. }
  172. catch (Throwable t)
  173.     { }
  174.     }
  175. }
  176.     }
  177.     private static String getCookieJarName()
  178.     {
  179. String file = null;
  180. try
  181.     { file = System.getProperty("HTTPClient.cookies.jar"); }
  182. catch (Exception e)
  183.     { }
  184. if (file == null)
  185. {
  186.     // default to something reasonable
  187.     String os = System.getProperty("os.name");
  188.     if (os.equalsIgnoreCase("Windows 95")  ||
  189. os.equalsIgnoreCase("16-bit Windows")  ||
  190. os.equalsIgnoreCase("Windows"))
  191.     {
  192. file = System.getProperty("java.home") +
  193.        File.separator + ".httpclient_cookies";
  194.     }
  195.     else if (os.equalsIgnoreCase("Windows NT"))
  196.     {
  197. file = System.getProperty("user.home") +
  198.        File.separator + ".httpclient_cookies";
  199.     }
  200.     else if (os.equalsIgnoreCase("OS/2"))
  201.     {
  202. file = System.getProperty("user.home") +
  203.        File.separator + ".httpclient_cookies";
  204.     }
  205.     else if (os.equalsIgnoreCase("Mac OS")  ||
  206.      os.equalsIgnoreCase("MacOS"))
  207.     {
  208. file = "System Folder" + File.separator +
  209.        "Preferences" + File.separator +
  210.        "HTTPClientCookies";
  211.     }
  212.     else // it's probably U*IX or VMS
  213.     {
  214. file = System.getProperty("user.home") +
  215.        File.separator + ".httpclient_cookies";
  216.     }
  217. }
  218. return file;
  219.     }
  220.     // Constructors
  221.     CookieModule()
  222.     {
  223.     }
  224.     // Methods
  225.     /**
  226.      * Invoked by the HTTPClient.
  227.      */
  228.     public int requestHandler(Request req, Response[] resp)
  229.     {
  230. // First remove any Cookie headers we might have set for a previous
  231. // request
  232. NVPair[] hdrs = req.getHeaders();
  233. int length = hdrs.length;
  234. for (int idx=0; idx<hdrs.length; idx++)
  235. {
  236.     int beg = idx;
  237.     while (idx < hdrs.length  &&
  238.    hdrs[idx].getName().equalsIgnoreCase("Cookie"))
  239. idx++;
  240.     if (idx-beg > 0)
  241.     {
  242. length -= idx-beg;
  243. System.arraycopy(hdrs, idx, hdrs, beg, length-beg);
  244.     }
  245. }
  246. if (length < hdrs.length)
  247. {
  248.     hdrs = Util.resizeArray(hdrs, length);
  249.     req.setHeaders(hdrs);
  250. }
  251. // Now set any new cookie headers
  252. Hashtable cookie_list =
  253.     Util.getList(cookie_cntxt_list, req.getConnection().getContext());
  254. if (cookie_list.size() == 0)
  255.     return REQ_CONTINUE; // no need to create a lot of objects
  256. Vector  names   = new Vector();
  257. Vector  lens    = new Vector();
  258. int     version = 0;
  259. synchronized (cookie_list)
  260. {
  261.     Enumeration list = cookie_list.elements();
  262.     Vector remove_list = null;
  263.     while (list.hasMoreElements())
  264.     {
  265. Cookie cookie = (Cookie) list.nextElement();
  266. if (cookie.hasExpired())
  267. {
  268.     Log.write(Log.COOKI, "CookM: cookie has expired and is " +
  269.  "being removed: " + cookie);
  270.     if (remove_list == null)  remove_list = new Vector();
  271.     remove_list.addElement(cookie);
  272.     continue;
  273. }
  274. if (cookie.sendWith(req)  &&  (cookie_handler == null  ||
  275.     cookie_handler.sendCookie(cookie, req)))
  276. {
  277.     int len = cookie.getPath().length();
  278.     int idx;
  279.     // insert in correct position
  280.     for (idx=0; idx<lens.size(); idx++)
  281. if (((Integer) lens.elementAt(idx)).intValue() < len)
  282.     break;
  283.     names.insertElementAt(cookie.toExternalForm(), idx);
  284.     lens.insertElementAt(new Integer(len), idx);
  285.     if (cookie instanceof Cookie2)
  286. version = Math.max(version, ((Cookie2) cookie).getVersion());
  287. }
  288.     }
  289.     // remove any marked cookies
  290.     // Note: we can't do this during the enumeration!
  291.     if (remove_list != null)
  292.     {
  293. for (int idx=0; idx<remove_list.size(); idx++)
  294.     cookie_list.remove(remove_list.elementAt(idx));
  295.     }
  296. }
  297. if (!names.isEmpty())
  298. {
  299.     StringBuffer value = new StringBuffer();
  300.     if (version > 0)
  301. value.append("$Version="" + version + ""; ");
  302.     value.append((String) names.elementAt(0));
  303.     for (int idx=1; idx<names.size(); idx++)
  304.     {
  305. value.append("; ");
  306. value.append((String) names.elementAt(idx));
  307.     }
  308.     hdrs = Util.resizeArray(hdrs, hdrs.length+1);
  309.     hdrs[hdrs.length-1] = new NVPair("Cookie", value.toString());
  310.     // add Cookie2 header if necessary
  311.     if (version != 1) // we currently know about version 1 only
  312.     {
  313. int idx;
  314. for (idx=0; idx<hdrs.length; idx++)
  315.     if (hdrs[idx].getName().equalsIgnoreCase("Cookie2"))
  316. break;
  317. if (idx == hdrs.length)
  318. {
  319.     hdrs = Util.resizeArray(hdrs, hdrs.length+1);
  320.     hdrs[hdrs.length-1] =
  321.     new NVPair("Cookie2", "$Version="1"");
  322. }
  323.     }
  324.     req.setHeaders(hdrs);
  325.     Log.write(Log.COOKI, "CookM: Sending cookies '" + value + "'");
  326. }
  327. return REQ_CONTINUE;
  328.     }
  329.     /**
  330.      * Invoked by the HTTPClient.
  331.      */
  332.     public void responsePhase1Handler(Response resp, RoRequest req)
  333.     throws IOException
  334.     {
  335. String set_cookie  = resp.getHeader("Set-Cookie");
  336. String set_cookie2 = resp.getHeader("Set-Cookie2");
  337. if (set_cookie == null  &&  set_cookie2 == null)
  338.     return;
  339. resp.deleteHeader("Set-Cookie");
  340. resp.deleteHeader("Set-Cookie2");
  341. if (set_cookie != null)
  342.     handleCookie(set_cookie, false, req, resp);
  343. if (set_cookie2 != null)
  344.     handleCookie(set_cookie2, true, req, resp);
  345.     }
  346.     /**
  347.      * Invoked by the HTTPClient.
  348.      */
  349.     public int responsePhase2Handler(Response resp, Request req)
  350.     {
  351. return RSP_CONTINUE;
  352.     }
  353.     /**
  354.      * Invoked by the HTTPClient.
  355.      */
  356.     public void responsePhase3Handler(Response resp, RoRequest req)
  357.     {
  358.     }
  359.     /**
  360.      * Invoked by the HTTPClient.
  361.      */
  362.     public void trailerHandler(Response resp, RoRequest req)  throws IOException
  363.     {
  364. String set_cookie = resp.getTrailer("Set-Cookie");
  365. String set_cookie2 = resp.getTrailer("Set-Cookie2");
  366. if (set_cookie == null  &&  set_cookie2 == null)
  367.     return;
  368. resp.deleteTrailer("Set-Cookie");
  369. resp.deleteTrailer("Set-Cookie2");
  370. if (set_cookie != null)
  371.     handleCookie(set_cookie, false, req, resp);
  372. if (set_cookie2 != null)
  373.     handleCookie(set_cookie2, true, req, resp);
  374.     }
  375.     private void handleCookie(String set_cookie, boolean cookie2, RoRequest req,
  376.       Response resp)
  377.     throws ProtocolException
  378.     {
  379. Cookie[] cookies;
  380. if (cookie2)
  381.     cookies = Cookie2.parse(set_cookie, req);
  382. else
  383.     cookies = Cookie.parse(set_cookie, req);
  384. if (Log.isEnabled(Log.COOKI))
  385. {
  386.     Log.write(Log.COOKI, "CookM: Received and parsed " + cookies.length +
  387.  " cookies:");
  388.     for (int idx=0; idx<cookies.length; idx++)
  389. Log.write(Log.COOKI, "CookM: Cookie " + idx + ": " + cookies[idx]);
  390. }
  391. Hashtable cookie_list =
  392.     Util.getList(cookie_cntxt_list, req.getConnection().getContext());
  393. synchronized (cookie_list)
  394. {
  395.     for (int idx=0; idx<cookies.length; idx++)
  396.     {
  397. Cookie cookie = (Cookie) cookie_list.get(cookies[idx]);
  398. if (cookie != null  &&  cookies[idx].hasExpired())
  399. {
  400.     Log.write(Log.COOKI, "CookM: cookie has expired and is " +
  401.  "being removed: " + cookie);
  402.     cookie_list.remove(cookie); // expired, so remove
  403. }
  404. else if (!cookies[idx].hasExpired()) // new or replaced
  405. {
  406.     if (cookie_handler == null  ||
  407. cookie_handler.acceptCookie(cookies[idx], req, resp))
  408. cookie_list.put(cookies[idx], cookies[idx]);
  409. }
  410.     }
  411. }
  412.     }
  413.     /**
  414.      * Discard all cookies for all contexts. Cookies stored in persistent
  415.      * storage are not affected.
  416.      */
  417.     public static void discardAllCookies()
  418.     {
  419. cookie_cntxt_list.clear();
  420.     }
  421.     /**
  422.      * Discard all cookies for the given context. Cookies stored in persistent
  423.      * storage are not affected.
  424.      *
  425.      * @param context the context Object
  426.      */
  427.     public static void discardAllCookies(Object context)
  428.     {
  429. if (context != null)
  430.     cookie_cntxt_list.remove(context);
  431.     }
  432.     /**
  433.      * List all stored cookies for all contexts.
  434.      *
  435.      * @return an array of all Cookies
  436.      * @since V0.3-1
  437.      */
  438.     public static Cookie[] listAllCookies()
  439.     {
  440. synchronized (cookie_cntxt_list)
  441. {
  442.     Cookie[] cookies = new Cookie[0];
  443.     int idx = 0;
  444.     Enumeration cntxt_list = cookie_cntxt_list.elements();
  445.     while (cntxt_list.hasMoreElements())
  446.     {
  447. Hashtable cntxt = (Hashtable) cntxt_list.nextElement();
  448. synchronized (cntxt)
  449. {
  450.     cookies = Util.resizeArray(cookies, idx+cntxt.size());
  451.     Enumeration cookie_list = cntxt.elements();
  452.     while (cookie_list.hasMoreElements())
  453. cookies[idx++] = (Cookie) cookie_list.nextElement();
  454. }
  455.     }
  456.     return cookies;
  457. }
  458.     }
  459.     /**
  460.      * List all stored cookies for a given context.
  461.      *
  462.      * @param  context the context Object.
  463.      * @return an array of Cookies
  464.      * @since V0.3-1
  465.      */
  466.     public static Cookie[] listAllCookies(Object context)
  467.     {
  468. Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
  469. synchronized (cookie_list)
  470. {
  471.     Cookie[] cookies = new Cookie[cookie_list.size()];
  472.     int idx = 0;
  473.     Enumeration enum = cookie_list.elements();
  474.     while (enum.hasMoreElements())
  475. cookies[idx++] = (Cookie) enum.nextElement();
  476.     return cookies;
  477. }
  478.     }
  479.     /**
  480.      * Add the specified cookie to the list of cookies in the default context.
  481.      * If a compatible cookie (as defined by <var>Cookie.equals()</var>)
  482.      * already exists in the list then it is replaced with the new cookie.
  483.      *
  484.      * @param cookie the Cookie to add
  485.      * @since V0.3-1
  486.      */
  487.     public static void addCookie(Cookie cookie)
  488.     {
  489. Hashtable cookie_list =
  490.     Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
  491. cookie_list.put(cookie, cookie);
  492.     }
  493.     /**
  494.      * Add the specified cookie to the list of cookies for the specified
  495.      * context. If a compatible cookie (as defined by
  496.      * <var>Cookie.equals()</var>) already exists in the list then it is
  497.      * replaced with the new cookie.
  498.      *
  499.      * @param cookie  the cookie to add
  500.      * @param context the context Object.
  501.      * @since V0.3-1
  502.      */
  503.     public static void addCookie(Cookie cookie, Object context)
  504.     {
  505. Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
  506. cookie_list.put(cookie, cookie);
  507.     }
  508.     /**
  509.      * Remove the specified cookie from the list of cookies in the default
  510.      * context. If the cookie is not found in the list then this method does
  511.      * nothing.
  512.      *
  513.      * @param cookie the Cookie to remove
  514.      * @since V0.3-1
  515.      */
  516.     public static void removeCookie(Cookie cookie)
  517.     {
  518. Hashtable cookie_list =
  519.     Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
  520. cookie_list.remove(cookie);
  521.     }
  522.     /**
  523.      * Remove the specified cookie from the list of cookies for the specified
  524.      * context. If the cookie is not found in the list then this method does
  525.      * nothing.
  526.      *
  527.      * @param cookie  the cookie to remove
  528.      * @param context the context Object
  529.      * @since V0.3-1
  530.      */
  531.     public static void removeCookie(Cookie cookie, Object context)
  532.     {
  533. Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
  534. cookie_list.remove(cookie);
  535.     }
  536.     /**
  537.      * Sets a new cookie policy handler. This handler will be called for each
  538.      * cookie that a server wishes to set and for each cookie that this
  539.      * module wishes to send with a request. In either case the handler may
  540.      * allow or reject the operation. If you wish to blindly accept and send
  541.      * all cookies then just disable the handler with
  542.      * <code>CookieModule.setCookiePolicyHandler(null);</code>.
  543.      *
  544.      * <P>At initialization time a default handler is installed. This
  545.      * handler allows all cookies to be sent. For any cookie that a server
  546.      * wishes to be set two lists are consulted. If the server matches any
  547.      * host or domain in the reject list then the cookie is rejected; if
  548.      * the server matches any host or domain in the accept list then the
  549.      * cookie is accepted (in that order). If no host or domain match is
  550.      * found in either of these two lists and user interaction is allowed
  551.      * then a dialog box is poped up to ask the user whether to accept or
  552.      * reject the cookie; if user interaction is not allowed the cookie is
  553.      * accepted.
  554.      *
  555.      * <P>The accept and reject lists in the default handler are initialized
  556.      * at startup from the two properties
  557.      * <var>HTTPClient.cookies.hosts.accept</var> and
  558.      * <var>HTTPClient.cookies.hosts.reject</var>. These properties must
  559.      * contain a "|" separated list of host and domain names. All names
  560.      * beginning with a "." are treated as domain names, all others as host
  561.      * names. An empty string will match all hosts. The two lists are
  562.      * further expanded if the user chooses one of the "Accept All from
  563.      * Domain" or "Reject All from Domain" buttons in the dialog box.
  564.      *
  565.      * <P>Note: the default handler does not implement the rules concerning
  566.      * unverifiable transactions (section 3.3.6, <A
  567.      * HREF="http://www.ietf.org/rfc/rfc2965.txt">RFC-2965</A>). The reason
  568.      * for this is simple: the default handler knows nothing about the
  569.      * application using this client, and it therefore does not have enough
  570.      * information to determine when a request is verifiable and when not. You
  571.      * are therefore encouraged to provide your own handler which implements
  572.      * section 3.3.6 (use the <code>CookiePolicyHandler.sendCookie</code>
  573.      * method for this).
  574.      *
  575.      * @param handler the new policy handler
  576.      * @return the previous policy handler
  577.      */
  578.     public static synchronized CookiePolicyHandler
  579.     setCookiePolicyHandler(CookiePolicyHandler handler)
  580.     {
  581. CookiePolicyHandler old = cookie_handler;
  582. cookie_handler = handler;
  583. return old;
  584.     }
  585. }
  586. /**
  587.  * A simple cookie policy handler.
  588.  */
  589. class DefaultCookiePolicyHandler implements CookiePolicyHandler
  590. {
  591.     /** a list of all hosts and domains from which to silently accept cookies */
  592.     private String[] accept_domains = new String[0];
  593.     /** a list of all hosts and domains from which to silently reject cookies */
  594.     private String[] reject_domains = new String[0];
  595.     /** the query popup */
  596.     private BasicCookieBox popup = null;
  597.     DefaultCookiePolicyHandler()
  598.     {
  599. // have all cookies been accepted or rejected?
  600. String list;
  601. try
  602.     { list = System.getProperty("HTTPClient.cookies.hosts.accept"); }
  603. catch (Exception e)
  604.     { list = null; }
  605. String[] domains = Util.splitProperty(list);
  606. for (int idx=0; idx<domains.length; idx++)
  607.     addAcceptDomain(domains[idx].toLowerCase());
  608. try
  609.     { list = System.getProperty("HTTPClient.cookies.hosts.reject"); }
  610. catch (Exception e)
  611.     { list = null; }
  612. domains = Util.splitProperty(list);
  613. for (int idx=0; idx<domains.length; idx++)
  614.     addRejectDomain(domains[idx].toLowerCase());
  615.     }
  616.     /**
  617.      * returns whether this cookie should be accepted. First checks the
  618.      * stored lists of accept and reject domains, and if it is neither
  619.      * accepted nor rejected by these then query the user via a popup.
  620.      *
  621.      * @param cookie   the cookie in question
  622.      * @param req      the request
  623.      * @param resp     the response
  624.      * @return true if we accept this cookie.
  625.      */
  626.     public boolean acceptCookie(Cookie cookie, RoRequest req, RoResponse resp)
  627.     {
  628. String server = req.getConnection().getHost();
  629. if (server.indexOf('.') == -1)  server += ".local";
  630. // Check lists. Reject takes priority over accept
  631. for (int idx=0; idx<reject_domains.length; idx++)
  632. {
  633.     if (reject_domains[idx].length() == 0  ||
  634. reject_domains[idx].charAt(0) == '.'  &&
  635. server.endsWith(reject_domains[idx])  ||
  636. reject_domains[idx].charAt(0) != '.'  &&
  637. server.equals(reject_domains[idx]))
  638.     return false;
  639. }
  640. for (int idx=0; idx<accept_domains.length; idx++)
  641. {
  642.     if (accept_domains[idx].length() == 0  ||
  643. accept_domains[idx].charAt(0) == '.'  &&
  644. server.endsWith(accept_domains[idx])  ||
  645. accept_domains[idx].charAt(0) != '.'  &&
  646. server.equals(accept_domains[idx]))
  647.     return true;
  648. }
  649. // Ok, not in any list, so ask the user (if allowed).
  650. if (!req.allowUI())  return true;
  651. if (popup == null)
  652.     popup = new BasicCookieBox();
  653. return popup.accept(cookie, this, server);
  654.     }
  655.     /**
  656.      * This handler just allows all cookies to be sent which were accepted
  657.      * (i.e. no further restrictions are placed on the sending of cookies).
  658.      *
  659.      * @return true
  660.      */
  661.     public boolean sendCookie(Cookie cookie, RoRequest req)
  662.     {
  663. return true;
  664.     }
  665.     void addAcceptDomain(String domain)
  666.     {
  667. if (domain.indexOf('.') == -1  &&  domain.length() > 0)
  668.     domain += ".local";
  669. for (int idx=0; idx<accept_domains.length; idx++)
  670. {
  671.     if (domain.endsWith(accept_domains[idx]))
  672. return;
  673.     if (accept_domains[idx].endsWith(domain))
  674.     {
  675. accept_domains[idx] = domain;
  676. return;
  677.     }
  678. }
  679. accept_domains =
  680.     Util.resizeArray(accept_domains, accept_domains.length+1);
  681. accept_domains[accept_domains.length-1] = domain;
  682.     }
  683.     void addRejectDomain(String domain)
  684.     {
  685. if (domain.indexOf('.') == -1  &&  domain.length() > 0)
  686.     domain += ".local";
  687. for (int idx=0; idx<reject_domains.length; idx++)
  688. {
  689.     if (domain.endsWith(reject_domains[idx]))
  690. return;
  691.     if (reject_domains[idx].endsWith(domain))
  692.     {
  693. reject_domains[idx] = domain;
  694. return;
  695.     }
  696. }
  697. reject_domains =
  698.     Util.resizeArray(reject_domains, reject_domains.length+1);
  699. reject_domains[reject_domains.length-1] = domain;
  700.     }
  701. }
  702. /**
  703.  * A simple popup that asks whether the cookie should be accepted or rejected,
  704.  * or if cookies from whole domains should be silently accepted or rejected.
  705.  *
  706.  * @version 0.3-3  06/05/2001
  707.  * @author Ronald Tschal鋜
  708.  */
  709. class BasicCookieBox extends Frame
  710. {
  711.     private final static String title = "Set Cookie Request";
  712.     private Dimension           screen;
  713.     private GridBagConstraints  constr;
  714.     private Label name_value_label;
  715.     private Label domain_value;
  716.     private Label ports_label;
  717.     private Label ports_value;
  718.     private Label path_value;
  719.     private Label expires_value;
  720.     private Label discard_note;
  721.     private Label secure_note;
  722.     private Label c_url_note;
  723.     private Panel left_panel;
  724.     private Panel right_panel;
  725.     private Label    comment_label;
  726.     private TextArea comment_value;
  727.     private TextField domain;
  728.     private Button default_focus;
  729.     private boolean             accept;
  730.     private boolean             accept_domain;
  731.     /**
  732.      * Constructs the popup.
  733.      */
  734.     BasicCookieBox()
  735.     {
  736. super(title);
  737. screen = getToolkit().getScreenSize();
  738. addNotify();
  739. addWindowListener(new Close());
  740. GridBagLayout layout;
  741. setLayout(layout = new GridBagLayout());
  742. constr = new GridBagConstraints();
  743. constr.gridwidth = GridBagConstraints.REMAINDER;
  744. constr.anchor = GridBagConstraints.WEST;
  745. add(new Label("The server would like to set the following cookie:"), constr);
  746. Panel p = new Panel();
  747. left_panel = new Panel();
  748. left_panel.setLayout(new GridLayout(4,1));
  749. left_panel.add(new Label("Name=Value:"));
  750. left_panel.add(new Label("Domain:"));
  751. left_panel.add(new Label("Path:"));
  752. left_panel.add(new Label("Expires:"));
  753. ports_label = new Label("Ports:");
  754. p.add(left_panel);
  755. right_panel = new Panel();
  756. right_panel.setLayout(new GridLayout(4,1));
  757. right_panel.add(name_value_label = new Label());
  758. right_panel.add(domain_value = new Label());
  759. right_panel.add(path_value = new Label());
  760. right_panel.add(expires_value = new Label());
  761. ports_value = new Label();
  762. p.add(right_panel);
  763. add(p, constr);
  764. secure_note = new Label("This cookie will only be sent over secure connections");
  765. discard_note = new Label("This cookie will be discarded at the end of the session");
  766. c_url_note = new Label("");
  767. comment_label = new Label("Comment:");
  768. comment_value =
  769. new TextArea("", 3, 45, TextArea.SCROLLBARS_VERTICAL_ONLY);
  770. comment_value.setEditable(false);
  771. add(new Panel(), constr);
  772. constr.gridwidth = 1;
  773. constr.anchor = GridBagConstraints.CENTER;
  774. constr.weightx = 1.0;
  775. add(default_focus = new Button("Accept"), constr);
  776. default_focus.addActionListener(new Accept());
  777. Button b;
  778. constr.gridwidth = GridBagConstraints.REMAINDER;
  779. add(b= new Button("Reject"), constr);
  780. b.addActionListener(new Reject());
  781. constr.weightx = 0.0;
  782. p = new Separator();
  783. constr.fill = GridBagConstraints.HORIZONTAL;
  784. add(p, constr);
  785. constr.fill   = GridBagConstraints.NONE;
  786. constr.anchor = GridBagConstraints.WEST;
  787. add(new Label("Accept/Reject all cookies from a host or domain:"), constr);
  788. p = new Panel();
  789. p.add(new Label("Host/Domain:"));
  790. p.add(domain = new TextField(30));
  791. add(p, constr);
  792. add(new Label("domains are characterized by a leading dot (`.');"), constr);
  793. add(new Label("an empty string matches all hosts"), constr);
  794. constr.anchor    = GridBagConstraints.CENTER;
  795. constr.gridwidth = 1;
  796. constr.weightx   = 1.0;
  797. add(b = new Button("Accept All"), constr);
  798. b.addActionListener(new AcceptDomain());
  799. constr.gridwidth = GridBagConstraints.REMAINDER;
  800. add(b = new Button("Reject All"), constr);
  801. b.addActionListener(new RejectDomain());
  802. pack();
  803. constr.anchor    = GridBagConstraints.WEST;
  804. constr.gridwidth = GridBagConstraints.REMAINDER;
  805.     }
  806.     public Dimension getMaximumSize()
  807.     {
  808. return new Dimension(screen.width*3/4, screen.height*3/4);
  809.     }
  810.     /**
  811.      * our event handlers
  812.      */
  813.     private class Accept implements ActionListener
  814.     {
  815.         public void actionPerformed(ActionEvent ae)
  816.         {
  817.     accept = true;
  818.     accept_domain = false;
  819.             synchronized (BasicCookieBox.this)
  820. { BasicCookieBox.this.notifyAll(); }
  821.         }
  822.     }
  823.     private class Reject implements ActionListener
  824.     {
  825.         public void actionPerformed(ActionEvent ae)
  826. {
  827.     accept = false;
  828.     accept_domain = false;
  829.             synchronized (BasicCookieBox.this)
  830. { BasicCookieBox.this.notifyAll(); }
  831. }
  832.     }
  833.     private class AcceptDomain implements ActionListener
  834.     {
  835.         public void actionPerformed(ActionEvent ae)
  836.         {
  837.     accept = true;
  838.     accept_domain = true;
  839.             synchronized (BasicCookieBox.this)
  840. { BasicCookieBox.this.notifyAll(); }
  841. }
  842.     }
  843.     private class RejectDomain implements ActionListener
  844.     {
  845.         public void actionPerformed(ActionEvent ae)
  846. {
  847.     accept = false;
  848.     accept_domain = true;
  849.             synchronized (BasicCookieBox.this)
  850. { BasicCookieBox.this.notifyAll(); }
  851. }
  852.     }
  853.     private class Close extends WindowAdapter
  854.     {
  855. public void windowClosing(WindowEvent we)
  856. {
  857.     new Reject().actionPerformed(null);
  858. }
  859.     }
  860.     /**
  861.      * the method called by the DefaultCookiePolicyHandler.
  862.      *
  863.      * @return true if the cookie should be accepted
  864.      */
  865.     public synchronized boolean accept(Cookie cookie,
  866.        DefaultCookiePolicyHandler h,
  867.        String server)
  868.     {
  869. // set the new values
  870. name_value_label.setText(cookie.getName() + "=" + cookie.getValue());
  871. domain_value.setText(cookie.getDomain());
  872. path_value.setText(cookie.getPath());
  873. if (cookie.expires() == null)
  874.     expires_value.setText("never");
  875. else
  876.     expires_value.setText(cookie.expires().toString());
  877. int pos = 2;
  878. if (cookie.isSecure())
  879.     add(secure_note, constr, pos++);
  880. if (cookie.discard())
  881.     add(discard_note, constr, pos++);
  882. if (cookie instanceof Cookie2)
  883. {
  884.     Cookie2 cookie2 = (Cookie2) cookie;
  885.     // set ports list
  886.     if (cookie2.getPorts() != null)
  887.     {
  888. ((GridLayout) left_panel.getLayout()).setRows(5);
  889. left_panel.add(ports_label, 2);
  890. ((GridLayout) right_panel.getLayout()).setRows(5);
  891. int[] ports = cookie2.getPorts();
  892. StringBuffer plist = new StringBuffer();
  893. plist.append(ports[0]);
  894. for (int idx=1; idx<ports.length; idx++)
  895. {
  896.     plist.append(", ");
  897.     plist.append(ports[idx]);
  898. }
  899. ports_value.setText(plist.toString());
  900. right_panel.add(ports_value, 2);
  901.     }
  902.     // set comment url
  903.     if (cookie2.getCommentURL() != null)
  904.     {
  905. c_url_note.setText("For more info on this cookie see: " +
  906.     cookie2.getCommentURL());
  907. add(c_url_note, constr, pos++);
  908.     }
  909.     // set comment
  910.     if (cookie2.getComment() != null)
  911.     {
  912. comment_value.setText(cookie2.getComment());
  913. add(comment_label, constr, pos++);
  914. add(comment_value, constr, pos++);
  915.     }
  916. }
  917. // invalidate all labels, so that new values are displayed correctly
  918. name_value_label.invalidate();
  919. domain_value.invalidate();
  920. ports_value.invalidate();
  921. path_value.invalidate();
  922. expires_value.invalidate();
  923. left_panel.invalidate();
  924. right_panel.invalidate();
  925. secure_note.invalidate();
  926. discard_note.invalidate();
  927. c_url_note.invalidate();
  928. comment_value.invalidate();
  929. invalidate();
  930. // set default domain test
  931. domain.setText(cookie.getDomain());
  932. // display
  933. setResizable(true);
  934. pack();
  935. setResizable(false);
  936. setLocation((screen.width-getPreferredSize().width)/2,
  937.     (int) ((screen.height-getPreferredSize().height)/2*.7));
  938. setVisible(true);
  939. default_focus.requestFocus();
  940. // wait for user input
  941. try { wait(); } catch (InterruptedException e) { }
  942. setVisible(false);
  943. // reset popup
  944. remove(secure_note);
  945. remove(discard_note);
  946. left_panel.remove(ports_label);
  947. ((GridLayout) left_panel.getLayout()).setRows(4);
  948. right_panel.remove(ports_value);
  949. ((GridLayout) right_panel.getLayout()).setRows(4);
  950. remove(c_url_note);
  951. remove(comment_label);
  952. remove(comment_value);
  953. // handle accept/reject domain buttons
  954. if (accept_domain)
  955. {
  956.     String dom = domain.getText().trim().toLowerCase();
  957.     if (accept)
  958. h.addAcceptDomain(dom);
  959.     else
  960. h.addRejectDomain(dom);
  961. }
  962. return accept;
  963.     }
  964. }
  965. /**
  966.  * A simple separator element.
  967.  */
  968. class Separator extends Panel
  969. {
  970.     public void paint(Graphics g)
  971.     {
  972. int w = getSize().width,
  973.     h = getSize().height/2;
  974. g.setColor(Color.darkGray);
  975. g.drawLine(2, h-1, w-2, h-1);
  976. g.setColor(Color.white);
  977. g.drawLine(2, h, w-2, h);
  978.     }
  979.     public Dimension getMinimumSize()
  980.     {
  981. return new Dimension(4, 2);
  982.     }
  983. }