KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > HTTPClient > CookieModule


1 /*
2  * @(#)CookieModule.java 0.3-2 18/06/1999
3  *
4  * This file is part of the HTTPClient package
5  * Copyright (C) 1996-1999 Ronald Tschalär
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  */

28
29 package HTTPClient;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.io.FileInputStream;
34 import java.io.FileOutputStream;
35 import java.io.ObjectInputStream;
36 import java.io.ObjectOutputStream;
37 import java.net.ProtocolException;
38 import java.util.Date;
39 import java.util.Vector;
40 import java.util.Hashtable;
41 import java.util.Enumeration;
42 import java.util.StringTokenizer;
43
44 import java.awt.Frame;
45 import java.awt.Panel;
46 import java.awt.Label;
47 import java.awt.Color;
48 import java.awt.Button;
49 import java.awt.Graphics;
50 import java.awt.Dimension;
51 import java.awt.TextArea;
52 import java.awt.TextField;
53 import java.awt.GridLayout;
54 import java.awt.GridBagLayout;
55 import java.awt.GridBagConstraints;
56 import java.awt.event.ActionEvent;
57 import java.awt.event.ActionListener;
58 import java.awt.event.WindowEvent;
59 import java.awt.event.WindowAdapter;
60
61
62 /**
63  * This module handles Netscape cookies (also called Version 0 cookies)
64  * and Version 1 cookies. Specifically is reads the <var>Set-Cookie</var>
65  * and <var>Set-Cookie2</var> response headers and sets the <var>Cookie</var>
66  * and <var>Cookie2</var> headers as neccessary.
67  *
68  * <P>The accepting and sending of cookies is controlled by a
69  * <var>CookiePolicyHandler</var>. This allows you to fine tune your privacy
70  * preferences. A cookie is only added to the cookie list if the handler
71  * allows it, and a cookie from the cookie list is only sent if the handler
72  * allows it.
73  *
74  * <P>A cookie jar can be used to store cookies between sessions. This file is
75  * read when this class is loaded and is written when the application exits;
76  * only cookies from the default context are saved. The name of the file is
77  * controlled by the system property <var>HTTPClient.cookies.jar</var> and
78  * defaults to a system dependent name. The reading and saving of cookies is
79  * enabled by setting the system property <var>HTTPClient.cookies.save</var>
80  * to <var>true</var>.
81  *
82  * @see <a HREF="http://home.netscape.com/newsref/std/cookie_spec.html">Netscape's cookie spec</a>
83  * @see <a HREF="ftp://ds.internic.net/internet-drafts/draft-ietf-http-state-man-mec-10.txt">HTTP State Management Mechanism spec</a>
84  * @version 0.3-2 18/06/1999
85  * @author Ronald Tschalär
86  * @since V0.3
87  */

