1   /*
2    * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/TestCookie.java,v 1.28 2004/02/22 18:08:49 olegk Exp $
3    * $Revision: 1.28 $
4    * $Date: 2004/02/22 18:08:49 $
5    * ====================================================================
6    *
7    *  Copyright 1999-2004 The Apache Software Foundation
8    *
9    *  Licensed under the Apache License, Version 2.0 (the "License");
10   *  you may not use this file except in compliance with the License.
11   *  You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing, software
16   *  distributed under the License is distributed on an "AS IS" BASIS,
17   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   *  See the License for the specific language governing permissions and
19   *  limitations under the License.
20   * ====================================================================
21   *
22   * This software consists of voluntary contributions made by many
23   * individuals on behalf of the Apache Software Foundation.  For more
24   * information on the Apache Software Foundation, please see
25   * <http://www.apache.org/>.
26   *
27   * [Additional notices, if required by prior licensing conditions]
28   *
29   */
30  
31  package org.apache.commons.httpclient;
32  
33  import java.util.Date;
34  import java.util.Iterator;
35  import java.util.SortedSet;
36  import java.util.TreeSet;
37  import java.util.Vector;
38  
39  import junit.framework.Test;
40  import junit.framework.TestSuite;
41  
42  import org.apache.commons.httpclient.cookie.CookiePolicy;
43  import org.apache.commons.httpclient.cookie.CookieSpec;
44  import org.apache.commons.httpclient.cookie.CookieSpecBase;
45  import org.apache.commons.httpclient.cookie.MalformedCookieException;
46  import org.apache.commons.httpclient.methods.GetMethod;
47  
48  
49  /***
50   * Test cases for Cookie
51   *
52   * @author BC Holmes
53   * @author Rod Waldhoff
54   * @author dIon Gillard
55   * @author <a href="mailto:JEvans@Cyveillance.com">John Evans</a>
56   * @author Marc A. Saegesser
57   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
58   * @version $Revision: 1.28 $
59   */
60  public class TestCookie extends TestNoHostBase {
61  
62  
63      // -------------------------------------------------------------- Constants
64  
65      private static final String DOMAIN_NAME = "www.apache.org";
66      private static final String TEST_COOKIE = "cookie-name=cookie-value";
67      private static final String OLD_EXPIRY = "Expires=Thu, 01-Jan-1970 00:00:10 GMT";
68      private static final String SEP = ";";
69      private static final String ROOT_PATH = "/";
70      private static final int DEFAULT_PORT = 80;
71  
72      private String[] testName = { "custno", "name", "name" };
73      private String[] testValue = { "12345", "John", "Doe, John" };
74      private String[] testDomain = { "www.apache.org", ".apache.org",
75          ".apache.org" };
76  
77      // ------------------------------------------------------------ Constructor
78  
79  
80      public TestCookie(String name) {
81          super(name);
82      }
83  
84  
85      // ------------------------------------------------------- TestCase Methods
86  
87  
88      public static Test suite() {
89          return new TestSuite(TestCookie.class);
90      }
91  
92  
93      // ------------------------------------------------------- Helper Methods
94  
95  	private static Cookie[] cookieParse(String policy, String host, String path, boolean isSecure, Header setHeader)
96  	  throws MalformedCookieException 
97  	{
98  		CookieSpec parser = CookiePolicy.getCookieSpec(policy);
99  		Cookie[] cookies = parser.parse(host, DEFAULT_PORT, path, isSecure, setHeader);
100 		if (cookies != null)
101 		{
102 			for(int i = 0; i < cookies.length; i++)
103 			{
104 				parser.validate(host, DEFAULT_PORT, path, isSecure, cookies[i]);
105 			}
106 		}
107 		return cookies;
108 	}
109 
110 
111 	private static Cookie[] cookieParse(String host, String path, boolean isSecure, Header setHeader)
112 	  throws MalformedCookieException 
113 	{
114 		return cookieParse(CookiePolicy.RFC_2109, host, path, isSecure, setHeader);
115 	}
116 
117 
118 	private static Cookie[] cookieParse(String host, String path, Header setHeader)
119 	  throws MalformedCookieException 
120 	{
121 		return cookieParse(CookiePolicy.RFC_2109, host, path, false, setHeader);
122 	}
123 
124 
125 	private static Cookie[] netscapeCcookieParse(String host, String path, Header setHeader)
126 	  throws MalformedCookieException 
127 	{
128 		return cookieParse(CookiePolicy.NETSCAPE, host, path, false, setHeader);
129 	}
130 
131 
132     public static Header cookieCreateHeader(String policy, String domain, int port, String path, boolean secure, Cookie[] cookies)
133     {
134         CookieSpec matcher = CookiePolicy.getCookieSpec(policy);
135         cookies = matcher.match(domain, port, path, secure, cookies);
136         if ((cookies != null) && (cookies.length > 0))
137         {
138             return matcher.formatCookieHeader(cookies);
139         }
140         else
141         {
142             return null;
143         } 
144     }
145 
146     public static Header cookieCreateHeader(String domain, int port, String path, boolean secure, Cookie[] cookies)
147     {
148     	return cookieCreateHeader(CookiePolicy.RFC_2109, domain, port, path, secure, cookies);
149     }
150 
151 
152     public boolean cookieMatch(String policy, String domain, int port, String path, boolean secure, Cookie cookie)
153     {
154         CookieSpec matcher = CookiePolicy.getCookieSpec(policy);
155         return matcher.match(domain, port, path, secure, cookie);
156     }
157 
158 
159     public boolean cookieMatch(String domain, int port, String path, boolean secure, Cookie cookie)
160     {
161         return cookieMatch(CookiePolicy.RFC_2109, domain, port, path, secure, cookie);
162     }
163 
164     // ------------------------------------------------------------ Parse1 Test
165 
166 
167     /***
168      * Test basic parse (with various spacings
169      */
170     public void testParse1() throws Exception {
171         String headerValue = "custno = 12345; comment=test; version=1," +
172             " name=John; version=1; max-age=600; secure; domain=.apache.org";
173         Cookie[] cookies = cookieParse(DOMAIN_NAME,"/", true, new Header(
174             "set-cookie", headerValue));
175         checkResultsOfParse(cookies, 2, 0);
176     }
177 
178 
179     protected void checkResultsOfParse(
180         Cookie[] cookies, int length, int offset) throws Exception {
181 
182         assertTrue("number of cookies should be " + length + ", but is " +
183                cookies.length + " instead.", cookies.length == length);
184 
185         for (int i = 0; i < cookies.length; i++) {
186 
187             assertTrue("Name of cookie " + i + " should be \"" +
188                    testName[i+offset] + "\", but is " + cookies[i].getName() +
189                    " instead.",
190                    testName[i+offset].equals(cookies[i].getName()));
191             assertTrue("Value of cookie " + i + " should be \"" +
192                    testValue[i+offset] + "\", but is " +
193                    cookies[i].getValue() + " instead.",
194                    testValue[i+offset].equals(cookies[i].getValue()));
195             assertTrue("Domain of cookie " + i + " should be \"" +
196                    testDomain[i+offset] + "\", but is " +
197                    cookies[i].getDomain() + " instead.",
198                    testDomain[i+offset].equalsIgnoreCase(
199                        cookies[i].getDomain()));
200         }
201     }
202 
203 
204     // ------------------------------------------------------------ Parse2 Test
205 
206 
207     /***
208      * Test no spaces
209      */
210     public void testParse2() throws Exception {
211         String headerValue = "custno=12345;comment=test; version=1," +
212             "name=John;version=1;max-age=600;secure;domain=.apache.org";
213         Cookie[] cookies = cookieParse(DOMAIN_NAME, "/", true, new Header(
214             "set-cookie", headerValue));
215         checkResultsOfParse(cookies, 2, 0);
216     }
217 
218 
219     // ------------------------------------------------------------ Parse3 Test
220 
221 
222     /***
223      * Test parse with quoted text
224      */
225     public void testParse3() throws Exception {
226         String headerValue =
227             "name=\"Doe, John\";version=1;max-age=600;secure;domain=.apache.org";
228         Cookie[] cookies = cookieParse(DOMAIN_NAME,"/", true, new Header(
229             "set-cookie", headerValue));
230         checkResultsOfParse(cookies, 1, 2);
231     }
232 
233     // ------------------------------------------------------------- More Tests
234 
235     // see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=5279
236     public void testQuotedExpiresAttribute() throws Exception {
237         String headerValue = "custno=12345;Expires='Thu, 01-Jan-2070 00:00:10 GMT'";
238         Cookie[] cookies = cookieParse(DOMAIN_NAME,"/",true,new Header(
239             "set-cookie", headerValue));
240         assertNotNull("Expected some cookies",cookies);
241         assertEquals("Expected 1 cookie",1,cookies.length);
242         assertNotNull("Expected cookie to have getExpiryDate",cookies[0].getExpiryDate());
243     }
244 
245     public void testSecurityError() throws Exception {
246         String headerValue = "custno=12345;comment=test; version=1," +
247             "name=John;version=1;max-age=600;secure;domain=jakarta.apache.org";
248         try {
249             Cookie[] cookies = cookieParse(DOMAIN_NAME, "/", new Header(
250                 "set-cookie", headerValue));
251             fail("HttpException exception should have been thrown");
252         } catch (HttpException e) {
253             // expected
254         }
255     }
256 
257     public void testParseSimple() throws Exception {
258         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value");
259         Cookie[] parsed = cookieParse("127.0.0.1","/path/path",setCookie);
260         assertEquals("Found 1 cookie.",1,parsed.length);
261         assertEquals("Name","cookie-name",parsed[0].getName());
262         assertEquals("Value","cookie-value",parsed[0].getValue());
263         assertTrue("Comment",null == parsed[0].getComment());
264         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
265         //assertTrue("isToBeDiscarded",parsed[0].isToBeDiscarded());
266         assertTrue("isPersistent",!parsed[0].isPersistent());
267         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
268         assertEquals("Path","/path",parsed[0].getPath());
269         assertTrue("Secure",!parsed[0].getSecure());
270         assertEquals("Version",0,parsed[0].getVersion());
271     }
272  
273  
274     public void testParseSimple2() throws Exception {
275         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value");
276         Cookie[] parsed = cookieParse("127.0.0.1","/path",setCookie);
277         assertEquals("Found 1 cookie.",1,parsed.length);
278         assertEquals("Name","cookie-name",parsed[0].getName());
279         assertEquals("Value","cookie-value",parsed[0].getValue());
280         assertTrue("Comment",null == parsed[0].getComment());
281         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
282         //assertTrue("isToBeDiscarded",parsed[0].isToBeDiscarded());
283         assertTrue("isPersistent",!parsed[0].isPersistent());
284         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
285         assertEquals("Path","/",parsed[0].getPath());
286         assertTrue("Secure",!parsed[0].getSecure());
287         assertEquals("Version",0,parsed[0].getVersion());
288     }
289  
290  
291     public void testParseNoValue() throws Exception {
292         Header setCookie = new Header("Set-Cookie","cookie-name=");
293         Cookie[] parsed = cookieParse("127.0.0.1","/",setCookie);
294         assertEquals("Found 1 cookie.",1,parsed.length);
295         assertEquals("Name","cookie-name",parsed[0].getName());
296         assertTrue("Value",null == parsed[0].getValue());
297         assertTrue("Comment",null == parsed[0].getComment());
298         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
299         //assertTrue("isToBeDiscarded",parsed[0].isToBeDiscarded());
300         assertTrue("isPersistent",!parsed[0].isPersistent());
301         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
302         assertEquals("Path","/",parsed[0].getPath());
303         assertTrue("Secure",!parsed[0].getSecure());
304         assertEquals("Version",0,parsed[0].getVersion());
305     }
306 
307     public void testParseWithWhiteSpace() throws Exception {
308         Header setCookie = new Header("Set-Cookie"," cookie-name  =    cookie-value  ");
309         Cookie[] parsed = cookieParse("127.0.0.1","/",setCookie);
310         assertEquals("Found 1 cookie.",1,parsed.length);
311         assertEquals("Name","cookie-name",parsed[0].getName());
312         assertEquals("Value","cookie-value",parsed[0].getValue());
313         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
314         assertEquals("Path","/",parsed[0].getPath());
315         assertTrue("Secure",!parsed[0].getSecure());
316         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
317         assertTrue("Comment",null == parsed[0].getComment());
318     }
319 
320     public void testParseWithQuotes() throws Exception {
321         Header setCookie = new Header("Set-Cookie"," cookie-name  =  \" cookie-value \" ;path=/");
322         Cookie[] parsed = cookieParse("127.0.0.1","/",setCookie);
323         assertEquals("Found 1 cookie.",1,parsed.length);
324         assertEquals("Name","cookie-name",parsed[0].getName());
325         assertEquals("Value"," cookie-value ",parsed[0].getValue());
326         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
327         assertEquals("Path","/",parsed[0].getPath());
328         assertTrue("Secure",!parsed[0].getSecure());
329         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
330         assertTrue("Comment",null == parsed[0].getComment());
331     }
332 
333     public void testParseWithPath() throws Exception {
334         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; Path=/path/");
335         Cookie[] parsed = cookieParse("127.0.0.1","/path/path",setCookie);
336         assertEquals("Found 1 cookie.",1,parsed.length);
337         assertEquals("Name","cookie-name",parsed[0].getName());
338         assertEquals("Value","cookie-value",parsed[0].getValue());
339         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
340         assertEquals("Path","/path/",parsed[0].getPath());
341         assertTrue("Secure",!parsed[0].getSecure());
342         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
343         assertTrue("Comment",null == parsed[0].getComment());
344     }
345 
346     public void testParseWithDomain() throws Exception {
347         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; Domain=127.0.0.1");
348         Cookie[] parsed = cookieParse("127.0.0.1","/",setCookie);
349         assertEquals("Found 1 cookie.",1,parsed.length);
350         assertEquals("Name","cookie-name",parsed[0].getName());
351         assertEquals("Value","cookie-value",parsed[0].getValue());
352         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
353         assertEquals("Path","/",parsed[0].getPath());
354         assertTrue("Secure",!parsed[0].getSecure());
355         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
356         assertTrue("Comment",null == parsed[0].getComment());
357     }
358 
359     public void testParseWithSecure() throws Exception {
360         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; secure");
361         Cookie[] parsed = cookieParse("127.0.0.1","/",true,setCookie);
362         assertEquals("Found 1 cookie.",1,parsed.length);
363         assertEquals("Name","cookie-name",parsed[0].getName());
364         assertEquals("Value","cookie-value",parsed[0].getValue());
365         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
366         assertEquals("Path","/",parsed[0].getPath());
367         assertTrue("Secure",parsed[0].getSecure());
368         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
369         assertTrue("Comment",null == parsed[0].getComment());
370     }
371 
372     public void testParseWithComment() throws Exception {
373         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; comment=\"This is a comment.\"");
374         Cookie[] parsed = cookieParse("127.0.0.1","/",true,setCookie);
375         assertEquals("Found 1 cookie.",1,parsed.length);
376         assertEquals("Name","cookie-name",parsed[0].getName());
377         assertEquals("Value","cookie-value",parsed[0].getValue());
378         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
379         assertEquals("Path","/",parsed[0].getPath());
380         assertTrue("Secure",!parsed[0].getSecure());
381         assertTrue("ExpiryDate",null == parsed[0].getExpiryDate());
382         assertEquals("Comment","This is a comment.",parsed[0].getComment());
383     }
384 
385     public void testParseWithExpires() throws Exception {
386         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
387         Cookie[] parsed = cookieParse("127.0.0.1","/",true,setCookie);
388         assertEquals("Found 1 cookie.",1,parsed.length);
389         assertEquals("Name","cookie-name",parsed[0].getName());
390         assertEquals("Value","cookie-value",parsed[0].getValue());
391         assertEquals("Domain","127.0.0.1",parsed[0].getDomain());
392         assertEquals("Path","/",parsed[0].getPath());
393         assertTrue("Secure",!parsed[0].getSecure());
394         assertEquals(new Date(10000L),parsed[0].getExpiryDate());
395         assertTrue("Comment",null == parsed[0].getComment());
396     }
397 
398     public void testParseWithAll() throws Exception {
399         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Version=1;Path=/commons;Domain=.apache.org;Comment=This is a comment.;secure;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
400         Cookie[] parsed = cookieParse(".apache.org","/commons/httpclient",true,setCookie);
401         assertEquals("Found 1 cookie.",1,parsed.length);
402         assertEquals("Name","cookie-name",parsed[0].getName());
403         assertEquals("Value","cookie-value",parsed[0].getValue());
404         assertEquals("Domain",".apache.org",parsed[0].getDomain());
405         assertEquals("Path","/commons",parsed[0].getPath());
406         assertTrue("Secure",parsed[0].getSecure());
407         assertEquals(new Date(10000L),parsed[0].getExpiryDate());
408         assertEquals("Comment","This is a comment.",parsed[0].getComment());
409         assertEquals("Version",1,parsed[0].getVersion());
410     }
411 
412     public void testParseMultipleDifferentPaths() throws Exception {
413         Header setCookie = new Header("Set-Cookie","name1=value1;Version=1;Path=/commons,name1=value2;Version=1;Path=/commons/httpclient;Version=1");
414         Cookie[] parsed = cookieParse(".apache.org","/commons/httpclient",true,setCookie);
415         HttpState state = new HttpState();
416         state.addCookies(parsed);
417         Cookie[] cookies = state.getCookies();
418         assertEquals("Wrong number of cookies.",2,cookies.length);
419         assertEquals("Name","name1",cookies[0].getName());
420         assertEquals("Value","value1",cookies[0].getValue());
421         assertEquals("Name","name1",cookies[1].getName());
422         assertEquals("Value","value2",cookies[1].getValue());
423     }
424 
425     public void testParseMultipleSamePaths() throws Exception {
426         Header setCookie = new Header("Set-Cookie","name1=value1;Version=1;Path=/commons,name1=value2;Version=1;Path=/commons");
427         Cookie[] parsed = cookieParse(".apache.org","/commons/httpclient",true,setCookie);
428         HttpState state = new HttpState();
429         state.addCookies(parsed);
430         Cookie[] cookies = state.getCookies();
431         assertEquals("Found 1 cookies.",1,cookies.length);
432         assertEquals("Name","name1",cookies[0].getName());
433         assertEquals("Value","value2",cookies[0].getValue());
434     }
435 
436     public void testParseWithWrongDomain() throws Exception {
437         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=127.0.0.1; version=1");
438         try {
439             Cookie[] parsed = cookieParse("127.0.0.2","/",setCookie);
440             fail("HttpException exception should have been thrown");
441         } catch (HttpException e) {
442             // expected
443         }
444     }
445 
446     public void testParseWithWrongDomain2() throws Exception {
447         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=.c.com; version=1");
448         try {
449             Cookie[] parsed = cookieParse("a.b.c.com","/",setCookie);
450             fail("HttpException exception should have been thrown");
451         } catch (HttpException e) {
452             // expected
453         }
454     }
455 
456     /***
457      * Domain has no embedded dots
458      */
459     public void testParseWithIllegalDomain() throws Exception {
460         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=.com; version=1");
461         try {
462             Cookie[] parsed = cookieParse("b.com","/",setCookie);
463             fail("HttpException exception should have been thrown");
464         } catch (HttpException e) {
465             // expected
466         }
467     }
468 
469     /***
470      * Domain has no embedded dots again
471      */
472     public void testParseWithIllegalDomain2() throws Exception {
473         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=.com.; version=1");
474         try {
475             Cookie[] parsed = cookieParse("b.com","/",setCookie);
476             fail("HttpException exception should have been thrown");
477         } catch (HttpException e) {
478             // expected
479         }
480     }
481 
482     public void testParseWithIllegalNetscapeDomain1() throws Exception {
483         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=.com");
484         try {
485             Cookie[] parsed = netscapeCcookieParse("a.com","/",setCookie);
486             fail("HttpException exception should have been thrown");
487         } catch (HttpException e) {
488             // expected
489         }
490     }
491 
492     public void testParseWithWrongNetscapeDomain2() throws Exception {
493         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=.y.z");
494         try {
495             Cookie[] parsed = netscapeCcookieParse("x.y.z","/",setCookie);
496             fail("HttpException exception should have been thrown");
497         } catch (HttpException e) {
498             // expected
499         }
500     }
501 
502     public void testParseWithWrongPath() throws Exception {
503         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=127.0.0.1; path=/not/just/root");
504         try {
505             Cookie[] parsed = cookieParse("127.0.0.1","/",setCookie);
506             fail("HttpException exception should have been thrown");
507         } catch (HttpException e) {
508             // expected
509         }
510     }
511 
512     public void testParseWithNullDomain() {
513         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=127.0.0.1; path=/; secure");
514         try {
515             Cookie[] parsed = cookieParse(null,"/",false,setCookie);
516             fail("IllegalArgumentException should have been thrown");
517         } catch (IllegalArgumentException e) {
518             // expected
519         } catch (Exception e){
520             fail("Should have thrown IllegalArgumentException.");
521         }
522     }
523 
524     public void testParseWithNullPath() {
525         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=127.0.0.1; path=/; secure");
526         try {
527             Cookie[] parsed = cookieParse("127.0.0.1",null,false,setCookie);
528             fail("IllegalArgumentException should have been thrown");
529         } catch (IllegalArgumentException e) {
530             // expected
531         } catch (Exception e){
532             fail("Should have thrown IllegalArgumentException.");
533         }
534     }
535 
536     public void testParseWithNullDomainAndPath() {
537         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; domain=127.0.0.1; path=/; secure");
538         try {
539             Cookie[] parsed = cookieParse(null,null,false,setCookie);
540             fail("IllegalArgumentException should have been thrown");
541         } catch (IllegalArgumentException e) {
542             // expected
543         } catch (Exception e){
544             fail("Should have thrown IllegalArgumentException.");
545         }
546     }
547     
548     public void testParseWithPathMismatch() {
549         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; path=/path/path/path");
550         try {
551             Cookie[] parsed = cookieParse("127.0.0.1","/path",false,setCookie);
552             fail("HttpException should have been thrown.");
553         } catch (HttpException e) {
554             // expected
555         } catch (Exception e){
556             fail("Should have thrown HttpException.");
557         }
558     }
559     
560     public void testParseWithPathMismatch2() {
561         Header setCookie = new Header("Set-Cookie","cookie-name=cookie-value; path=/foobar");
562         try {
563             Cookie[] parsed = cookieParse("127.0.0.1","/foo",false,setCookie);
564             fail("HttpException should have been thrown.");
565         } catch (HttpException e) {
566             // expected
567         } catch (Exception e){
568             fail("Should have thrown HttpException.");
569         }
570     }
571     
572     public void testComparator() throws Exception {
573         Header setCookie = null;
574         Cookie[] parsed = null;
575         Vector cookies = new Vector();
576         // Cookie 0
577         setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Path=/commons;Domain=.apache.org;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
578         parsed = cookieParse(".apache.org", "/commons/httpclient", true,
579                               setCookie);
580         cookies.add(parsed[0]);
581         // Cookie 1
582         setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Path=/commons/bif;Domain=.apache.org;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
583         parsed = cookieParse(".apache.org","/commons/bif/httpclient",true,setCookie);
584         cookies.add(parsed[0]);
585         // Cookie 2
586         setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Path=/commons;Domain=.baz.org;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
587         parsed = cookieParse(".baz.org","/commons/httpclient",true,setCookie);
588         cookies.add(parsed[0]);
589         // Cookie 3
590         setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Path=/commons/bif;Domain=.baz.org;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
591         parsed = cookieParse(".baz.org","/commons/bif/httpclient",true,setCookie);
592         cookies.add(parsed[0]);
593         // Cookie 4
594         setCookie = new Header("Set-Cookie","cookie-name=cookie-value;Path=/commons;Domain=.baz.com;Expires=Thu, 01-Jan-1970 00:00:10 GMT");
595         parsed = cookieParse(".baz.com","/commons/httpclient",true,setCookie);
596         cookies.add(parsed[0]);
597         // The order should be:
598         // 1, 0, 3, 2, 4
599         parsed = (Cookie[])cookies.toArray(new Cookie[0]);
600         SortedSet set = new TreeSet(parsed[0]);
601         int pass = 0;
602         for (Iterator itr = set.iterator(); itr.hasNext();) {
603             Cookie cookie = (Cookie)itr.next();
604             switch (pass) {
605                 case 0:
606                     assertTrue("0th cookie should be cookie[1]", cookie == parsed[1]);
607                     break;
608                 case 1:
609                     assertTrue("1st cookie should be cookie[0]", cookie == parsed[0]);
610                     break;
611                 case 2:
612                     assertTrue("2nd cookie should be cookie[3]", cookie == parsed[3]);
613                     break;
614                 case 3:
615                     assertTrue("3rd cookie should be cookie[2]", cookie == parsed[2]);
616                     break;
617                 case 4:
618                     assertTrue("4th cookie should be cookie[4]", cookie == parsed[4]);
619                     break;
620                 default:
621                     fail("This should never happen.");
622             }
623             pass++;
624         }
625         try {
626             parsed[0].compare("foo", "bar");
627             fail("Should have thrown an exception trying to compare non-cookies");
628         }
629         catch (ClassCastException ex) {
630             // expected
631         }
632     }
633     
634     /*** Call Cookie.createCookieHeader providing null for domain to match on
635      */
636     public void testCreateCookieHeaderWithNullDomain() throws Exception {
637         Header setCookie = new Header("Set-Cookie",
638                                       TEST_COOKIE + SEP + OLD_EXPIRY);
639         Cookie[] parsed = cookieParse(DOMAIN_NAME, ROOT_PATH, true, setCookie);
640 
641         try{
642             Header header = cookieCreateHeader(null, DEFAULT_PORT, ROOT_PATH, false, parsed);
643             fail("IllegalArgumentException should have been thrown.");
644         }catch(IllegalArgumentException e){
645             // Expected
646         }catch(Exception e){
647             fail("Threw wrong type of exception.  Expected IllegalArgumentException.");
648         }
649     }
650     
651     /*** Call Cookie.createCookieHeader providing null for path to match on
652      */
653     public void testCreateCookieHeaderWithNullPath() throws Exception{
654         Header setCookie = new Header("Set-Cookie",
655                                       TEST_COOKIE + SEP + OLD_EXPIRY);
656         Cookie[] parsed = cookieParse(DOMAIN_NAME, ROOT_PATH, false, setCookie);
657 
658         try{
659             Header header = cookieCreateHeader(DOMAIN_NAME, DEFAULT_PORT, null, false, parsed);
660             fail("IllegalArgumentException should have been thrown.");
661         }catch(IllegalArgumentException e){
662             // Expected
663         }catch(Exception e){
664             fail("Threw wrong type of exception.  Expected IllegalArgumentException.");
665         }
666     }
667 
668     /***
669      * Verify that cookies with no domain or path don't get added to a cookie header.
670      */
671     public void testCreateCookieHeaderWithUninitializedCookies() throws Exception {
672         Cookie cookies[] = new Cookie[2];
673         cookies[0] = new Cookie(null, "name0", "value0");
674         cookies[1] = new Cookie(null, "name1", "value1", null, null, false);
675 
676         Header header = cookieCreateHeader(DOMAIN_NAME, DEFAULT_PORT, ROOT_PATH, false, cookies);
677         assertEquals("createCookieHeader added cookies with null domains or paths", null, header);
678     }
679 
680     /*** Call Cookie.createCookieHeader providing null for domain and path to
681      * match on
682      */
683     public void testCreateCookieHeaderWithNullDomainAndPath() throws Exception {
684         Header setCookie = new Header("Set-Cookie",
685                                       TEST_COOKIE + SEP + OLD_EXPIRY);
686         Cookie[] parsed = cookieParse(DOMAIN_NAME, ROOT_PATH, true, setCookie);
687 
688         try{
689             Header header = cookieCreateHeader(null, DEFAULT_PORT, null, false, parsed);
690             fail("IllegalArgumentException should have been thrown.");
691         }catch(IllegalArgumentException e){
692             // Expected
693         }catch(Exception e){
694             fail("Threw wrong type of exception.  Expected IllegalArgumentException.");
695         }
696     }
697 
698     /***
699      * Tests several date formats.
700      */
701     public void testDateFormats() throws Exception {
702         //comma, dashes
703         checkDate("Thu, 01-Jan-70 00:00:10 GMT");
704         checkDate("Thu, 01-Jan-2070 00:00:10 GMT");
705         //no comma, dashes
706         checkDate("Thu 01-Jan-70 00:00:10 GMT");
707         checkDate("Thu 01-Jan-2070 00:00:10 GMT");
708         //comma, spaces
709         checkDate("Thu, 01 Jan 70 00:00:10 GMT");
710         checkDate("Thu, 01 Jan 2070 00:00:10 GMT");
711         //no comma, spaces
712         checkDate("Thu 01 Jan 70 00:00:10 GMT");
713         checkDate("Thu 01 Jan 2070 00:00:10 GMT");
714         //weird stuff
715         checkDate("Wed, 20-Nov-2002 09-38-33 GMT");
716 
717 
718         try {
719             checkDate("this aint a date");
720             fail("Date check is bogous");
721         } catch(Exception e) {
722             /* must fail */
723         }
724     }
725 
726     private void checkDate(String date) throws Exception {
727         Header setCookie = new Header("Set-Cookie", "custno=12345;Expires='"+date+"'");
728         cookieParse("localhost","/",setCookie);
729     }
730     
731     
732     /***
733      * Tests default constructor.
734      */
735     public void testDefaultConstuctor() {
736         Cookie dummy = new Cookie();
737         assertEquals( "noname=", dummy.toExternalForm() );
738     }
739 
740     public void testIgnoreCookies() throws Exception {
741         String headers = 
742             "HTTP/1.1 401 OK\r\n" +
743             "Connection: close\r\n" +
744             "Content-Length: 0\r\n" +
745             "Set-Cookie: custno = 12345; comment=test; version=1," +
746             " name=John; version=1; max-age=600; secure; domain=.apache.org";
747         
748         conn.addResponse(headers);
749         
750         GetMethod get = new GetMethod("/");
751         get.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
752         client.executeMethod(get);
753         
754         assertEquals("Cookie parsing should have been disabled", 
755                 0, client.getState().getCookies().length);
756     }
757     
758     /***
759      * Tests whether domain attribute check is case-insensitive.
760      */
761     public void testDomainCaseInsensitivity() {
762         Header setCookie = new Header(
763           "Set-Cookie", "name=value; path=/; domain=.whatever.com");
764         try {
765             Cookie[] parsed = cookieParse("www.WhatEver.com", "/", false, setCookie );
766         }
767         catch(HttpException e) {
768             e.printStackTrace();
769             fail("Unexpected exception: " + e.toString());
770         }
771     }
772     
773 
774     /***
775      * Tests if cookie constructor rejects cookie name containing blanks.
776      */
777     public void testInvalidCookieName() {
778         try
779         {
780             CookieSpec parser = new CookieSpecBase();
781             parser.parse("localhost", 80, "/", false, "invalid name="); 
782             fail("MalformedCookieException must have been thrown");
783         }
784         catch(MalformedCookieException e)
785         {
786             // Expected            
787         }
788     }
789 
790 
791     /***
792      * Tests if cookie constructor rejects cookie name starting with $.
793      */
794     public void testInvalidCookieName2() {
795         try
796         {
797             CookieSpec parser = new CookieSpecBase();
798             parser.parse("localhost", 80, "/", false, "$invalid_name="); 
799             fail("MalformedCookieException must have been thrown");
800         }
801         catch(MalformedCookieException e)
802         {
803             // Expected            
804         }
805     }
806 
807     /***
808      * Tests if default cookie validator rejects cookies originating from a host without domain
809      * where domain attribute does not match the host of origin 
810      */
811     
812     public void testInvalidDomainWithSimpleHostName() {    
813         CookieSpec parser = CookiePolicy.getDefaultSpec();
814         Header setCookie = null;
815         Cookie[] cookies = null;
816         try {
817             setCookie = new Header(
818             "Set-Cookie", "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
819             cookies = parser.parse("host", 80, "/", false, setCookie );
820             try {
821                 parser.validate("host", 80, "/", false, cookies[0]);
822                 fail("MalformedCookieException must have thrown");
823             }
824             catch(MalformedCookieException expected) {
825             }
826         }
827         catch(HttpException e) {
828             e.printStackTrace();
829             fail("Unexpected exception: " + e.toString());
830         }
831         try {
832             setCookie = new Header(
833             "Set-Cookie", "name=\"value\"; version=\"1\"; path=\"/\"; domain=\"host1\"");
834             cookies = parser.parse("host2", 80, "/", false, setCookie );
835             try {
836                 parser.validate("host2", 80, "/", false, cookies[0]);
837                 fail("MalformedCookieException must have thrown");
838             }
839             catch(MalformedCookieException expected) {
840             }
841         }
842         catch(HttpException e) {
843             e.printStackTrace();
844             fail("Unexpected exception: " + e.toString());
845         }
846     }
847 
848     /***
849      * Makes sure that a cookie matches with a path of the same value.
850      */
851     public void testMatchWithEqualPaths() {
852         
853         Cookie cookie = new Cookie(".test.com", "test", "1", "/test", null, false);
854         
855         try {
856             boolean match = cookieMatch(
857                 "test.test.com", 
858                 80, 
859                 "/test", 
860                 false,
861                 cookie
862             );
863             
864             assertTrue("Cookie paths did not match", match);
865         } catch ( Exception e ) {
866             e.printStackTrace();
867             fail("Unexpected exception: " + e);
868         }
869                    
870     }
871 
872 
873     /***
874      * Tests generic cookie formatting.
875      */
876     
877     public void testGenericCookieFormatting() {
878         Header setCookie = new Header(
879           "Set-Cookie", "name=value; path=/; domain=.mydomain.com");
880         try {
881             CookieSpec parser = CookiePolicy.getCookieSpec(CookiePolicy.BROWSER_COMPATIBILITY);
882             Cookie[] cookies = parser.parse("myhost.mydomain.com", 80, "/", false, setCookie );
883             parser.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
884             String s = parser.formatCookie(cookies[0]);
885             assertEquals("name=value", s);
886         }
887         catch(HttpException e) {
888             e.printStackTrace();
889             fail("Unexpected exception: " + e.toString());
890         }
891     }    
892 
893     /***
894      * Tests Netscape specific cookie formatting.
895      */
896     
897     public void testNetscapeCookieFormatting() {
898         Header setCookie = new Header(
899           "Set-Cookie", "name=value; path=/; domain=.mydomain.com");
900         try {
901             CookieSpec parser = CookiePolicy.getCookieSpec(CookiePolicy.NETSCAPE);
902             Cookie[] cookies = parser.parse("myhost.mydomain.com", 80, "/", false, setCookie );
903             parser.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
904             String s = parser.formatCookie(cookies[0]);
905             assertEquals("name=value", s);
906         }
907         catch(HttpException e) {
908             e.printStackTrace();
909             fail("Unexpected exception: " + e.toString());
910         }
911     }
912     
913 
914     /***
915      * Tests RFC 2109 compiant cookie formatting.
916      */
917     
918     public void testRFC2109CookieFormatting() {
919         CookieSpec parser = CookiePolicy.getCookieSpec(CookiePolicy.RFC_2109);
920         Header setCookie = null;
921         Cookie[] cookies = null;
922         try {
923             setCookie = new Header(
924             "Set-Cookie", "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
925             cookies = parser.parse("myhost.mydomain.com", 80, "/", false, setCookie );
926             parser.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
927             String s1 = parser.formatCookie(cookies[0]);
928             assertEquals(s1, "$Version=\"1\"; name=\"value\"; $Domain=\".mydomain.com\"; $Path=\"/\"");
929 
930             setCookie = new Header(
931             "Set-Cookie", "name=value; path=/; domain=.mydomain.com");
932             cookies = parser.parse("myhost.mydomain.com", 80, "/", false, setCookie );
933             parser.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
934             String s2 = parser.formatCookie(cookies[0]);
935             assertEquals(s2, "$Version=0; name=value; $Domain=.mydomain.com; $Path=/");
936         }
937         catch(HttpException e) {
938             e.printStackTrace();
939             fail("Unexpected exception: " + e.toString());
940         }
941     }
942 
943 
944     /***
945      * Tests Netscape specific expire attribute parsing.
946      */
947     
948     public void testNetscapeCookieExpireAttribute() {
949         CookieSpec parser = CookiePolicy.getCookieSpec(CookiePolicy.NETSCAPE);
950         Header setCookie = null;
951         Cookie[] cookies = null;
952         try {
953             setCookie = new Header(
954               "Set-Cookie", "name=value; path=/; domain=.mydomain.com; expires=Thu, 01-Jan-2070 00:00:10 GMT; comment=no_comment");
955             cookies = parser.parse("myhost.mydomain.com", 80, "/", false, setCookie );
956             parser.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
957         }
958         catch(MalformedCookieException e) {
959             e.printStackTrace();
960             fail("Unexpected exception: " + e.toString());
961         }
962         try {
963             setCookie = new Header(
964               "Set-Cookie", "name=value; path=/; domain=.mydomain.com; expires=Thu 01-Jan-2070 00:00:10 GMT; comment=no_comment");
965             cookies = parser.parse("myhost.mydomain.com", 80, "/", false, setCookie );
966             parser.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
967             fail("MalformedCookieException must have been thrown");
968         }
969         catch(MalformedCookieException e) {
970             //expected
971         }
972     }
973     
974 
975     /***
976      * Tests if null cookie values are handled correctly.
977      */
978     public void testNullCookieValueFormatting() {
979         Cookie cookie = new Cookie(".whatever.com", "name", null, "/", null, false); 
980         cookie.setDomainAttributeSpecified(true);
981         cookie.setPathAttributeSpecified(true);
982 
983         CookieSpec parser = null;
984         String s = null;
985 
986         parser = CookiePolicy.getCookieSpec(CookiePolicy.BROWSER_COMPATIBILITY);
987         s = parser.formatCookie(cookie);
988         assertEquals("name=", s);
989 
990         parser = CookiePolicy.getCookieSpec(CookiePolicy.RFC_2109);
991         s = parser.formatCookie(cookie);
992         assertEquals("$Version=0; name=; $Domain=.whatever.com; $Path=/", s);
993     }
994     
995 
996     /***
997      * Tests if cookie values with embedded comma are handled correctly.
998      */
999     public void testCookieWithComma() throws Exception {
1000         CookieSpec parser = null;
1001         Cookie[] cookies = null;
1002         Header header = new Header("Set-Cookie", "a=b,c");
1003 
1004         parser = CookiePolicy.getCookieSpec(CookiePolicy.RFC_2109); 
1005         cookies = parser.parse("localhost", 80, "/", false, header);
1006         assertEquals("number of cookies", 2, cookies.length);
1007         assertEquals("a", cookies[0].getName());
1008         assertEquals("b", cookies[0].getValue());
1009         assertEquals("c", cookies[1].getName());
1010         assertEquals(null, cookies[1].getValue());
1011 
1012         parser = CookiePolicy.getCookieSpec(CookiePolicy.NETSCAPE);
1013         cookies = parser.parse("localhost", 80, "/", false, header);
1014         assertEquals("number of cookies", 1, cookies.length);
1015         assertEquals("a", cookies[0].getName());
1016         assertEquals("b,c", cookies[0].getValue());
1017     }
1018 
1019     
1020     /***
1021      * Tests if that invalid second domain level cookie gets 
1022      * rejected in the strict mode, but gets accepted in the
1023      * browser compatibility mode.
1024      */
1025     public void testSecondDomainLevelCookie() throws Exception {
1026         Cookie cookie = new Cookie(".sourceforge.net", "name", null, "/", null, false); 
1027         cookie.setDomainAttributeSpecified(true);
1028         cookie.setPathAttributeSpecified(true);
1029 
1030         CookieSpec parser = null;
1031 
1032         parser = CookiePolicy.getCookieSpec(CookiePolicy.BROWSER_COMPATIBILITY);
1033         parser.validate("sourceforge.net", 80, "/", false, cookie);
1034 
1035         parser = CookiePolicy.getCookieSpec(CookiePolicy.RFC_2109);
1036         try {
1037             parser.validate("sourceforge.net", 80, "/", false, cookie);
1038             fail("MalformedCookieException should have been thrown");
1039         } catch (MalformedCookieException e) {
1040             // Expected
1041         }
1042     }
1043 }
1044