1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/test/org/apache/commons/httpclient/cookie/TestCookieRFC2109Spec.java $
3    * $Revision: 1425331 $
4    * $Date: 2012-12-22 19:29:41 +0100 (Sat, 22 Dec 2012) $
5    * ====================================================================
6    *
7    *  Licensed to the Apache Software Foundation (ASF) under one or more
8    *  contributor license agreements.  See the NOTICE file distributed with
9    *  this work for additional information regarding copyright ownership.
10   *  The ASF licenses this file to You under the Apache License, Version 2.0
11   *  (the "License"); you may not use this file except in compliance with
12   *  the License.  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient.cookie;
31  
32  import junit.framework.Test;
33  import junit.framework.TestSuite;
34  
35  import org.apache.commons.httpclient.Cookie;
36  import org.apache.commons.httpclient.Header;
37  import org.apache.commons.httpclient.NameValuePair;
38  
39  /***
40   * Test cases for RFC2109 cookie spec
41   *
42   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
43   * 
44   * @version $Revision: 1425331 $
45   */
46  public class TestCookieRFC2109Spec extends TestCookieBase {
47  
48  
49      // ------------------------------------------------------------ Constructor
50  
51      public TestCookieRFC2109Spec(String name) {
52          super(name);
53      }
54  
55      // ------------------------------------------------------- TestCase Methods
56  
57      public static Test suite() {
58          return new TestSuite(TestCookieRFC2109Spec.class);
59      }
60  
61      public void testParseAttributeInvalidAttrib() throws Exception {
62          CookieSpec cookiespec = new RFC2109Spec();
63          try {
64              cookiespec.parseAttribute(null, null);
65              fail("IllegalArgumentException must have been thrown");
66          } catch (IllegalArgumentException expected) {
67          }
68      }
69  
70      public void testParseAttributeInvalidCookie() throws Exception {
71          CookieSpec cookiespec = new RFC2109Spec();
72          try {
73              cookiespec.parseAttribute(new NameValuePair("name", "value"), null);
74              fail("IllegalArgumentException must have been thrown");
75          } catch (IllegalArgumentException expected) {
76          }
77      }
78  
79      public void testParseAttributeNullPath() throws Exception {
80          CookieSpec cookiespec = new RFC2109Spec();
81          try {
82              Cookie cookie = new Cookie();
83              cookiespec.parseAttribute(new NameValuePair("path", null), cookie);
84              fail("MalformedCookieException must have been thrown");
85          } catch (MalformedCookieException expected) {
86          }
87      }
88  
89      public void testParseAttributeBlankPath() throws Exception {
90          CookieSpec cookiespec = new RFC2109Spec();
91          try {
92              Cookie cookie = new Cookie();
93              cookiespec.parseAttribute(new NameValuePair("path", "   "), cookie);
94              fail("MalformedCookieException must have been thrown");
95          } catch (MalformedCookieException expected) {
96          }
97      }
98  
99      public void testParseAttributeNullVersion() throws Exception {
100         CookieSpec cookiespec = new RFC2109Spec();
101         try {
102             Cookie cookie = new Cookie();
103             cookiespec.parseAttribute(new NameValuePair("version", null), cookie);
104             fail("MalformedCookieException must have been thrown");
105         } catch (MalformedCookieException expected) {
106         }
107     }
108 
109     public void testParseAttributeInvalidVersion() throws Exception {
110         CookieSpec cookiespec = new RFC2109Spec();
111         try {
112             Cookie cookie = new Cookie();
113             cookiespec.parseAttribute(new NameValuePair("version", "nonsense"), cookie);
114             fail("MalformedCookieException must have been thrown");
115         } catch (MalformedCookieException expected) {
116         }
117     }
118 
119     public void testParseVersion() throws Exception {
120         Header header = new Header("Set-Cookie","cookie-name=cookie-value; version=1");
121 
122         CookieSpec cookiespec = new RFC2109Spec();
123         Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header);
124         assertEquals("Found 1 cookie.",1,parsed.length);
125         assertEquals("Name","cookie-name",parsed[0].getName());
126         assertEquals("Value","cookie-value",parsed[0].getValue());
127         assertEquals("Version",1,parsed[0].getVersion());
128     }
129 
130     /***
131      * Test domain equals host 
132      */
133     public void testParseDomainEqualsHost() throws Exception {
134         Header header = new Header("Set-Cookie",
135             "cookie-name=cookie-value; domain=www.b.com; version=1");
136 
137         CookieSpec cookiespec = new RFC2109Spec();
138         Cookie[] parsed = cookieParse(cookiespec, "www.b.com", 80, "/", false, header);
139         assertNotNull(parsed);
140         assertEquals(1, parsed.length);
141         assertEquals("www.b.com", parsed[0].getDomain());
142     }
143 
144     /***
145      * Domain does not start with a dot
146      */
147     public void testParseWithIllegalDomain1() throws Exception {
148         Header header = new Header("Set-Cookie",
149             "cookie-name=cookie-value; domain=a.b.com; version=1");
150 
151         CookieSpec cookiespec = new RFC2109Spec();
152         try {
153             Cookie[] parsed = cookieParse(cookiespec, "www.a.b.com", 80, "/", false, header);
154             fail("MalformedCookieException should have been thrown");
155         } catch (MalformedCookieException e) {
156             // expected
157         }
158     }
159 
160     /***
161      * Domain must have alt least one embedded dot
162      */
163     public void testParseWithIllegalDomain2() throws Exception {
164         Header header = new Header("Set-Cookie",
165             "cookie-name=cookie-value; domain=.com; version=1");
166 
167         CookieSpec cookiespec = new RFC2109Spec();
168         try {
169             Cookie[] parsed = cookieParse(cookiespec, "b.com", 80, "/", false, header);
170             fail("MalformedCookieException should have been thrown");
171         } catch (MalformedCookieException e) {
172             // expected
173         }
174     }
175     /***
176      * Domain must have alt least one embedded dot
177      */
178     public void testParseWithIllegalDomain3() throws Exception {
179         Header header = new Header("Set-Cookie",
180             "cookie-name=cookie-value; domain=.com.; version=1");
181 
182         CookieSpec cookiespec = new RFC2109Spec();
183         try {
184             Cookie[] parsed = cookieParse(cookiespec, "b.com", 80, "/", false, header);
185             fail("HttpException exception should have been thrown");
186         } catch (MalformedCookieException e) {
187             // expected
188         }
189     }
190 
191     /***
192      * Host minus domain may not contain any dots
193      */
194     public void testParseWithIllegalDomain4() throws Exception {
195         Header header = new Header("Set-Cookie",
196             "cookie-name=cookie-value; domain=.c.com; version=1");
197 
198         CookieSpec cookiespec = new RFC2109Spec();
199         try {
200             Cookie[] parsed = cookieParse(cookiespec, "a.b.c.com", 80, "/", false, header);
201             fail("MalformedCookieException should have been thrown");
202         } catch (MalformedCookieException e) {
203             // expected
204         }
205     }
206 
207     /***
208      * Tests if that invalid second domain level cookie gets 
209      * rejected in the strict mode, but gets accepted in the
210      * browser compatibility mode.
211      */
212     public void testSecondDomainLevelCookie() throws Exception {
213         Cookie cookie = new Cookie(".sourceforge.net", "name", null, "/", null, false); 
214         cookie.setDomainAttributeSpecified(true);
215         cookie.setPathAttributeSpecified(true);
216 
217         CookieSpec cookiespec = new RFC2109Spec();
218         try {
219             cookiespec.validate("sourceforge.net", 80, "/", false, cookie);
220             fail("MalformedCookieException should have been thrown");
221         } catch (MalformedCookieException e) {
222             // Expected
223         }
224     }    
225 
226     public void testSecondDomainLevelCookieMatch() throws Exception {
227         Cookie cookie = new Cookie(".sourceforge.net", "name", null, "/", null, false); 
228         cookie.setDomainAttributeSpecified(true);
229         cookie.setPathAttributeSpecified(true);
230 
231         CookieSpec cookiespec = new RFC2109Spec();
232         assertFalse(cookiespec.match("sourceforge.net", 80, "/", false, cookie));
233     }
234     
235     public void testParseWithWrongPath() throws Exception {
236         Header header = new Header("Set-Cookie",
237             "cookie-name=cookie-value; domain=127.0.0.1; path=/not/just/root");
238 
239         CookieSpec cookiespec = new RFC2109Spec();
240         try {
241             Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, header);
242             fail("HttpException exception should have been thrown");
243         } catch (MalformedCookieException e) {
244             // expected
245         }
246     }
247 
248     /***
249      * Tests if cookie constructor rejects cookie name containing blanks.
250      */
251     public void testCookieNameWithBlanks() throws Exception {
252         Header setcookie = new Header("Set-Cookie", "invalid name=");
253         CookieSpec cookiespec = new RFC2109Spec();
254         try {
255             Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, setcookie);
256             fail("MalformedCookieException exception should have been thrown");
257         } catch (MalformedCookieException e) {
258             // expected
259         }
260     }
261 
262 
263     /***
264      * Tests if cookie constructor rejects cookie name starting with $.
265      */
266     public void testCookieNameStartingWithDollarSign() throws Exception {
267         Header setcookie = new Header("Set-Cookie", "$invalid_name=");
268         CookieSpec cookiespec = new RFC2109Spec();
269         try {
270             Cookie[] parsed = cookieParse(cookiespec, "127.0.0.1", 80, "/", false, setcookie);
271             fail("MalformedCookieException exception should have been thrown");
272         } catch (MalformedCookieException e) {
273             // expected
274         }
275     }
276 
277     /***
278      * Tests if default cookie validator rejects cookies originating from a host without domain
279      * where domain attribute does not match the host of origin 
280      */
281     public void testInvalidDomainWithSimpleHostName() throws Exception {    
282         CookieSpec cookiespec = new RFC2109Spec();
283         Header header = new Header("Set-Cookie", 
284             "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
285         Cookie[]cookies = cookiespec.parse("host", 80, "/", false, header );
286         try {
287             cookiespec.validate("host", 80, "/", false, cookies[0]);
288             fail("MalformedCookieException must have thrown");
289         }
290         catch(MalformedCookieException expected) {
291         }
292         header = new Header("Set-Cookie", 
293             "name=\"value\"; version=\"1\"; path=\"/\"; domain=\"host1\"");
294         cookies = cookiespec.parse("host2", 80, "/", false, header );
295         try {
296             cookiespec.validate("host2", 80, "/", false, cookies[0]);
297             fail("MalformedCookieException must have thrown");
298         }
299         catch(MalformedCookieException expected) {
300         }
301     }
302 
303     /***
304      * Tests if cookie values with embedded comma are handled correctly.
305      */
306     public void testCookieWithComma() throws Exception {
307         Header header = new Header("Set-Cookie", "a=b,c");
308 
309         CookieSpec cookiespec = new RFC2109Spec();
310         Cookie[] cookies = cookiespec.parse("localhost", 80, "/", false, header);
311         assertEquals("number of cookies", 2, cookies.length);
312         assertEquals("a", cookies[0].getName());
313         assertEquals("b", cookies[0].getValue());
314         assertEquals("c", cookies[1].getName());
315         assertEquals(null, cookies[1].getValue());
316     }
317 
318     public void testFormatInvalidCookies() throws Exception {
319         CookieSpec cookiespec = new RFC2109Spec();
320         try {
321             String s = cookiespec.formatCookie(null);
322             fail("IllegalArgumentException nust have been thrown");
323         } catch (IllegalArgumentException expected) {
324         }
325     }    
326 
327     /***
328      * Tests RFC 2109 compiant cookie formatting.
329      */
330     public void testRFC2109CookieFormatting() throws Exception {
331         CookieSpec cookiespec = new RFC2109Spec();
332         Header header = new Header("Set-Cookie", 
333             "name=\"value\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
334         Cookie[] cookies  = cookiespec.parse("myhost.mydomain.com", 80, "/", false, header );
335         cookiespec.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
336         String s1 = cookiespec.formatCookie(cookies[0]);
337         assertEquals(s1, "$Version=\"1\"; name=\"value\"; $Path=\"/\"; $Domain=\".mydomain.com\"");
338 
339         header = new Header( "Set-Cookie", 
340             "name=value; path=/; domain=.mydomain.com");
341         cookies = cookiespec.parse("myhost.mydomain.com", 80, "/", false, header );
342         cookiespec.validate("myhost.mydomain.com", 80, "/", false, cookies[0]);
343         String s2 = cookiespec.formatCookie(cookies[0]);
344         assertEquals(s2, "$Version=0; name=value; $Path=/; $Domain=.mydomain.com");
345     }
346 
347     public void testRFC2109CookiesFormatting() throws Exception {
348         CookieSpec cookiespec = new RFC2109Spec();
349         Header header = new Header("Set-Cookie", 
350             "name1=value1; path=/; domain=.mydomain.com, " + 
351             "name2=\"value2\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
352         Cookie[] cookies = cookieParse(cookiespec, "myhost.mydomain.com", 80, "/", false, header);
353         assertNotNull(cookies);
354         assertEquals(2, cookies.length);
355         String s1 = cookiespec.formatCookies(cookies);
356         assertEquals(s1, 
357             "$Version=0; name1=value1; $Path=/; $Domain=.mydomain.com; " + 
358             "name2=value2; $Path=/; $Domain=.mydomain.com");
359 
360         header = new Header("Set-Cookie", 
361             "name1=value1; version=1; path=/; domain=.mydomain.com, " + 
362             "name2=\"value2\"; version=\"1\"; path=\"/\"; domain=\".mydomain.com\"");
363         cookies = cookieParse(cookiespec, "myhost.mydomain.com", 80, "/", false, header);
364         assertNotNull(cookies);
365         assertEquals(2, cookies.length);
366         String s2 = cookiespec.formatCookies(cookies);
367         assertEquals(s2, 
368             "$Version=\"1\"; name1=\"value1\"; $Path=\"/\"; $Domain=\".mydomain.com\"; " + 
369             "name2=\"value2\"; $Path=\"/\"; $Domain=\".mydomain.com\"");
370     }
371     
372     /***
373      * Tests if null cookie values are handled correctly.
374      */
375     public void testNullCookieValueFormatting() {
376         Cookie cookie = new Cookie(".whatever.com", "name", null, "/", null, false); 
377         cookie.setDomainAttributeSpecified(true);
378         cookie.setPathAttributeSpecified(true);
379 
380         CookieSpec cookiespec = new RFC2109Spec();
381         String s = cookiespec.formatCookie(cookie);
382         assertEquals("$Version=0; name=; $Path=/; $Domain=.whatever.com", s);
383 
384         cookie.setVersion(1);
385         s = cookiespec.formatCookie(cookie);
386         assertEquals("$Version=\"1\"; name=\"\"; $Path=\"/\"; $Domain=\".whatever.com\"", s);
387     }
388 
389     public void testCookieNullDomainNullPathFormatting() {
390         Cookie cookie = new Cookie(null, "name", null, "/", null, false); 
391         cookie.setDomainAttributeSpecified(true);
392         cookie.setPathAttributeSpecified(true);
393 
394         CookieSpec cookiespec = new RFC2109Spec();
395         String s = cookiespec.formatCookie(cookie);
396         assertEquals("$Version=0; name=; $Path=/", s);
397 
398         cookie.setDomainAttributeSpecified(false);
399         cookie.setPathAttributeSpecified(false);
400         s = cookiespec.formatCookie(cookie);
401         assertEquals("$Version=0; name=", s);
402     }
403 
404 }
405