88
89 public class CookieModule implements HTTPClientModule, GlobalConstants
90 {
91     /** the list of known cookies */
92     private static Hashtable cookie_cntxt_list = new Hashtable();
93
94     /** the file to use for persistent cookie storage */
95     private static File cookie_jar = null;
96
97     /** an object, whose finalizer will save the cookies to the jar */
98     private static Object cookieSaver = null;
99
100     /** the cookie policy handler */
101     private static CookiePolicyHandler cookie_handler =
102                         new DefaultCookiePolicyHandler();
103
104
105
106     // read in cookies from disk at startup
107

108     static
109     {
110     boolean persist;
111     try
112         { persist = Boolean.getBoolean("HTTPClient.cookies.save"); }
113     catch (Exception e)
114         { persist = false; }
115
116     if (persist)
117     {
118         loadCookies();
119
120         // the nearest thing to atexit() I know of...
121

122         cookieSaver = new Object()
123         {
124             public void finalize() { saveCookies(); }
125         };
126         try
127         { System.runFinalizersOnExit(true); }
128         catch (Throwable t)
129         { }
130     }
131     }
132
133
134     private static void loadCookies()
135     {
136     // The isFile() etc need to be protected by the catch as signed
137
// applets may be allowed to read properties but not do IO
138
try
139     {
140         cookie_jar = new File(getCookieJarName());
141         if (cookie_jar.isFile() && cookie_jar.canRead())
142         {
143         ObjectInputStream ois =
144             new ObjectInputStream(new FileInputStream(cookie_jar));
145         cookie_cntxt_list.put(HTTPConnection.getDefaultContext(),
146                       (Hashtable) ois.readObject());
147         ois.close();
148         }
149     }
150     catch (Throwable t)
151         { cookie_jar = null; }
152     }
153
154
155     private static void saveCookies()
156     {
157     if (cookie_jar != null && (!cookie_jar.exists() ||
158          cookie_jar.isFile() && cookie_jar.canWrite()))
159     {
160         Hashtable cookie_list = new Hashtable();
161         Enumeration enum = Util.getList(cookie_cntxt_list,
162                         HTTPConnection.getDefaultContext())
163                    .elements();
164
165         // discard cookies which are not to be kept across sessions
166

167         while (enum.hasMoreElements())
168         {
169         Cookie cookie = (Cookie) enum.nextElement();
170         if (!cookie.discard())
171             cookie_list.put(cookie, cookie);
172         }
173
174
175         // save any remaining cookies in jar
176

177         if (cookie_list.size() > 0)
178         {
179         try
180         {
181             ObjectOutputStream oos =
182             new ObjectOutputStream(new FileOutputStream(cookie_jar));
183             oos.writeObject(cookie_list);
184             oos.close();
185         }
186         catch (Throwable t)
187             { }
188         }
189     }
190     }
191
192
193     private static String getCookieJarName()
194     {
195     String file = null;
196
197     try
198         { file = System.getProperty("HTTPClient.cookies.jar"); }
199     catch (Exception e)
200         { }
201
202     if (file == null)
203     {
204         // default to something reasonable
205

206         String os = System.getProperty("os.name");
207         if (os.equalsIgnoreCase("Windows 95") ||
208         os.equalsIgnoreCase("16-bit Windows") ||
209         os.equalsIgnoreCase("Windows"))
210         {
211         file = System.getProperty("java.home") +
212                File.separator + ".httpclient_cookies";
213         }
214         else if (os.equalsIgnoreCase("Windows NT"))
215         {
216         file = System.getProperty("user.home") +
217                File.separator + ".httpclient_cookies";
218         }
219         else if (os.equalsIgnoreCase("OS/2"))
220         {
221         file = System.getProperty("user.home") +
222                File.separator + ".httpclient_cookies";
223         }
224         else if (os.equalsIgnoreCase("Mac OS") ||
225              os.equalsIgnoreCase("MacOS"))
226         {
227         file = "System Folder" + File.separator +
228                "Preferences" + File.separator +
229                "HTTPClientCookies";
230         }
231         else // it's probably U*IX or VMS
232
{
233         file = System.getProperty("user.home") +
234                File.separator + ".httpclient_cookies";
235         }
236     }
237
238     return file;
239     }
240
241
242     // Constructors
243

244     CookieModule()
245     {
246     }
247
248
249     // Methods
250

251     /**
252      * Invoked by the HTTPClient.
253      */

254     public int requestHandler(Request req, Response[] resp)
255     {
256     // First remove any Cookie headers we might have set for a previous
257
// request
258

259     NVPair[] hdrs = req.getHeaders();
260     int length = hdrs.length;
261     for (int idx=0; idx<hdrs.length; idx++)
262     {
263         int beg = idx;
264         while (idx < hdrs.length &&
265            hdrs[idx].getName().equalsIgnoreCase("Cookie"))
266         idx++;
267
268         if (idx-beg > 0)
269         {
270         length -= idx-beg;
271         System.arraycopy(hdrs, idx, hdrs, beg, length-beg);
272         }
273     }
274     if (length < hdrs.length)
275     {
276         hdrs = Util.resizeArray(hdrs, length);
277         req.setHeaders(hdrs);
278     }
279
280
281     // Now set any new cookie headers
282

283     Hashtable cookie_list =
284         Util.getList(cookie_cntxt_list, req.getConnection().getContext());
285     if (cookie_list.size() == 0)
286         return REQ_CONTINUE; // no need to create a lot of objects
287

288     Vector names = new Vector();
289     Vector lens = new Vector();
290     boolean cookie2 = false;
291
292     synchronized(cookie_list)
293     {
294         Enumeration list = cookie_list.elements();
295         Vector remove_list = null;
296
297         while (list.hasMoreElements())
298         {
299         Cookie cookie = (Cookie) list.nextElement();
300
301         if (cookie.hasExpired())
302         {
303             if (remove_list == null) remove_list = new Vector();
304             remove_list.addElement(cookie);
305             continue;
306         }
307
308         if (cookie.sendWith(req) && (cookie_handler == null ||
309             cookie_handler.sendCookie(cookie, req)))
310         {
311             int len = cookie.getPath().length();
312             int idx;
313
314             // insert in correct position
315
for (idx=0; idx<lens.size(); idx++)
316             if (((Integer) lens.elementAt(idx)).intValue() < len)
317                 break;
318
319             names.insertElementAt(cookie.toExternalForm(), idx);
320             lens.insertElementAt(new Integer(len), idx);
321
322             if (cookie instanceof Cookie2) cookie2 = true;
323         }
324         }
325
326         // remove any marked cookies
327
// Note: we can't do this during the enumeration!
328
if (remove_list != null)
329         {
330         for (int idx=0; idx<remove_list.size(); idx++)
331             cookie_list.remove(remove_list.elementAt(idx));
332         }
333     }
334
335     if (!names.isEmpty())
336     {
337         StringBuffer value = new StringBuffer();
338
339         if (cookie2)
340         value.append("$Version=\"1\"; ");
341
342         value.append((String) names.elementAt(0));
343         for (int idx=1; idx<names.size(); idx++)
344         {
345         value.append("; ");
346         value.append((String) names.elementAt(idx));
347         }
348         hdrs = Util.resizeArray(hdrs, hdrs.length+1);
349         hdrs[hdrs.length-1] = new NVPair("Cookie", value.toString());
350
351         // add Cookie2 header if necessary
352
if (!cookie2)
353         {
354         int idx;
355         for (idx=0; idx<hdrs.length; idx++)
356             if (hdrs[idx].getName().equalsIgnoreCase("Cookie2"))
357             break;
358         if (idx == hdrs.length)
359         {
360             hdrs = Util.resizeArray(hdrs, hdrs.length+1);
361             hdrs[hdrs.length-1] =
362                     new NVPair("Cookie2", "$Version=\"1\"");
363         }
364         }
365
366         req.setHeaders(hdrs);
367
368         if (DebugMods)
369         System.err.println("CookM: Sending cookies '" + value + "'");
370     }
371
372     return REQ_CONTINUE;
373     }
374
375
376     /**
377      * Invoked by the HTTPClient.
378      */

379     public void responsePhase1Handler(Response resp, RoRequest req)
380         throws IOException
381     {
382     String set_cookie = resp.getHeader("Set-Cookie");
383     String set_cookie2 = resp.getHeader("Set-Cookie2");
384     if (set_cookie == null && set_cookie2 == null)
385         return;
386
387     resp.deleteHeader("Set-Cookie");
388     resp.deleteHeader("Set-Cookie2");
389
390     if (set_cookie != null)
391         handleCookie(set_cookie, false, req, resp);
392     if (set_cookie2 != null)
393         handleCookie(set_cookie2, true, req, resp);
394     }
395
396
397     /**
398      * Invoked by the HTTPClient.
399      */

400     public int responsePhase2Handler(Response resp, Request req)
401     {
402     return RSP_CONTINUE;
403     }
404
405
406     /**
407      * Invoked by the HTTPClient.
408      */

409     public void responsePhase3Handler(Response resp, RoRequest req)
410     {
411     }
412
413
414     /**
415      * Invoked by the HTTPClient.
416      */

417     public void trailerHandler(Response resp, RoRequest req) throws IOException
418     {
419     String set_cookie = resp.getTrailer("Set-Cookie");
420     String set_cookie2 = resp.getHeader("Set-Cookie2");
421     if (set_cookie == null && set_cookie2 == null)
422         return;
423
424     resp.deleteTrailer("Set-Cookie");
425     resp.deleteTrailer("Set-Cookie2");
426
427     if (set_cookie != null)
428         handleCookie(set_cookie, false, req, resp);
429     if (set_cookie2 != null)
430         handleCookie(set_cookie2, true, req, resp);
431     }
432
433
434     private void handleCookie(String set_cookie, boolean cookie2, RoRequest req,
435                   Response resp)
436         throws ProtocolException
437     {
438     Cookie[] cookies;
439     if (cookie2)
440         cookies = Cookie2.parse(set_cookie, req);
441     else
442         cookies = Cookie.parse(set_cookie, req);
443
444     if (DebugMods)
445     {
446         System.err.println("CookM: Received and parsed " + cookies.length +
447                    " cookies:");
448         for (int idx=0; idx<cookies.length; idx++)
449         System.err.println("CookM: Cookie " + idx + ": " +cookies[idx]);
450     }
451
452     Hashtable cookie_list =
453         Util.getList(cookie_cntxt_list, req.getConnection().getContext());
454     synchronized(cookie_list)
455     {
456         for (int idx=0; idx<cookies.length; idx++)
457         {
458         Cookie cookie = (Cookie) cookie_list.get(cookies[idx]);
459         if (cookie != null && cookies[idx].hasExpired())
460             cookie_list.remove(cookie); // expired, so remove
461
else // new or replaced
462
{
463             if (cookie_handler == null ||
464             cookie_handler.acceptCookie(cookies[idx], req, resp))
465             cookie_list.put(cookies[idx], cookies[idx]);
466         }
467         }
468     }
469     }
470
471
472     /**
473      * Discard all cookies for all contexts. Cookies stored in persistent
474      * storage are not affected.
475      */

476     public static void discardAllCookies()
477     {
478     cookie_cntxt_list.clear();
479     }
480
481
482     /**
483      * Discard all cookies for the given context. Cookies stored in persistent
484      * storage are not affected.
485      *
486      * @param context the context Object
487      */

488     public static void discardAllCookies(Object context)
489     {
490     Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
491     cookie_list.clear();
492     }
493
494
495     /**
496      * List all stored cookies for all contexts.
497      *
498      * @return an array of all Cookies
499      * @since V0.3-1
500      */

501     public static Cookie[] listAllCookies()
502     {
503     synchronized(cookie_cntxt_list)
504     {
505         Cookie[] cookies = new Cookie[0];
506         int idx = 0;
507
508         Enumeration cntxt_list = cookie_cntxt_list.elements();
509         while (cntxt_list.hasMoreElements())
510         {
511         Hashtable cntxt = (Hashtable) cntxt_list.nextElement();
512         synchronized(cntxt)
513         {
514             cookies = Util.resizeArray(cookies, idx+cntxt.size());
515             Enumeration cookie_list = cntxt.elements();
516             while (cookie_list.hasMoreElements())
517             cookies[idx++] = (Cookie) cookie_list.nextElement();
518         }
519         }
520
521         return cookies;
522     }
523     }
524
525
526     /**
527      * List all stored cookies for a given context.
528      *
529      * @param context the context Object.
530      * @return an array of Cookies
531      * @since V0.3-1
532      */

533     public static Cookie[] listAllCookies(Object context)
534     {
535     Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
536
537     synchronized(cookie_list)
538     {
539         Cookie[] cookies = new Cookie[cookie_list.size()];
540         int idx = 0;
541
542         Enumeration enum = cookie_list.elements();
543         while (enum.hasMoreElements())
544         cookies[idx++] = (Cookie) enum.nextElement();
545
546         return cookies;
547     }
548     }
549
550
551     /**
552      * Add the specified cookie to the list of cookies in the default context.
553      * If a compatible cookie (as defined by <var>Cookie.equals()</var>)
554      * already exists in the list then it is replaced with the new cookie.
555      *
556      * @param cookie the Cookie to add
557      * @since V0.3-1
558      */

559     public static void addCookie(Cookie cookie)
560     {
561     Hashtable cookie_list =
562         Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
563     cookie_list.put(cookie, cookie);
564     }
565
566
567     /**
568      * Add the specified cookie to the list of cookies for the specified
569      * context. If a compatible cookie (as defined by
570      * <var>Cookie.equals()</var>) already exists in the list then it is
571      * replaced with the new cookie.
572      *
573      * @param cookie the cookie to add
574      * @param context the context Object.
575      * @since V0.3-1
576      */

577     public static void addCookie(Cookie cookie, Object context)
578     {
579     Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
580     cookie_list.put(cookie, cookie);
581     }
582
583
584     /**
585      * Remove the specified cookie from the list of cookies in the default
586      * context. If the cookie is not found in the list then this method does
587      * nothing.
588      *
589      * @param cookie the Cookie to remove
590      * @since V0.3-1
591      */

592     public static void removeCookie(Cookie cookie)
593     {
594     Hashtable cookie_list =
595         Util.getList(cookie_cntxt_list, HTTPConnection.getDefaultContext());
596     cookie_list.remove(cookie);
597     }
598
599
600     /**
601      * Remove the specified cookie from the list of cookies for the specified
602      * context. If the cookie is not found in the list then this method does
603      * nothing.
604      *
605      * @param cookie the cookie to remove
606      * @param context the context Object
607      * @since V0.3-1
608      */

609     public static void removeCookie(Cookie cookie, Object context)
610     {
611     Hashtable cookie_list = Util.getList(cookie_cntxt_list, context);
612     cookie_list.remove(cookie);
613     }
614
615
616     /**
617      * Sets a new cookie policy handler. This handler will be called for each
618      * cookie that a server wishes to set and for each cookie that this
619      * module wishes to send with a request. In either case the handler may
620      * allow or reject the operation. If you wish to blindly accept and send
621      * all cookies then just disable the handler with
622      * <code>CookieModule.setCookiePolicyHandler(null);</code>.
623      *
624      * <P>At initialization time a default handler is installed. This
625      * handler allows all cookies to be sent. For any cookie that a server
626      * wishes to be set two lists are consulted. If the server matches any
627      * host or domain in the reject list then the cookie is rejected; if
628      * the server matches any host or domain in the accept list then the
629      * cookie is accepted (in that order). If no host or domain match is
630      * found in either of these two lists and user interaction is allowed
631      * then a dialog box is poped up to ask the user whether to accept or
632      * reject the cookie; if user interaction is not allowed the cookie is
633      * accepted.
634      *
635      * <P>The accept and reject lists in the default handler are initialized
636      * at startup from the two properties
637      * <var>HTTPClient.cookies.hosts.accept</var> and
638      * <var>HTTPClient.cookies.hosts.reject</var>. These properties must
639      * contain a "|" separated list of host and domain names. All names
640      * beginning with a "." are treated as domain names, all others as host
641      * names. An empty string which will match all hosts. The two lists are
642      * further expanded if the user chooses one of the "Accept All from Domain"
643      * or "Reject All from Domain" buttons in the dialog box.
644      *
645      * <P>Note: the default handler does not implement the rules concerning
646      * unverifiable transactions (section 4.3.5,
647      * <A HREF="http://www.cis.ohio-state.edu/htbin/rfc/rfc2109">RFC-2109</A>).
648      * The reason for this is simple: the default handler knows nothing
649      * about the application using this client, and it therefore does not
650      * have enough information to determine when a request is verifiable
651      * and when not. You are therefore encouraged to provide your own handler
652      * which implements section 4.3.5 (use the
653      * <var>CookiePolicyHandler.sendCookie</var> method for this).
654      *
655      * @param the new policy handler
656      * @return the previous policy handler
657      */

658     public static synchronized CookiePolicyHandler
659                 setCookiePolicyHandler(CookiePolicyHandler handler)
660     {
661     CookiePolicyHandler old = cookie_handler;
662     cookie_handler = handler;
663     return old;
664     }
665 }
666
667
668 /**
669  * A simple cookie policy handler.
670  */

671
672 class DefaultCookiePolicyHandler implements CookiePolicyHandler
673 {
674     /** a list of all hosts and domains from which to silently accept cookies */
675     private String[] accept_domains = new String[0];
676
677     /** a list of all hosts and domains from which to silently reject cookies */
678     private String[] reject_domains = new String[0];
679
680     /** the query popup */
681     private BasicCookieBox popup = null;
682
683
684     DefaultCookiePolicyHandler()
685     {
686     // have all cookies been accepted or rejected?
687
String list;
688
689     try
690         { list = System.getProperty("HTTPClient.cookies.hosts.accept"); }
691     catch (Exception e)
692         { list = null; }
693     String[] domains = Util.splitProperty(list);
694     for (int idx=0; idx<domains.length; idx++)
695         addAcceptDomain(domains[idx].toLowerCase());
696
697     try
698         { list = System.getProperty("HTTPClient.cookies.hosts.reject"); }
699     catch (Exception e)
700         { list = null; }
701     domains = Util.splitProperty(list);
702     for (int idx=0; idx<domains.length; idx++)
703         addRejectDomain(domains[idx].toLowerCase());
704     }
705
706
707     /**
708      * returns whether this cookie should be accepted. First checks the
709      * stored lists of accept and reject domains, and if it is neither
710      * accepted nor rejected by these then query the user via a popup.
711      *
712      * @param cookie the cookie in question
713      * @param req the request
714      * @param resp the response
715      * @return true if we accept this cookie.
716      */

717     public boolean acceptCookie(Cookie cookie, RoRequest req, RoResponse resp)
718     {
719     String server = req.getConnection().getHost();
720     if (server.indexOf('.') == -1) server += ".local";
721
722
723     // Check lists. Reject takes priority over accept
724

725     for (int idx=0; idx<reject_domains.length; idx++)
726     {
727         if (reject_domains[idx].length() == 0 ||
728         reject_domains[idx].charAt(0) == '.' &&
729         server.endsWith(reject_domains[idx]) ||
730         reject_domains[idx].charAt(0) != '.' &&
731         server.equals(reject_domains[idx]))
732             return false;
733     }
734
735     for (int idx=0; idx<accept_domains.length; idx++)
736     {
737         if (accept_domains[idx].length() == 0 ||
738         accept_domains[idx].charAt(0) == '.' &&
739         server.endsWith(accept_domains[idx]) ||
740         accept_domains[idx].charAt(0) != '.' &&
741         server.equals(accept_domains[idx]))
742             return true;
743     }
744
745
746     // Ok, not in any list, so ask the user (if allowed).
747

748     if (!req.allowUI()) return true;
749
750     if (popup == null)
751         popup = new BasicCookieBox();
752
753     return popup.accept(cookie, this, server);
754     }
755
756
757     /**
758      * This handler just allows all cookies to be sent which were accepted
759      * (i.e. no further restrictions are placed on the sending of cookies).
760      *
761      * @return true
762      */

763     public boolean sendCookie(Cookie cookie, RoRequest req)
764     {
765     return true;
766     }
767
768
769     void addAcceptDomain(String domain)
770     {
771     if (domain.indexOf('.') == -1) domain += ".local";
772
773     for (int idx=0; idx<accept_domains.length; idx++)
774     {
775         if (domain.endsWith(accept_domains[idx]))
776         return;
777         if (accept_domains[idx].endsWith(domain))
778         {
779         accept_domains[idx] = domain;
780         return;
781         }
782     }
783     accept_domains =
784             Util.resizeArray(accept_domains, accept_domains.length+1);
785     accept_domains[accept_domains.length-1] = domain;
786     }
787
788     void addRejectDomain(String domain)
789     {
790     if (domain.indexOf('.') == -1) domain += ".local";
791
792     for (int idx=0; idx<reject_domains.length; idx++)
793     {
794         if (domain.endsWith(reject_domains[idx]))
795         return;
796         if (reject_domains[idx].endsWith(domain))
797         {
798         reject_domains[idx] = domain;
799         return;
800         }
801     }
802
803     reject_domains =
804             Util.resizeArray(reject_domains, reject_domains.length+1);
805     reject_domains[reject_domains.length-1] = domain;
806     }
807 }
808
809
810 /**
811  * A simple popup that asks whether the cookie should be accepted or rejected,
812  * or if cookies from whole domains should be silently accepted or rejected.
813  *
814  * @version 0.3-2 18/06/1999
815  * @author Ronald Tschalär
816  */

817 class BasicCookieBox extends Frame
818 {
819     private final static String title = "Set Cookie Request";
820     private Dimension screen;
821     private GridBagConstraints constr;
822     private Label name_value_label;
823     private Label domain_value;
824     private Label ports_label;
825     private Label ports_value;
826     private Label path_value;
827     private Label expires_value;
828     private Label discard_note;
829     private Label secure_note;
830     private Label c_url_note;
831     private Panel left_panel;
832     private Panel right_panel;
833     private Label comment_label;
834     private TextArea comment_value;
835     private TextField domain;
836     private Button default_focus;
837     private boolean accept;
838     private boolean accept_domain;
839
840
841     /**
842      * Constructs the popup.
843      */

844     BasicCookieBox()
845     {
846     super(title);
847
848     screen = getToolkit().getScreenSize();
849
850     addNotify();
851     addWindowListener(new Close());
852
853     GridBagLayout layout;
854     setLayout(layout = new GridBagLayout());
855     constr = new GridBagConstraints();
856
857     constr.gridwidth = GridBagConstraints.REMAINDER;
858     constr.anchor = GridBagConstraints.WEST;
859     add(new Label("The server would like to set the following cookie:"), constr);
860
861     Panel p = new Panel();
862     left_panel = new Panel();
863     left_panel.setLayout(new GridLayout(4,1));
864     left_panel.add(new Label("Name=Value:"));
865     left_panel.add(new Label("Domain:"));
866     left_panel.add(new Label("Path:"));
867     left_panel.add(new Label("Expires:"));
868     ports_label = new Label("Ports:");
869     p.add(left_panel);
870
871     right_panel = new Panel();
872     right_panel.setLayout(new GridLayout(4,1));
873     right_panel.add(name_value_label = new Label());
874     right_panel.add(domain_value = new Label());
875     right_panel.add(path_value = new Label());
876     right_panel.add(expires_value = new Label());
877     ports_value = new Label();
878     p.add(right_panel);
879     add(p, constr);
880     secure_note = new Label("This cookie will only be sent over secure connections");
881     discard_note = new Label("This cookie will be discarded at the end of the session");
882     c_url_note = new Label("");
883     comment_label = new Label("Comment:");
884     comment_value =
885         new TextArea("", 3, 45, TextArea.SCROLLBARS_VERTICAL_ONLY);
886     comment_value.setEditable(false);
887
888     add(new Panel(), constr);
889
890     constr.gridwidth = 1;
891     constr.anchor = GridBagConstraints.CENTER;
892     constr.weightx = 1.0;
893     add(default_focus = new Button("Accept"), constr);
894     default_focus.addActionListener(new Accept());
895
896     Button b;
897     constr.gridwidth = GridBagConstraints.REMAINDER;
898     add(b= new Button("Reject"), constr);
899     b.addActionListener(new Reject());
900
901     constr.weightx = 0.0;
902     p = new Separator();
903     constr.fill = GridBagConstraints.HORIZONTAL;
904     add(p, constr);
905
906     constr.fill = GridBagConstraints.NONE;
907     constr.anchor = GridBagConstraints.WEST;
908     add(new Label("Accept/Reject all cookies from a host or domain:"), constr);
909
910     p = new Panel();
911     p.add(new Label("Host/Domain:"));
912     p.add(domain = new TextField(30));
913     add(p, constr);
914
915     add(new Label("domains are characterized by a leading dot (`.');"), constr);
916     add(new Label("an empty string matches all hosts"), constr);
917
918     constr.anchor = GridBagConstraints.CENTER;
919     constr.gridwidth = 1;
920     constr.weightx = 1.0;
921     add(b = new Button("Accept All"), constr);
922     b.addActionListener(new AcceptDomain());
923
924     constr.gridwidth = GridBagConstraints.REMAINDER;
925     add(b = new Button("Reject All"), constr);
926     b.addActionListener(new RejectDomain());
927
928     pack();
929
930     constr.anchor = GridBagConstraints.WEST;
931     constr.gridwidth = GridBagConstraints.REMAINDER;
932     }
933
934
935     public Dimension getMaximumSize()
936     {
937     return new Dimension(screen.width*3/4, screen.height*3/4);
938     }
939
940
941     /**
942      * our event handlers
943      */

944     private class Accept implements ActionListener
945     {
946         public void actionPerformed(ActionEvent ae)
947         {
948         accept = true;
949         accept_domain = false;
950             synchronized (BasicCookieBox.this)
951         { BasicCookieBox.this.notifyAll(); }
952         }
953     }
954
955     private class Reject implements ActionListener
956     {
957         public void actionPerformed(ActionEvent ae)
958     {
959         accept = false;
960         accept_domain = false;
961             synchronized (BasicCookieBox.this)
962         { BasicCookieBox.this.notifyAll(); }
963     }
964     }
965
966     private class AcceptDomain implements ActionListener
967     {
968         public void actionPerformed(ActionEvent ae)
969         {
970         accept = true;
971         accept_domain = true;
972             synchronized (BasicCookieBox.this)
973         { BasicCookieBox.this.notifyAll(); }
974     }
975     }
976
977     private class RejectDomain implements ActionListener
978     {
979         public void actionPerformed(ActionEvent ae)
980     {
981         accept = false;
982         accept_domain = true;
983             synchronized (BasicCookieBox.this)
984         { BasicCookieBox.this.notifyAll(); }
985     }
986     }
987
988
989     private class Close extends WindowAdapter
990     {
991     public void windowClosing(WindowEvent we)
992     {
993         new Reject().actionPerformed(null);
994     }
995     }
996
997
998     /**
999      * the method called by the DefaultCookiePolicyHandler.
1000     *
1001     * @return true if the cookie should be accepted
1002     */

1003    public synchronized boolean accept(Cookie cookie,
1004                       DefaultCookiePolicyHandler h,
1005                       String server)
1006    {
1007    // set the new values
1008

1009    name_value_label.setText(cookie.getName() + "=" + cookie.getValue());
1010    domain_value.setText(cookie.getDomain());
1011    path_value.setText(cookie.getPath());
1012    if (cookie.expires() == null)
1013        expires_value.setText("never");
1014    else
1015        expires_value.setText(cookie.expires().toString());
1016    int pos = 2;
1017    if (cookie.isSecure())
1018        add(secure_note, constr, pos++);
1019    if (cookie.discard())
1020        add(discard_note, constr, pos++);
1021
1022    if (cookie instanceof Cookie2)
1023    {
1024        Cookie2 cookie2 = (Cookie2) cookie;
1025
1026        // set ports list
1027
if (cookie2.getPorts() != null)
1028        {
1029        ((GridLayout) left_panel.getLayout()).setRows(5);
1030        left_panel.add(ports_label, 2);
1031        ((GridLayout) right_panel.getLayout()).setRows(5);
1032        int[] ports = cookie2.getPorts();
1033        StringBuffer plist = new StringBuffer();
1034        plist.append(ports[0]);
1035        for (int idx=1; idx<ports.length; idx++)
1036        {
1037            plist.append(", ");
1038            plist.append(ports[idx]);
1039        }
1040        ports_value.setText(plist.toString());
1041        right_panel.add(ports_value, 2);
1042        }
1043
1044        // set comment url
1045
if (cookie2.getCommentURL() != null)
1046        {
1047        c_url_note.setText("For more info on this cookie see: " +
1048                    cookie2.getCommentURL());
1049        add(c_url_note, constr, pos++);
1050        }
1051
1052        // set comment
1053
if (cookie2.getComment() != null)
1054        {
1055        comment_value.setText(cookie2.getComment());
1056        add(comment_label, constr, pos++);
1057        add(comment_value, constr, pos++);
1058        }
1059    }
1060
1061
1062    // invalidate all labels, so that new values are displayed correctly
1063

1064    name_value_label.invalidate();
1065    domain_value.invalidate();
1066    ports_value.invalidate();
1067    path_value.invalidate();
1068    expires_value.invalidate();
1069    left_panel.invalidate();
1070    right_panel.invalidate();
1071    secure_note.invalidate();
1072    discard_note.invalidate();
1073    c_url_note.invalidate();
1074    comment_value.invalidate();
1075    invalidate();
1076
1077
1078    // set default domain test
1079

1080    domain.setText(cookie.getDomain());
1081
1082
1083    // display
1084

1085    setResizable(true);
1086    pack();
1087    setResizable(false);
1088    setLocation((screen.width-getPreferredSize().width)/2,
1089            (int) ((screen.height-getPreferredSize().height)/2*.7));
1090    setVisible(true);
1091    default_focus.requestFocus();
1092
1093
1094    // wait for user input
1095

1096    try { wait(); } catch (InterruptedException e) { }
1097
1098    setVisible(false);
1099
1100
1101    // reset popup
1102

1103    remove(secure_note);
1104    remove(discard_note);
1105    left_panel.remove(ports_label);
1106    ((GridLayout) left_panel.getLayout()).setRows(4);
1107    right_panel.remove(ports_value);
1108    ((GridLayout) right_panel.getLayout()).setRows(4);
1109    remove(c_url_note);
1110    remove(comment_label);
1111    remove(comment_value);
1112
1113
1114    // handle accept/reject domain buttons
1115

1116    if (accept_domain)
1117    {
1118        String dom = domain.getText().trim().toLowerCase();
1119
1120        if (accept)
1121        h.addAcceptDomain(dom);
1122        else
1123        h.addRejectDomain(dom);
1124    }
1125
1126    return accept;
1127    }
1128}
1129
1130
1131/**
1132 * A simple separator element.
1133 */

1134class Separator extends Panel
1135{
1136    public void paint(Graphics g)
1137    {
1138    int w = getSize().width,
1139        h = getSize().height/2;
1140
1141    g.setColor(Color.darkGray);
1142    g.drawLine(2, h-1, w-2, h-1);
1143    g.setColor(Color.white);
1144    g.drawLine(2, h, w-2, h);
1145    }
1146
1147    public Dimension getMinimumSize()
1148    {
1149    return new Dimension(4, 2);
1150    }
1151}
1152
1153
Popular Tags