]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/test/test_cookielib.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / test / test_cookielib.py
CommitLineData
4710c53d 1# -*- coding: latin-1 -*-\r
2"""Tests for cookielib.py."""\r
3\r
4import cookielib\r
5import os\r
6import re\r
7import time\r
8\r
9from unittest import TestCase\r
10\r
11from test import test_support\r
12\r
13\r
14class DateTimeTests(TestCase):\r
15\r
16 def test_time2isoz(self):\r
17 from cookielib import time2isoz\r
18\r
19 base = 1019227000\r
20 day = 24*3600\r
21 self.assertEqual(time2isoz(base), "2002-04-19 14:36:40Z")\r
22 self.assertEqual(time2isoz(base+day), "2002-04-20 14:36:40Z")\r
23 self.assertEqual(time2isoz(base+2*day), "2002-04-21 14:36:40Z")\r
24 self.assertEqual(time2isoz(base+3*day), "2002-04-22 14:36:40Z")\r
25\r
26 az = time2isoz()\r
27 bz = time2isoz(500000)\r
28 for text in (az, bz):\r
29 self.assertTrue(re.search(r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\dZ$", text),\r
30 "bad time2isoz format: %s %s" % (az, bz))\r
31\r
32 def test_http2time(self):\r
33 from cookielib import http2time\r
34\r
35 def parse_date(text):\r
36 return time.gmtime(http2time(text))[:6]\r
37\r
38 self.assertEqual(parse_date("01 Jan 2001"), (2001, 1, 1, 0, 0, 0.0))\r
39\r
40 # this test will break around year 2070\r
41 self.assertEqual(parse_date("03-Feb-20"), (2020, 2, 3, 0, 0, 0.0))\r
42\r
43 # this test will break around year 2048\r
44 self.assertEqual(parse_date("03-Feb-98"), (1998, 2, 3, 0, 0, 0.0))\r
45\r
46 def test_http2time_formats(self):\r
47 from cookielib import http2time, time2isoz\r
48\r
49 # test http2time for supported dates. Test cases with 2 digit year\r
50 # will probably break in year 2044.\r
51 tests = [\r
52 'Thu, 03 Feb 1994 00:00:00 GMT', # proposed new HTTP format\r
53 'Thursday, 03-Feb-94 00:00:00 GMT', # old rfc850 HTTP format\r
54 'Thursday, 03-Feb-1994 00:00:00 GMT', # broken rfc850 HTTP format\r
55\r
56 '03 Feb 1994 00:00:00 GMT', # HTTP format (no weekday)\r
57 '03-Feb-94 00:00:00 GMT', # old rfc850 (no weekday)\r
58 '03-Feb-1994 00:00:00 GMT', # broken rfc850 (no weekday)\r
59 '03-Feb-1994 00:00 GMT', # broken rfc850 (no weekday, no seconds)\r
60 '03-Feb-1994 00:00', # broken rfc850 (no weekday, no seconds, no tz)\r
61\r
62 '03-Feb-94', # old rfc850 HTTP format (no weekday, no time)\r
63 '03-Feb-1994', # broken rfc850 HTTP format (no weekday, no time)\r
64 '03 Feb 1994', # proposed new HTTP format (no weekday, no time)\r
65\r
66 # A few tests with extra space at various places\r
67 ' 03 Feb 1994 0:00 ',\r
68 ' 03-Feb-1994 ',\r
69 ]\r
70\r
71 test_t = 760233600 # assume broken POSIX counting of seconds\r
72 result = time2isoz(test_t)\r
73 expected = "1994-02-03 00:00:00Z"\r
74 self.assertEqual(result, expected,\r
75 "%s => '%s' (%s)" % (test_t, result, expected))\r
76\r
77 for s in tests:\r
78 t = http2time(s)\r
79 t2 = http2time(s.lower())\r
80 t3 = http2time(s.upper())\r
81\r
82 self.assertTrue(t == t2 == t3 == test_t,\r
83 "'%s' => %s, %s, %s (%s)" % (s, t, t2, t3, test_t))\r
84\r
85 def test_http2time_garbage(self):\r
86 from cookielib import http2time\r
87\r
88 for test in [\r
89 '',\r
90 'Garbage',\r
91 'Mandag 16. September 1996',\r
92 '01-00-1980',\r
93 '01-13-1980',\r
94 '00-01-1980',\r
95 '32-01-1980',\r
96 '01-01-1980 25:00:00',\r
97 '01-01-1980 00:61:00',\r
98 '01-01-1980 00:00:62',\r
99 ]:\r
100 self.assertTrue(http2time(test) is None,\r
101 "http2time(%s) is not None\n"\r
102 "http2time(test) %s" % (test, http2time(test))\r
103 )\r
104\r
105\r
106class HeaderTests(TestCase):\r
107\r
108 def test_parse_ns_headers_expires(self):\r
109 from cookielib import parse_ns_headers\r
110\r
111 # quotes should be stripped\r
112 expected = [[('foo', 'bar'), ('expires', 2209069412L), ('version', '0')]]\r
113 for hdr in [\r
114 'foo=bar; expires=01 Jan 2040 22:23:32 GMT',\r
115 'foo=bar; expires="01 Jan 2040 22:23:32 GMT"',\r
116 ]:\r
117 self.assertEqual(parse_ns_headers([hdr]), expected)\r
118\r
119 def test_parse_ns_headers_version(self):\r
120 from cookielib import parse_ns_headers\r
121\r
122 # quotes should be stripped\r
123 expected = [[('foo', 'bar'), ('version', '1')]]\r
124 for hdr in [\r
125 'foo=bar; version="1"',\r
126 'foo=bar; Version="1"',\r
127 ]:\r
128 self.assertEqual(parse_ns_headers([hdr]), expected)\r
129\r
130 def test_parse_ns_headers_special_names(self):\r
131 # names such as 'expires' are not special in first name=value pair\r
132 # of Set-Cookie: header\r
133 from cookielib import parse_ns_headers\r
134\r
135 # Cookie with name 'expires'\r
136 hdr = 'expires=01 Jan 2040 22:23:32 GMT'\r
137 expected = [[("expires", "01 Jan 2040 22:23:32 GMT"), ("version", "0")]]\r
138 self.assertEqual(parse_ns_headers([hdr]), expected)\r
139\r
140 def test_join_header_words(self):\r
141 from cookielib import join_header_words\r
142\r
143 joined = join_header_words([[("foo", None), ("bar", "baz")]])\r
144 self.assertEqual(joined, "foo; bar=baz")\r
145\r
146 self.assertEqual(join_header_words([[]]), "")\r
147\r
148 def test_split_header_words(self):\r
149 from cookielib import split_header_words\r
150\r
151 tests = [\r
152 ("foo", [[("foo", None)]]),\r
153 ("foo=bar", [[("foo", "bar")]]),\r
154 (" foo ", [[("foo", None)]]),\r
155 (" foo= ", [[("foo", "")]]),\r
156 (" foo=", [[("foo", "")]]),\r
157 (" foo= ; ", [[("foo", "")]]),\r
158 (" foo= ; bar= baz ", [[("foo", ""), ("bar", "baz")]]),\r
159 ("foo=bar bar=baz", [[("foo", "bar"), ("bar", "baz")]]),\r
160 # doesn't really matter if this next fails, but it works ATM\r
161 ("foo= bar=baz", [[("foo", "bar=baz")]]),\r
162 ("foo=bar;bar=baz", [[("foo", "bar"), ("bar", "baz")]]),\r
163 ('foo bar baz', [[("foo", None), ("bar", None), ("baz", None)]]),\r
164 ("a, b, c", [[("a", None)], [("b", None)], [("c", None)]]),\r
165 (r'foo; bar=baz, spam=, foo="\,\;\"", bar= ',\r
166 [[("foo", None), ("bar", "baz")],\r
167 [("spam", "")], [("foo", ',;"')], [("bar", "")]]),\r
168 ]\r
169\r
170 for arg, expect in tests:\r
171 try:\r
172 result = split_header_words([arg])\r
173 except:\r
174 import traceback, StringIO\r
175 f = StringIO.StringIO()\r
176 traceback.print_exc(None, f)\r
177 result = "(error -- traceback follows)\n\n%s" % f.getvalue()\r
178 self.assertEqual(result, expect, """\r
179When parsing: '%s'\r
180Expected: '%s'\r
181Got: '%s'\r
182""" % (arg, expect, result))\r
183\r
184 def test_roundtrip(self):\r
185 from cookielib import split_header_words, join_header_words\r
186\r
187 tests = [\r
188 ("foo", "foo"),\r
189 ("foo=bar", "foo=bar"),\r
190 (" foo ", "foo"),\r
191 ("foo=", 'foo=""'),\r
192 ("foo=bar bar=baz", "foo=bar; bar=baz"),\r
193 ("foo=bar;bar=baz", "foo=bar; bar=baz"),\r
194 ('foo bar baz', "foo; bar; baz"),\r
195 (r'foo="\"" bar="\\"', r'foo="\""; bar="\\"'),\r
196 ('foo,,,bar', 'foo, bar'),\r
197 ('foo=bar,bar=baz', 'foo=bar, bar=baz'),\r
198\r
199 ('text/html; charset=iso-8859-1',\r
200 'text/html; charset="iso-8859-1"'),\r
201\r
202 ('foo="bar"; port="80,81"; discard, bar=baz',\r
203 'foo=bar; port="80,81"; discard, bar=baz'),\r
204\r
205 (r'Basic realm="\"foo\\\\bar\""',\r
206 r'Basic; realm="\"foo\\\\bar\""')\r
207 ]\r
208\r
209 for arg, expect in tests:\r
210 input = split_header_words([arg])\r
211 res = join_header_words(input)\r
212 self.assertEqual(res, expect, """\r
213When parsing: '%s'\r
214Expected: '%s'\r
215Got: '%s'\r
216Input was: '%s'\r
217""" % (arg, expect, res, input))\r
218\r
219\r
220class FakeResponse:\r
221 def __init__(self, headers=[], url=None):\r
222 """\r
223 headers: list of RFC822-style 'Key: value' strings\r
224 """\r
225 import mimetools, StringIO\r
226 f = StringIO.StringIO("\n".join(headers))\r
227 self._headers = mimetools.Message(f)\r
228 self._url = url\r
229 def info(self): return self._headers\r
230\r
231def interact_2965(cookiejar, url, *set_cookie_hdrs):\r
232 return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie2")\r
233\r
234def interact_netscape(cookiejar, url, *set_cookie_hdrs):\r
235 return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie")\r
236\r
237def _interact(cookiejar, url, set_cookie_hdrs, hdr_name):\r
238 """Perform a single request / response cycle, returning Cookie: header."""\r
239 from urllib2 import Request\r
240 req = Request(url)\r
241 cookiejar.add_cookie_header(req)\r
242 cookie_hdr = req.get_header("Cookie", "")\r
243 headers = []\r
244 for hdr in set_cookie_hdrs:\r
245 headers.append("%s: %s" % (hdr_name, hdr))\r
246 res = FakeResponse(headers, url)\r
247 cookiejar.extract_cookies(res, req)\r
248 return cookie_hdr\r
249\r
250\r
251class FileCookieJarTests(TestCase):\r
252 def test_lwp_valueless_cookie(self):\r
253 # cookies with no value should be saved and loaded consistently\r
254 from cookielib import LWPCookieJar\r
255 filename = test_support.TESTFN\r
256 c = LWPCookieJar()\r
257 interact_netscape(c, "http://www.acme.com/", 'boo')\r
258 self.assertEqual(c._cookies["www.acme.com"]["/"]["boo"].value, None)\r
259 try:\r
260 c.save(filename, ignore_discard=True)\r
261 c = LWPCookieJar()\r
262 c.load(filename, ignore_discard=True)\r
263 finally:\r
264 try: os.unlink(filename)\r
265 except OSError: pass\r
266 self.assertEqual(c._cookies["www.acme.com"]["/"]["boo"].value, None)\r
267\r
268 def test_bad_magic(self):\r
269 from cookielib import LWPCookieJar, MozillaCookieJar, LoadError\r
270 # IOErrors (eg. file doesn't exist) are allowed to propagate\r
271 filename = test_support.TESTFN\r
272 for cookiejar_class in LWPCookieJar, MozillaCookieJar:\r
273 c = cookiejar_class()\r
274 try:\r
275 c.load(filename="for this test to work, a file with this "\r
276 "filename should not exist")\r
277 except IOError, exc:\r
278 # exactly IOError, not LoadError\r
279 self.assertEqual(exc.__class__, IOError)\r
280 else:\r
281 self.fail("expected IOError for invalid filename")\r
282 # Invalid contents of cookies file (eg. bad magic string)\r
283 # causes a LoadError.\r
284 try:\r
285 f = open(filename, "w")\r
286 f.write("oops\n")\r
287 for cookiejar_class in LWPCookieJar, MozillaCookieJar:\r
288 c = cookiejar_class()\r
289 self.assertRaises(LoadError, c.load, filename)\r
290 finally:\r
291 try: os.unlink(filename)\r
292 except OSError: pass\r
293\r
294class CookieTests(TestCase):\r
295 # XXX\r
296 # Get rid of string comparisons where not actually testing str / repr.\r
297 # .clear() etc.\r
298 # IP addresses like 50 (single number, no dot) and domain-matching\r
299 # functions (and is_HDN)? See draft RFC 2965 errata.\r
300 # Strictness switches\r
301 # is_third_party()\r
302 # unverifiability / third-party blocking\r
303 # Netscape cookies work the same as RFC 2965 with regard to port.\r
304 # Set-Cookie with negative max age.\r
305 # If turn RFC 2965 handling off, Set-Cookie2 cookies should not clobber\r
306 # Set-Cookie cookies.\r
307 # Cookie2 should be sent if *any* cookies are not V1 (ie. V0 OR V2 etc.).\r
308 # Cookies (V1 and V0) with no expiry date should be set to be discarded.\r
309 # RFC 2965 Quoting:\r
310 # Should accept unquoted cookie-attribute values? check errata draft.\r
311 # Which are required on the way in and out?\r
312 # Should always return quoted cookie-attribute values?\r
313 # Proper testing of when RFC 2965 clobbers Netscape (waiting for errata).\r
314 # Path-match on return (same for V0 and V1).\r
315 # RFC 2965 acceptance and returning rules\r
316 # Set-Cookie2 without version attribute is rejected.\r
317\r
318 # Netscape peculiarities list from Ronald Tschalar.\r
319 # The first two still need tests, the rest are covered.\r
320## - Quoting: only quotes around the expires value are recognized as such\r
321## (and yes, some folks quote the expires value); quotes around any other\r
322## value are treated as part of the value.\r
323## - White space: white space around names and values is ignored\r
324## - Default path: if no path parameter is given, the path defaults to the\r
325## path in the request-uri up to, but not including, the last '/'. Note\r
326## that this is entirely different from what the spec says.\r
327## - Commas and other delimiters: Netscape just parses until the next ';'.\r
328## This means it will allow commas etc inside values (and yes, both\r
329## commas and equals are commonly appear in the cookie value). This also\r
330## means that if you fold multiple Set-Cookie header fields into one,\r
331## comma-separated list, it'll be a headache to parse (at least my head\r
332## starts hurting everytime I think of that code).\r
333## - Expires: You'll get all sorts of date formats in the expires,\r
334## including emtpy expires attributes ("expires="). Be as flexible as you\r
335## can, and certainly don't expect the weekday to be there; if you can't\r
336## parse it, just ignore it and pretend it's a session cookie.\r
337## - Domain-matching: Netscape uses the 2-dot rule for _all_ domains, not\r
338## just the 7 special TLD's listed in their spec. And folks rely on\r
339## that...\r
340\r
341 def test_domain_return_ok(self):\r
342 # test optimization: .domain_return_ok() should filter out most\r
343 # domains in the CookieJar before we try to access them (because that\r
344 # may require disk access -- in particular, with MSIECookieJar)\r
345 # This is only a rough check for performance reasons, so it's not too\r
346 # critical as long as it's sufficiently liberal.\r
347 import cookielib, urllib2\r
348 pol = cookielib.DefaultCookiePolicy()\r
349 for url, domain, ok in [\r
350 ("http://foo.bar.com/", "blah.com", False),\r
351 ("http://foo.bar.com/", "rhubarb.blah.com", False),\r
352 ("http://foo.bar.com/", "rhubarb.foo.bar.com", False),\r
353 ("http://foo.bar.com/", ".foo.bar.com", True),\r
354 ("http://foo.bar.com/", "foo.bar.com", True),\r
355 ("http://foo.bar.com/", ".bar.com", True),\r
356 ("http://foo.bar.com/", "com", True),\r
357 ("http://foo.com/", "rhubarb.foo.com", False),\r
358 ("http://foo.com/", ".foo.com", True),\r
359 ("http://foo.com/", "foo.com", True),\r
360 ("http://foo.com/", "com", True),\r
361 ("http://foo/", "rhubarb.foo", False),\r
362 ("http://foo/", ".foo", True),\r
363 ("http://foo/", "foo", True),\r
364 ("http://foo/", "foo.local", True),\r
365 ("http://foo/", ".local", True),\r
366 ]:\r
367 request = urllib2.Request(url)\r
368 r = pol.domain_return_ok(domain, request)\r
369 if ok: self.assertTrue(r)\r
370 else: self.assertTrue(not r)\r
371\r
372 def test_missing_value(self):\r
373 from cookielib import MozillaCookieJar, lwp_cookie_str\r
374\r
375 # missing = sign in Cookie: header is regarded by Mozilla as a missing\r
376 # name, and by cookielib as a missing value\r
377 filename = test_support.TESTFN\r
378 c = MozillaCookieJar(filename)\r
379 interact_netscape(c, "http://www.acme.com/", 'eggs')\r
380 interact_netscape(c, "http://www.acme.com/", '"spam"; path=/foo/')\r
381 cookie = c._cookies["www.acme.com"]["/"]["eggs"]\r
382 self.assertTrue(cookie.value is None)\r
383 self.assertEqual(cookie.name, "eggs")\r
384 cookie = c._cookies["www.acme.com"]['/foo/']['"spam"']\r
385 self.assertTrue(cookie.value is None)\r
386 self.assertEqual(cookie.name, '"spam"')\r
387 self.assertEqual(lwp_cookie_str(cookie), (\r
388 r'"spam"; path="/foo/"; domain="www.acme.com"; '\r
389 'path_spec; discard; version=0'))\r
390 old_str = repr(c)\r
391 c.save(ignore_expires=True, ignore_discard=True)\r
392 try:\r
393 c = MozillaCookieJar(filename)\r
394 c.revert(ignore_expires=True, ignore_discard=True)\r
395 finally:\r
396 os.unlink(c.filename)\r
397 # cookies unchanged apart from lost info re. whether path was specified\r
398 self.assertEqual(\r
399 repr(c),\r
400 re.sub("path_specified=%s" % True, "path_specified=%s" % False,\r
401 old_str)\r
402 )\r
403 self.assertEqual(interact_netscape(c, "http://www.acme.com/foo/"),\r
404 '"spam"; eggs')\r
405\r
406 def test_rfc2109_handling(self):\r
407 # RFC 2109 cookies are handled as RFC 2965 or Netscape cookies,\r
408 # dependent on policy settings\r
409 from cookielib import CookieJar, DefaultCookiePolicy\r
410\r
411 for rfc2109_as_netscape, rfc2965, version in [\r
412 # default according to rfc2965 if not explicitly specified\r
413 (None, False, 0),\r
414 (None, True, 1),\r
415 # explicit rfc2109_as_netscape\r
416 (False, False, None), # version None here means no cookie stored\r
417 (False, True, 1),\r
418 (True, False, 0),\r
419 (True, True, 0),\r
420 ]:\r
421 policy = DefaultCookiePolicy(\r
422 rfc2109_as_netscape=rfc2109_as_netscape,\r
423 rfc2965=rfc2965)\r
424 c = CookieJar(policy)\r
425 interact_netscape(c, "http://www.example.com/", "ni=ni; Version=1")\r
426 try:\r
427 cookie = c._cookies["www.example.com"]["/"]["ni"]\r
428 except KeyError:\r
429 self.assertTrue(version is None) # didn't expect a stored cookie\r
430 else:\r
431 self.assertEqual(cookie.version, version)\r
432 # 2965 cookies are unaffected\r
433 interact_2965(c, "http://www.example.com/",\r
434 "foo=bar; Version=1")\r
435 if rfc2965:\r
436 cookie2965 = c._cookies["www.example.com"]["/"]["foo"]\r
437 self.assertEqual(cookie2965.version, 1)\r
438\r
439 def test_ns_parser(self):\r
440 from cookielib import CookieJar, DEFAULT_HTTP_PORT\r
441\r
442 c = CookieJar()\r
443 interact_netscape(c, "http://www.acme.com/",\r
444 'spam=eggs; DoMain=.acme.com; port; blArgh="feep"')\r
445 interact_netscape(c, "http://www.acme.com/", 'ni=ni; port=80,8080')\r
446 interact_netscape(c, "http://www.acme.com:80/", 'nini=ni')\r
447 interact_netscape(c, "http://www.acme.com:80/", 'foo=bar; expires=')\r
448 interact_netscape(c, "http://www.acme.com:80/", 'spam=eggs; '\r
449 'expires="Foo Bar 25 33:22:11 3022"')\r
450\r
451 cookie = c._cookies[".acme.com"]["/"]["spam"]\r
452 self.assertEqual(cookie.domain, ".acme.com")\r
453 self.assertTrue(cookie.domain_specified)\r
454 self.assertEqual(cookie.port, DEFAULT_HTTP_PORT)\r
455 self.assertTrue(not cookie.port_specified)\r
456 # case is preserved\r
457 self.assertTrue(cookie.has_nonstandard_attr("blArgh") and\r
458 not cookie.has_nonstandard_attr("blargh"))\r
459\r
460 cookie = c._cookies["www.acme.com"]["/"]["ni"]\r
461 self.assertEqual(cookie.domain, "www.acme.com")\r
462 self.assertTrue(not cookie.domain_specified)\r
463 self.assertEqual(cookie.port, "80,8080")\r
464 self.assertTrue(cookie.port_specified)\r
465\r
466 cookie = c._cookies["www.acme.com"]["/"]["nini"]\r
467 self.assertTrue(cookie.port is None)\r
468 self.assertTrue(not cookie.port_specified)\r
469\r
470 # invalid expires should not cause cookie to be dropped\r
471 foo = c._cookies["www.acme.com"]["/"]["foo"]\r
472 spam = c._cookies["www.acme.com"]["/"]["foo"]\r
473 self.assertTrue(foo.expires is None)\r
474 self.assertTrue(spam.expires is None)\r
475\r
476 def test_ns_parser_special_names(self):\r
477 # names such as 'expires' are not special in first name=value pair\r
478 # of Set-Cookie: header\r
479 from cookielib import CookieJar\r
480\r
481 c = CookieJar()\r
482 interact_netscape(c, "http://www.acme.com/", 'expires=eggs')\r
483 interact_netscape(c, "http://www.acme.com/", 'version=eggs; spam=eggs')\r
484\r
485 cookies = c._cookies["www.acme.com"]["/"]\r
486 self.assertTrue('expires' in cookies)\r
487 self.assertTrue('version' in cookies)\r
488\r
489 def test_expires(self):\r
490 from cookielib import time2netscape, CookieJar\r
491\r
492 # if expires is in future, keep cookie...\r
493 c = CookieJar()\r
494 future = time2netscape(time.time()+3600)\r
495 interact_netscape(c, "http://www.acme.com/", 'spam="bar"; expires=%s' %\r
496 future)\r
497 self.assertEqual(len(c), 1)\r
498 now = time2netscape(time.time()-1)\r
499 # ... and if in past or present, discard it\r
500 interact_netscape(c, "http://www.acme.com/", 'foo="eggs"; expires=%s' %\r
501 now)\r
502 h = interact_netscape(c, "http://www.acme.com/")\r
503 self.assertEqual(len(c), 1)\r
504 self.assertTrue('spam="bar"' in h and "foo" not in h)\r
505\r
506 # max-age takes precedence over expires, and zero max-age is request to\r
507 # delete both new cookie and any old matching cookie\r
508 interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; expires=%s' %\r
509 future)\r
510 interact_netscape(c, "http://www.acme.com/", 'bar="bar"; expires=%s' %\r
511 future)\r
512 self.assertEqual(len(c), 3)\r
513 interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; '\r
514 'expires=%s; max-age=0' % future)\r
515 interact_netscape(c, "http://www.acme.com/", 'bar="bar"; '\r
516 'max-age=0; expires=%s' % future)\r
517 h = interact_netscape(c, "http://www.acme.com/")\r
518 self.assertEqual(len(c), 1)\r
519\r
520 # test expiry at end of session for cookies with no expires attribute\r
521 interact_netscape(c, "http://www.rhubarb.net/", 'whum="fizz"')\r
522 self.assertEqual(len(c), 2)\r
523 c.clear_session_cookies()\r
524 self.assertEqual(len(c), 1)\r
525 self.assertIn('spam="bar"', h)\r
526\r
527 # XXX RFC 2965 expiry rules (some apply to V0 too)\r
528\r
529 def test_default_path(self):\r
530 from cookielib import CookieJar, DefaultCookiePolicy\r
531\r
532 # RFC 2965\r
533 pol = DefaultCookiePolicy(rfc2965=True)\r
534\r
535 c = CookieJar(pol)\r
536 interact_2965(c, "http://www.acme.com/", 'spam="bar"; Version="1"')\r
537 self.assertIn("/", c._cookies["www.acme.com"])\r
538\r
539 c = CookieJar(pol)\r
540 interact_2965(c, "http://www.acme.com/blah", 'eggs="bar"; Version="1"')\r
541 self.assertIn("/", c._cookies["www.acme.com"])\r
542\r
543 c = CookieJar(pol)\r
544 interact_2965(c, "http://www.acme.com/blah/rhubarb",\r
545 'eggs="bar"; Version="1"')\r
546 self.assertIn("/blah/", c._cookies["www.acme.com"])\r
547\r
548 c = CookieJar(pol)\r
549 interact_2965(c, "http://www.acme.com/blah/rhubarb/",\r
550 'eggs="bar"; Version="1"')\r
551 self.assertIn("/blah/rhubarb/", c._cookies["www.acme.com"])\r
552\r
553 # Netscape\r
554\r
555 c = CookieJar()\r
556 interact_netscape(c, "http://www.acme.com/", 'spam="bar"')\r
557 self.assertIn("/", c._cookies["www.acme.com"])\r
558\r
559 c = CookieJar()\r
560 interact_netscape(c, "http://www.acme.com/blah", 'eggs="bar"')\r
561 self.assertIn("/", c._cookies["www.acme.com"])\r
562\r
563 c = CookieJar()\r
564 interact_netscape(c, "http://www.acme.com/blah/rhubarb", 'eggs="bar"')\r
565 self.assertIn("/blah", c._cookies["www.acme.com"])\r
566\r
567 c = CookieJar()\r
568 interact_netscape(c, "http://www.acme.com/blah/rhubarb/", 'eggs="bar"')\r
569 self.assertIn("/blah/rhubarb", c._cookies["www.acme.com"])\r
570\r
571 def test_default_path_with_query(self):\r
572 cj = cookielib.CookieJar()\r
573 uri = "http://example.com/?spam/eggs"\r
574 value = 'eggs="bar"'\r
575 interact_netscape(cj, uri, value)\r
576 # default path does not include query, so is "/", not "/?spam"\r
577 self.assertIn("/", cj._cookies["example.com"])\r
578 # cookie is sent back to the same URI\r
579 self.assertEqual(interact_netscape(cj, uri), value)\r
580\r
581 def test_escape_path(self):\r
582 from cookielib import escape_path\r
583 cases = [\r
584 # quoted safe\r
585 ("/foo%2f/bar", "/foo%2F/bar"),\r
586 ("/foo%2F/bar", "/foo%2F/bar"),\r
587 # quoted %\r
588 ("/foo%%/bar", "/foo%%/bar"),\r
589 # quoted unsafe\r
590 ("/fo%19o/bar", "/fo%19o/bar"),\r
591 ("/fo%7do/bar", "/fo%7Do/bar"),\r
592 # unquoted safe\r
593 ("/foo/bar&", "/foo/bar&"),\r
594 ("/foo//bar", "/foo//bar"),\r
595 ("\176/foo/bar", "\176/foo/bar"),\r
596 # unquoted unsafe\r
597 ("/foo\031/bar", "/foo%19/bar"),\r
598 ("/\175foo/bar", "/%7Dfoo/bar"),\r
599 # unicode\r
600 (u"/foo/bar\uabcd", "/foo/bar%EA%AF%8D"), # UTF-8 encoded\r
601 ]\r
602 for arg, result in cases:\r
603 self.assertEqual(escape_path(arg), result)\r
604\r
605 def test_request_path(self):\r
606 from urllib2 import Request\r
607 from cookielib import request_path\r
608 # with parameters\r
609 req = Request("http://www.example.com/rheum/rhaponticum;"\r
610 "foo=bar;sing=song?apples=pears&spam=eggs#ni")\r
611 self.assertEqual(request_path(req),\r
612 "/rheum/rhaponticum;foo=bar;sing=song")\r
613 # without parameters\r
614 req = Request("http://www.example.com/rheum/rhaponticum?"\r
615 "apples=pears&spam=eggs#ni")\r
616 self.assertEqual(request_path(req), "/rheum/rhaponticum")\r
617 # missing final slash\r
618 req = Request("http://www.example.com")\r
619 self.assertEqual(request_path(req), "/")\r
620\r
621 def test_request_port(self):\r
622 from urllib2 import Request\r
623 from cookielib import request_port, DEFAULT_HTTP_PORT\r
624 req = Request("http://www.acme.com:1234/",\r
625 headers={"Host": "www.acme.com:4321"})\r
626 self.assertEqual(request_port(req), "1234")\r
627 req = Request("http://www.acme.com/",\r
628 headers={"Host": "www.acme.com:4321"})\r
629 self.assertEqual(request_port(req), DEFAULT_HTTP_PORT)\r
630\r
631 def test_request_host(self):\r
632 from urllib2 import Request\r
633 from cookielib import request_host\r
634 # this request is illegal (RFC2616, 14.2.3)\r
635 req = Request("http://1.1.1.1/",\r
636 headers={"Host": "www.acme.com:80"})\r
637 # libwww-perl wants this response, but that seems wrong (RFC 2616,\r
638 # section 5.2, point 1., and RFC 2965 section 1, paragraph 3)\r
639 #self.assertEqual(request_host(req), "www.acme.com")\r
640 self.assertEqual(request_host(req), "1.1.1.1")\r
641 req = Request("http://www.acme.com/",\r
642 headers={"Host": "irrelevant.com"})\r
643 self.assertEqual(request_host(req), "www.acme.com")\r
644 # not actually sure this one is valid Request object, so maybe should\r
645 # remove test for no host in url in request_host function?\r
646 req = Request("/resource.html",\r
647 headers={"Host": "www.acme.com"})\r
648 self.assertEqual(request_host(req), "www.acme.com")\r
649 # port shouldn't be in request-host\r
650 req = Request("http://www.acme.com:2345/resource.html",\r
651 headers={"Host": "www.acme.com:5432"})\r
652 self.assertEqual(request_host(req), "www.acme.com")\r
653\r
654 def test_is_HDN(self):\r
655 from cookielib import is_HDN\r
656 self.assertTrue(is_HDN("foo.bar.com"))\r
657 self.assertTrue(is_HDN("1foo2.3bar4.5com"))\r
658 self.assertTrue(not is_HDN("192.168.1.1"))\r
659 self.assertTrue(not is_HDN(""))\r
660 self.assertTrue(not is_HDN("."))\r
661 self.assertTrue(not is_HDN(".foo.bar.com"))\r
662 self.assertTrue(not is_HDN("..foo"))\r
663 self.assertTrue(not is_HDN("foo."))\r
664\r
665 def test_reach(self):\r
666 from cookielib import reach\r
667 self.assertEqual(reach("www.acme.com"), ".acme.com")\r
668 self.assertEqual(reach("acme.com"), "acme.com")\r
669 self.assertEqual(reach("acme.local"), ".local")\r
670 self.assertEqual(reach(".local"), ".local")\r
671 self.assertEqual(reach(".com"), ".com")\r
672 self.assertEqual(reach("."), ".")\r
673 self.assertEqual(reach(""), "")\r
674 self.assertEqual(reach("192.168.0.1"), "192.168.0.1")\r
675\r
676 def test_domain_match(self):\r
677 from cookielib import domain_match, user_domain_match\r
678 self.assertTrue(domain_match("192.168.1.1", "192.168.1.1"))\r
679 self.assertTrue(not domain_match("192.168.1.1", ".168.1.1"))\r
680 self.assertTrue(domain_match("x.y.com", "x.Y.com"))\r
681 self.assertTrue(domain_match("x.y.com", ".Y.com"))\r
682 self.assertTrue(not domain_match("x.y.com", "Y.com"))\r
683 self.assertTrue(domain_match("a.b.c.com", ".c.com"))\r
684 self.assertTrue(not domain_match(".c.com", "a.b.c.com"))\r
685 self.assertTrue(domain_match("example.local", ".local"))\r
686 self.assertTrue(not domain_match("blah.blah", ""))\r
687 self.assertTrue(not domain_match("", ".rhubarb.rhubarb"))\r
688 self.assertTrue(domain_match("", ""))\r
689\r
690 self.assertTrue(user_domain_match("acme.com", "acme.com"))\r
691 self.assertTrue(not user_domain_match("acme.com", ".acme.com"))\r
692 self.assertTrue(user_domain_match("rhubarb.acme.com", ".acme.com"))\r
693 self.assertTrue(user_domain_match("www.rhubarb.acme.com", ".acme.com"))\r
694 self.assertTrue(user_domain_match("x.y.com", "x.Y.com"))\r
695 self.assertTrue(user_domain_match("x.y.com", ".Y.com"))\r
696 self.assertTrue(not user_domain_match("x.y.com", "Y.com"))\r
697 self.assertTrue(user_domain_match("y.com", "Y.com"))\r
698 self.assertTrue(not user_domain_match(".y.com", "Y.com"))\r
699 self.assertTrue(user_domain_match(".y.com", ".Y.com"))\r
700 self.assertTrue(user_domain_match("x.y.com", ".com"))\r
701 self.assertTrue(not user_domain_match("x.y.com", "com"))\r
702 self.assertTrue(not user_domain_match("x.y.com", "m"))\r
703 self.assertTrue(not user_domain_match("x.y.com", ".m"))\r
704 self.assertTrue(not user_domain_match("x.y.com", ""))\r
705 self.assertTrue(not user_domain_match("x.y.com", "."))\r
706 self.assertTrue(user_domain_match("192.168.1.1", "192.168.1.1"))\r
707 # not both HDNs, so must string-compare equal to match\r
708 self.assertTrue(not user_domain_match("192.168.1.1", ".168.1.1"))\r
709 self.assertTrue(not user_domain_match("192.168.1.1", "."))\r
710 # empty string is a special case\r
711 self.assertTrue(not user_domain_match("192.168.1.1", ""))\r
712\r
713 def test_wrong_domain(self):\r
714 # Cookies whose effective request-host name does not domain-match the\r
715 # domain are rejected.\r
716\r
717 # XXX far from complete\r
718 from cookielib import CookieJar\r
719 c = CookieJar()\r
720 interact_2965(c, "http://www.nasty.com/",\r
721 'foo=bar; domain=friendly.org; Version="1"')\r
722 self.assertEqual(len(c), 0)\r
723\r
724 def test_strict_domain(self):\r
725 # Cookies whose domain is a country-code tld like .co.uk should\r
726 # not be set if CookiePolicy.strict_domain is true.\r
727 from cookielib import CookieJar, DefaultCookiePolicy\r
728\r
729 cp = DefaultCookiePolicy(strict_domain=True)\r
730 cj = CookieJar(policy=cp)\r
731 interact_netscape(cj, "http://example.co.uk/", 'no=problemo')\r
732 interact_netscape(cj, "http://example.co.uk/",\r
733 'okey=dokey; Domain=.example.co.uk')\r
734 self.assertEqual(len(cj), 2)\r
735 for pseudo_tld in [".co.uk", ".org.za", ".tx.us", ".name.us"]:\r
736 interact_netscape(cj, "http://example.%s/" % pseudo_tld,\r
737 'spam=eggs; Domain=.co.uk')\r
738 self.assertEqual(len(cj), 2)\r
739\r
740 def test_two_component_domain_ns(self):\r
741 # Netscape: .www.bar.com, www.bar.com, .bar.com, bar.com, no domain\r
742 # should all get accepted, as should .acme.com, acme.com and no domain\r
743 # for 2-component domains like acme.com.\r
744 from cookielib import CookieJar, DefaultCookiePolicy\r
745\r
746 c = CookieJar()\r
747\r
748 # two-component V0 domain is OK\r
749 interact_netscape(c, "http://foo.net/", 'ns=bar')\r
750 self.assertEqual(len(c), 1)\r
751 self.assertEqual(c._cookies["foo.net"]["/"]["ns"].value, "bar")\r
752 self.assertEqual(interact_netscape(c, "http://foo.net/"), "ns=bar")\r
753 # *will* be returned to any other domain (unlike RFC 2965)...\r
754 self.assertEqual(interact_netscape(c, "http://www.foo.net/"),\r
755 "ns=bar")\r
756 # ...unless requested otherwise\r
757 pol = DefaultCookiePolicy(\r
758 strict_ns_domain=DefaultCookiePolicy.DomainStrictNonDomain)\r
759 c.set_policy(pol)\r
760 self.assertEqual(interact_netscape(c, "http://www.foo.net/"), "")\r
761\r
762 # unlike RFC 2965, even explicit two-component domain is OK,\r
763 # because .foo.net matches foo.net\r
764 interact_netscape(c, "http://foo.net/foo/",\r
765 'spam1=eggs; domain=foo.net')\r
766 # even if starts with a dot -- in NS rules, .foo.net matches foo.net!\r
767 interact_netscape(c, "http://foo.net/foo/bar/",\r
768 'spam2=eggs; domain=.foo.net')\r
769 self.assertEqual(len(c), 3)\r
770 self.assertEqual(c._cookies[".foo.net"]["/foo"]["spam1"].value,\r
771 "eggs")\r
772 self.assertEqual(c._cookies[".foo.net"]["/foo/bar"]["spam2"].value,\r
773 "eggs")\r
774 self.assertEqual(interact_netscape(c, "http://foo.net/foo/bar/"),\r
775 "spam2=eggs; spam1=eggs; ns=bar")\r
776\r
777 # top-level domain is too general\r
778 interact_netscape(c, "http://foo.net/", 'nini="ni"; domain=.net')\r
779 self.assertEqual(len(c), 3)\r
780\r
781## # Netscape protocol doesn't allow non-special top level domains (such\r
782## # as co.uk) in the domain attribute unless there are at least three\r
783## # dots in it.\r
784 # Oh yes it does! Real implementations don't check this, and real\r
785 # cookies (of course) rely on that behaviour.\r
786 interact_netscape(c, "http://foo.co.uk", 'nasty=trick; domain=.co.uk')\r
787## self.assertEqual(len(c), 2)\r
788 self.assertEqual(len(c), 4)\r
789\r
790 def test_two_component_domain_rfc2965(self):\r
791 from cookielib import CookieJar, DefaultCookiePolicy\r
792\r
793 pol = DefaultCookiePolicy(rfc2965=True)\r
794 c = CookieJar(pol)\r
795\r
796 # two-component V1 domain is OK\r
797 interact_2965(c, "http://foo.net/", 'foo=bar; Version="1"')\r
798 self.assertEqual(len(c), 1)\r
799 self.assertEqual(c._cookies["foo.net"]["/"]["foo"].value, "bar")\r
800 self.assertEqual(interact_2965(c, "http://foo.net/"),\r
801 "$Version=1; foo=bar")\r
802 # won't be returned to any other domain (because domain was implied)\r
803 self.assertEqual(interact_2965(c, "http://www.foo.net/"), "")\r
804\r
805 # unless domain is given explicitly, because then it must be\r
806 # rewritten to start with a dot: foo.net --> .foo.net, which does\r
807 # not domain-match foo.net\r
808 interact_2965(c, "http://foo.net/foo",\r
809 'spam=eggs; domain=foo.net; path=/foo; Version="1"')\r
810 self.assertEqual(len(c), 1)\r
811 self.assertEqual(interact_2965(c, "http://foo.net/foo"),\r
812 "$Version=1; foo=bar")\r
813\r
814 # explicit foo.net from three-component domain www.foo.net *does* get\r
815 # set, because .foo.net domain-matches .foo.net\r
816 interact_2965(c, "http://www.foo.net/foo/",\r
817 'spam=eggs; domain=foo.net; Version="1"')\r
818 self.assertEqual(c._cookies[".foo.net"]["/foo/"]["spam"].value,\r
819 "eggs")\r
820 self.assertEqual(len(c), 2)\r
821 self.assertEqual(interact_2965(c, "http://foo.net/foo/"),\r
822 "$Version=1; foo=bar")\r
823 self.assertEqual(interact_2965(c, "http://www.foo.net/foo/"),\r
824 '$Version=1; spam=eggs; $Domain="foo.net"')\r
825\r
826 # top-level domain is too general\r
827 interact_2965(c, "http://foo.net/",\r
828 'ni="ni"; domain=".net"; Version="1"')\r
829 self.assertEqual(len(c), 2)\r
830\r
831 # RFC 2965 doesn't require blocking this\r
832 interact_2965(c, "http://foo.co.uk/",\r
833 'nasty=trick; domain=.co.uk; Version="1"')\r
834 self.assertEqual(len(c), 3)\r
835\r
836 def test_domain_allow(self):\r
837 from cookielib import CookieJar, DefaultCookiePolicy\r
838 from urllib2 import Request\r
839\r
840 c = CookieJar(policy=DefaultCookiePolicy(\r
841 blocked_domains=["acme.com"],\r
842 allowed_domains=["www.acme.com"]))\r
843\r
844 req = Request("http://acme.com/")\r
845 headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"]\r
846 res = FakeResponse(headers, "http://acme.com/")\r
847 c.extract_cookies(res, req)\r
848 self.assertEqual(len(c), 0)\r
849\r
850 req = Request("http://www.acme.com/")\r
851 res = FakeResponse(headers, "http://www.acme.com/")\r
852 c.extract_cookies(res, req)\r
853 self.assertEqual(len(c), 1)\r
854\r
855 req = Request("http://www.coyote.com/")\r
856 res = FakeResponse(headers, "http://www.coyote.com/")\r
857 c.extract_cookies(res, req)\r
858 self.assertEqual(len(c), 1)\r
859\r
860 # set a cookie with non-allowed domain...\r
861 req = Request("http://www.coyote.com/")\r
862 res = FakeResponse(headers, "http://www.coyote.com/")\r
863 cookies = c.make_cookies(res, req)\r
864 c.set_cookie(cookies[0])\r
865 self.assertEqual(len(c), 2)\r
866 # ... and check is doesn't get returned\r
867 c.add_cookie_header(req)\r
868 self.assertTrue(not req.has_header("Cookie"))\r
869\r
870 def test_domain_block(self):\r
871 from cookielib import CookieJar, DefaultCookiePolicy\r
872 from urllib2 import Request\r
873\r
874 pol = DefaultCookiePolicy(\r
875 rfc2965=True, blocked_domains=[".acme.com"])\r
876 c = CookieJar(policy=pol)\r
877 headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"]\r
878\r
879 req = Request("http://www.acme.com/")\r
880 res = FakeResponse(headers, "http://www.acme.com/")\r
881 c.extract_cookies(res, req)\r
882 self.assertEqual(len(c), 0)\r
883\r
884 p = pol.set_blocked_domains(["acme.com"])\r
885 c.extract_cookies(res, req)\r
886 self.assertEqual(len(c), 1)\r
887\r
888 c.clear()\r
889 req = Request("http://www.roadrunner.net/")\r
890 res = FakeResponse(headers, "http://www.roadrunner.net/")\r
891 c.extract_cookies(res, req)\r
892 self.assertEqual(len(c), 1)\r
893 req = Request("http://www.roadrunner.net/")\r
894 c.add_cookie_header(req)\r
895 self.assertTrue((req.has_header("Cookie") and\r
896 req.has_header("Cookie2")))\r
897\r
898 c.clear()\r
899 pol.set_blocked_domains([".acme.com"])\r
900 c.extract_cookies(res, req)\r
901 self.assertEqual(len(c), 1)\r
902\r
903 # set a cookie with blocked domain...\r
904 req = Request("http://www.acme.com/")\r
905 res = FakeResponse(headers, "http://www.acme.com/")\r
906 cookies = c.make_cookies(res, req)\r
907 c.set_cookie(cookies[0])\r
908 self.assertEqual(len(c), 2)\r
909 # ... and check is doesn't get returned\r
910 c.add_cookie_header(req)\r
911 self.assertTrue(not req.has_header("Cookie"))\r
912\r
913 def test_secure(self):\r
914 from cookielib import CookieJar, DefaultCookiePolicy\r
915\r
916 for ns in True, False:\r
917 for whitespace in " ", "":\r
918 c = CookieJar()\r
919 if ns:\r
920 pol = DefaultCookiePolicy(rfc2965=False)\r
921 int = interact_netscape\r
922 vs = ""\r
923 else:\r
924 pol = DefaultCookiePolicy(rfc2965=True)\r
925 int = interact_2965\r
926 vs = "; Version=1"\r
927 c.set_policy(pol)\r
928 url = "http://www.acme.com/"\r
929 int(c, url, "foo1=bar%s%s" % (vs, whitespace))\r
930 int(c, url, "foo2=bar%s; secure%s" % (vs, whitespace))\r
931 self.assertTrue(\r
932 not c._cookies["www.acme.com"]["/"]["foo1"].secure,\r
933 "non-secure cookie registered secure")\r
934 self.assertTrue(\r
935 c._cookies["www.acme.com"]["/"]["foo2"].secure,\r
936 "secure cookie registered non-secure")\r
937\r
938 def test_quote_cookie_value(self):\r
939 from cookielib import CookieJar, DefaultCookiePolicy\r
940 c = CookieJar(policy=DefaultCookiePolicy(rfc2965=True))\r
941 interact_2965(c, "http://www.acme.com/", r'foo=\b"a"r; Version=1')\r
942 h = interact_2965(c, "http://www.acme.com/")\r
943 self.assertEqual(h, r'$Version=1; foo=\\b\"a\"r')\r
944\r
945 def test_missing_final_slash(self):\r
946 # Missing slash from request URL's abs_path should be assumed present.\r
947 from cookielib import CookieJar, DefaultCookiePolicy\r
948 from urllib2 import Request\r
949 url = "http://www.acme.com"\r
950 c = CookieJar(DefaultCookiePolicy(rfc2965=True))\r
951 interact_2965(c, url, "foo=bar; Version=1")\r
952 req = Request(url)\r
953 self.assertEqual(len(c), 1)\r
954 c.add_cookie_header(req)\r
955 self.assertTrue(req.has_header("Cookie"))\r
956\r
957 def test_domain_mirror(self):\r
958 from cookielib import CookieJar, DefaultCookiePolicy\r
959\r
960 pol = DefaultCookiePolicy(rfc2965=True)\r
961\r
962 c = CookieJar(pol)\r
963 url = "http://foo.bar.com/"\r
964 interact_2965(c, url, "spam=eggs; Version=1")\r
965 h = interact_2965(c, url)\r
966 self.assertNotIn("Domain", h,\r
967 "absent domain returned with domain present")\r
968\r
969 c = CookieJar(pol)\r
970 url = "http://foo.bar.com/"\r
971 interact_2965(c, url, 'spam=eggs; Version=1; Domain=.bar.com')\r
972 h = interact_2965(c, url)\r
973 self.assertIn('$Domain=".bar.com"', h, "domain not returned")\r
974\r
975 c = CookieJar(pol)\r
976 url = "http://foo.bar.com/"\r
977 # note missing initial dot in Domain\r
978 interact_2965(c, url, 'spam=eggs; Version=1; Domain=bar.com')\r
979 h = interact_2965(c, url)\r
980 self.assertIn('$Domain="bar.com"', h, "domain not returned")\r
981\r
982 def test_path_mirror(self):\r
983 from cookielib import CookieJar, DefaultCookiePolicy\r
984\r
985 pol = DefaultCookiePolicy(rfc2965=True)\r
986\r
987 c = CookieJar(pol)\r
988 url = "http://foo.bar.com/"\r
989 interact_2965(c, url, "spam=eggs; Version=1")\r
990 h = interact_2965(c, url)\r
991 self.assertNotIn("Path", h, "absent path returned with path present")\r
992\r
993 c = CookieJar(pol)\r
994 url = "http://foo.bar.com/"\r
995 interact_2965(c, url, 'spam=eggs; Version=1; Path=/')\r
996 h = interact_2965(c, url)\r
997 self.assertIn('$Path="/"', h, "path not returned")\r
998\r
999 def test_port_mirror(self):\r
1000 from cookielib import CookieJar, DefaultCookiePolicy\r
1001\r
1002 pol = DefaultCookiePolicy(rfc2965=True)\r
1003\r
1004 c = CookieJar(pol)\r
1005 url = "http://foo.bar.com/"\r
1006 interact_2965(c, url, "spam=eggs; Version=1")\r
1007 h = interact_2965(c, url)\r
1008 self.assertNotIn("Port", h, "absent port returned with port present")\r
1009\r
1010 c = CookieJar(pol)\r
1011 url = "http://foo.bar.com/"\r
1012 interact_2965(c, url, "spam=eggs; Version=1; Port")\r
1013 h = interact_2965(c, url)\r
1014 self.assertTrue(re.search("\$Port([^=]|$)", h),\r
1015 "port with no value not returned with no value")\r
1016\r
1017 c = CookieJar(pol)\r
1018 url = "http://foo.bar.com/"\r
1019 interact_2965(c, url, 'spam=eggs; Version=1; Port="80"')\r
1020 h = interact_2965(c, url)\r
1021 self.assertIn('$Port="80"', h,\r
1022 "port with single value not returned with single value")\r
1023\r
1024 c = CookieJar(pol)\r
1025 url = "http://foo.bar.com/"\r
1026 interact_2965(c, url, 'spam=eggs; Version=1; Port="80,8080"')\r
1027 h = interact_2965(c, url)\r
1028 self.assertIn('$Port="80,8080"', h,\r
1029 "port with multiple values not returned with multiple "\r
1030 "values")\r
1031\r
1032 def test_no_return_comment(self):\r
1033 from cookielib import CookieJar, DefaultCookiePolicy\r
1034\r
1035 c = CookieJar(DefaultCookiePolicy(rfc2965=True))\r
1036 url = "http://foo.bar.com/"\r
1037 interact_2965(c, url, 'spam=eggs; Version=1; '\r
1038 'Comment="does anybody read these?"; '\r
1039 'CommentURL="http://foo.bar.net/comment.html"')\r
1040 h = interact_2965(c, url)\r
1041 self.assertTrue(\r
1042 "Comment" not in h,\r
1043 "Comment or CommentURL cookie-attributes returned to server")\r
1044\r
1045 def test_Cookie_iterator(self):\r
1046 from cookielib import CookieJar, Cookie, DefaultCookiePolicy\r
1047\r
1048 cs = CookieJar(DefaultCookiePolicy(rfc2965=True))\r
1049 # add some random cookies\r
1050 interact_2965(cs, "http://blah.spam.org/", 'foo=eggs; Version=1; '\r
1051 'Comment="does anybody read these?"; '\r
1052 'CommentURL="http://foo.bar.net/comment.html"')\r
1053 interact_netscape(cs, "http://www.acme.com/blah/", "spam=bar; secure")\r
1054 interact_2965(cs, "http://www.acme.com/blah/",\r
1055 "foo=bar; secure; Version=1")\r
1056 interact_2965(cs, "http://www.acme.com/blah/",\r
1057 "foo=bar; path=/; Version=1")\r
1058 interact_2965(cs, "http://www.sol.no",\r
1059 r'bang=wallop; version=1; domain=".sol.no"; '\r
1060 r'port="90,100, 80,8080"; '\r
1061 r'max-age=100; Comment = "Just kidding! (\"|\\\\) "')\r
1062\r
1063 versions = [1, 1, 1, 0, 1]\r
1064 names = ["bang", "foo", "foo", "spam", "foo"]\r
1065 domains = [".sol.no", "blah.spam.org", "www.acme.com",\r
1066 "www.acme.com", "www.acme.com"]\r
1067 paths = ["/", "/", "/", "/blah", "/blah/"]\r
1068\r
1069 for i in range(4):\r
1070 i = 0\r
1071 for c in cs:\r
1072 self.assertIsInstance(c, Cookie)\r
1073 self.assertEqual(c.version, versions[i])\r
1074 self.assertEqual(c.name, names[i])\r
1075 self.assertEqual(c.domain, domains[i])\r
1076 self.assertEqual(c.path, paths[i])\r
1077 i = i + 1\r
1078\r
1079 def test_parse_ns_headers(self):\r
1080 from cookielib import parse_ns_headers\r
1081\r
1082 # missing domain value (invalid cookie)\r
1083 self.assertEqual(\r
1084 parse_ns_headers(["foo=bar; path=/; domain"]),\r
1085 [[("foo", "bar"),\r
1086 ("path", "/"), ("domain", None), ("version", "0")]]\r
1087 )\r
1088 # invalid expires value\r
1089 self.assertEqual(\r
1090 parse_ns_headers(["foo=bar; expires=Foo Bar 12 33:22:11 2000"]),\r
1091 [[("foo", "bar"), ("expires", None), ("version", "0")]]\r
1092 )\r
1093 # missing cookie value (valid cookie)\r
1094 self.assertEqual(\r
1095 parse_ns_headers(["foo"]),\r
1096 [[("foo", None), ("version", "0")]]\r
1097 )\r
1098 # shouldn't add version if header is empty\r
1099 self.assertEqual(parse_ns_headers([""]), [])\r
1100\r
1101 def test_bad_cookie_header(self):\r
1102\r
1103 def cookiejar_from_cookie_headers(headers):\r
1104 from cookielib import CookieJar\r
1105 from urllib2 import Request\r
1106 c = CookieJar()\r
1107 req = Request("http://www.example.com/")\r
1108 r = FakeResponse(headers, "http://www.example.com/")\r
1109 c.extract_cookies(r, req)\r
1110 return c\r
1111\r
1112 # none of these bad headers should cause an exception to be raised\r
1113 for headers in [\r
1114 ["Set-Cookie: "], # actually, nothing wrong with this\r
1115 ["Set-Cookie2: "], # ditto\r
1116 # missing domain value\r
1117 ["Set-Cookie2: a=foo; path=/; Version=1; domain"],\r
1118 # bad max-age\r
1119 ["Set-Cookie: b=foo; max-age=oops"],\r
1120 # bad version\r
1121 ["Set-Cookie: b=foo; version=spam"],\r
1122 ]:\r
1123 c = cookiejar_from_cookie_headers(headers)\r
1124 # these bad cookies shouldn't be set\r
1125 self.assertEqual(len(c), 0)\r
1126\r
1127 # cookie with invalid expires is treated as session cookie\r
1128 headers = ["Set-Cookie: c=foo; expires=Foo Bar 12 33:22:11 2000"]\r
1129 c = cookiejar_from_cookie_headers(headers)\r
1130 cookie = c._cookies["www.example.com"]["/"]["c"]\r
1131 self.assertTrue(cookie.expires is None)\r
1132\r
1133\r
1134class LWPCookieTests(TestCase):\r
1135 # Tests taken from libwww-perl, with a few modifications and additions.\r
1136\r
1137 def test_netscape_example_1(self):\r
1138 from cookielib import CookieJar, DefaultCookiePolicy\r
1139 from urllib2 import Request\r
1140\r
1141 #-------------------------------------------------------------------\r
1142 # First we check that it works for the original example at\r
1143 # http://www.netscape.com/newsref/std/cookie_spec.html\r
1144\r
1145 # Client requests a document, and receives in the response:\r
1146 #\r
1147 # Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT\r
1148 #\r
1149 # When client requests a URL in path "/" on this server, it sends:\r
1150 #\r
1151 # Cookie: CUSTOMER=WILE_E_COYOTE\r
1152 #\r
1153 # Client requests a document, and receives in the response:\r
1154 #\r
1155 # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/\r
1156 #\r
1157 # When client requests a URL in path "/" on this server, it sends:\r
1158 #\r
1159 # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001\r
1160 #\r
1161 # Client receives:\r
1162 #\r
1163 # Set-Cookie: SHIPPING=FEDEX; path=/fo\r
1164 #\r
1165 # When client requests a URL in path "/" on this server, it sends:\r
1166 #\r
1167 # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001\r
1168 #\r
1169 # When client requests a URL in path "/foo" on this server, it sends:\r
1170 #\r
1171 # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX\r
1172 #\r
1173 # The last Cookie is buggy, because both specifications say that the\r
1174 # most specific cookie must be sent first. SHIPPING=FEDEX is the\r
1175 # most specific and should thus be first.\r
1176\r
1177 year_plus_one = time.localtime()[0] + 1\r
1178\r
1179 headers = []\r
1180\r
1181 c = CookieJar(DefaultCookiePolicy(rfc2965 = True))\r
1182\r
1183 #req = Request("http://1.1.1.1/",\r
1184 # headers={"Host": "www.acme.com:80"})\r
1185 req = Request("http://www.acme.com:80/",\r
1186 headers={"Host": "www.acme.com:80"})\r
1187\r
1188 headers.append(\r
1189 "Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/ ; "\r
1190 "expires=Wednesday, 09-Nov-%d 23:12:40 GMT" % year_plus_one)\r
1191 res = FakeResponse(headers, "http://www.acme.com/")\r
1192 c.extract_cookies(res, req)\r
1193\r
1194 req = Request("http://www.acme.com/")\r
1195 c.add_cookie_header(req)\r
1196\r
1197 self.assertEqual(req.get_header("Cookie"), "CUSTOMER=WILE_E_COYOTE")\r
1198 self.assertEqual(req.get_header("Cookie2"), '$Version="1"')\r
1199\r
1200 headers.append("Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/")\r
1201 res = FakeResponse(headers, "http://www.acme.com/")\r
1202 c.extract_cookies(res, req)\r
1203\r
1204 req = Request("http://www.acme.com/foo/bar")\r
1205 c.add_cookie_header(req)\r
1206\r
1207 h = req.get_header("Cookie")\r
1208 self.assertIn("PART_NUMBER=ROCKET_LAUNCHER_0001", h)\r
1209 self.assertIn("CUSTOMER=WILE_E_COYOTE", h)\r
1210\r
1211 headers.append('Set-Cookie: SHIPPING=FEDEX; path=/foo')\r
1212 res = FakeResponse(headers, "http://www.acme.com")\r
1213 c.extract_cookies(res, req)\r
1214\r
1215 req = Request("http://www.acme.com/")\r
1216 c.add_cookie_header(req)\r
1217\r
1218 h = req.get_header("Cookie")\r
1219 self.assertIn("PART_NUMBER=ROCKET_LAUNCHER_0001", h)\r
1220 self.assertIn("CUSTOMER=WILE_E_COYOTE", h)\r
1221 self.assertNotIn("SHIPPING=FEDEX", h)\r
1222\r
1223 req = Request("http://www.acme.com/foo/")\r
1224 c.add_cookie_header(req)\r
1225\r
1226 h = req.get_header("Cookie")\r
1227 self.assertIn("PART_NUMBER=ROCKET_LAUNCHER_0001", h)\r
1228 self.assertIn("CUSTOMER=WILE_E_COYOTE", h)\r
1229 self.assertTrue(h.startswith("SHIPPING=FEDEX;"))\r
1230\r
1231 def test_netscape_example_2(self):\r
1232 from cookielib import CookieJar\r
1233 from urllib2 import Request\r
1234\r
1235 # Second Example transaction sequence:\r
1236 #\r
1237 # Assume all mappings from above have been cleared.\r
1238 #\r
1239 # Client receives:\r
1240 #\r
1241 # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/\r
1242 #\r
1243 # When client requests a URL in path "/" on this server, it sends:\r
1244 #\r
1245 # Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001\r
1246 #\r
1247 # Client receives:\r
1248 #\r
1249 # Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo\r
1250 #\r
1251 # When client requests a URL in path "/ammo" on this server, it sends:\r
1252 #\r
1253 # Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001\r
1254 #\r
1255 # NOTE: There are two name/value pairs named "PART_NUMBER" due to\r
1256 # the inheritance of the "/" mapping in addition to the "/ammo" mapping.\r
1257\r
1258 c = CookieJar()\r
1259 headers = []\r
1260\r
1261 req = Request("http://www.acme.com/")\r
1262 headers.append("Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/")\r
1263 res = FakeResponse(headers, "http://www.acme.com/")\r
1264\r
1265 c.extract_cookies(res, req)\r
1266\r
1267 req = Request("http://www.acme.com/")\r
1268 c.add_cookie_header(req)\r
1269\r
1270 self.assertEqual(req.get_header("Cookie"),\r
1271 "PART_NUMBER=ROCKET_LAUNCHER_0001")\r
1272\r
1273 headers.append(\r
1274 "Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo")\r
1275 res = FakeResponse(headers, "http://www.acme.com/")\r
1276 c.extract_cookies(res, req)\r
1277\r
1278 req = Request("http://www.acme.com/ammo")\r
1279 c.add_cookie_header(req)\r
1280\r
1281 self.assertTrue(re.search(r"PART_NUMBER=RIDING_ROCKET_0023;\s*"\r
1282 "PART_NUMBER=ROCKET_LAUNCHER_0001",\r
1283 req.get_header("Cookie")))\r
1284\r
1285 def test_ietf_example_1(self):\r
1286 from cookielib import CookieJar, DefaultCookiePolicy\r
1287 #-------------------------------------------------------------------\r
1288 # Then we test with the examples from draft-ietf-http-state-man-mec-03.txt\r
1289 #\r
1290 # 5. EXAMPLES\r
1291\r
1292 c = CookieJar(DefaultCookiePolicy(rfc2965=True))\r
1293\r
1294 #\r
1295 # 5.1 Example 1\r
1296 #\r
1297 # Most detail of request and response headers has been omitted. Assume\r
1298 # the user agent has no stored cookies.\r
1299 #\r
1300 # 1. User Agent -> Server\r
1301 #\r
1302 # POST /acme/login HTTP/1.1\r
1303 # [form data]\r
1304 #\r
1305 # User identifies self via a form.\r
1306 #\r
1307 # 2. Server -> User Agent\r
1308 #\r
1309 # HTTP/1.1 200 OK\r
1310 # Set-Cookie2: Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"\r
1311 #\r
1312 # Cookie reflects user's identity.\r
1313\r
1314 cookie = interact_2965(\r
1315 c, 'http://www.acme.com/acme/login',\r
1316 'Customer="WILE_E_COYOTE"; Version="1"; Path="/acme"')\r
1317 self.assertTrue(not cookie)\r
1318\r
1319 #\r
1320 # 3. User Agent -> Server\r
1321 #\r
1322 # POST /acme/pickitem HTTP/1.1\r
1323 # Cookie: $Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"\r
1324 # [form data]\r
1325 #\r
1326 # User selects an item for ``shopping basket.''\r
1327 #\r
1328 # 4. Server -> User Agent\r
1329 #\r
1330 # HTTP/1.1 200 OK\r
1331 # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";\r
1332 # Path="/acme"\r
1333 #\r
1334 # Shopping basket contains an item.\r
1335\r
1336 cookie = interact_2965(c, 'http://www.acme.com/acme/pickitem',\r
1337 'Part_Number="Rocket_Launcher_0001"; '\r
1338 'Version="1"; Path="/acme"');\r
1339 self.assertTrue(re.search(\r
1340 r'^\$Version="?1"?; Customer="?WILE_E_COYOTE"?; \$Path="/acme"$',\r
1341 cookie))\r
1342\r
1343 #\r
1344 # 5. User Agent -> Server\r
1345 #\r
1346 # POST /acme/shipping HTTP/1.1\r
1347 # Cookie: $Version="1";\r
1348 # Customer="WILE_E_COYOTE"; $Path="/acme";\r
1349 # Part_Number="Rocket_Launcher_0001"; $Path="/acme"\r
1350 # [form data]\r
1351 #\r
1352 # User selects shipping method from form.\r
1353 #\r
1354 # 6. Server -> User Agent\r
1355 #\r
1356 # HTTP/1.1 200 OK\r
1357 # Set-Cookie2: Shipping="FedEx"; Version="1"; Path="/acme"\r
1358 #\r
1359 # New cookie reflects shipping method.\r
1360\r
1361 cookie = interact_2965(c, "http://www.acme.com/acme/shipping",\r
1362 'Shipping="FedEx"; Version="1"; Path="/acme"')\r
1363\r
1364 self.assertTrue(re.search(r'^\$Version="?1"?;', cookie))\r
1365 self.assertTrue(re.search(r'Part_Number="?Rocket_Launcher_0001"?;'\r
1366 '\s*\$Path="\/acme"', cookie))\r
1367 self.assertTrue(re.search(r'Customer="?WILE_E_COYOTE"?;\s*\$Path="\/acme"',\r
1368 cookie))\r
1369\r
1370 #\r
1371 # 7. User Agent -> Server\r
1372 #\r
1373 # POST /acme/process HTTP/1.1\r
1374 # Cookie: $Version="1";\r
1375 # Customer="WILE_E_COYOTE"; $Path="/acme";\r
1376 # Part_Number="Rocket_Launcher_0001"; $Path="/acme";\r
1377 # Shipping="FedEx"; $Path="/acme"\r
1378 # [form data]\r
1379 #\r
1380 # User chooses to process order.\r
1381 #\r
1382 # 8. Server -> User Agent\r
1383 #\r
1384 # HTTP/1.1 200 OK\r
1385 #\r
1386 # Transaction is complete.\r
1387\r
1388 cookie = interact_2965(c, "http://www.acme.com/acme/process")\r
1389 self.assertTrue(\r
1390 re.search(r'Shipping="?FedEx"?;\s*\$Path="\/acme"', cookie) and\r
1391 "WILE_E_COYOTE" in cookie)\r
1392\r
1393 #\r
1394 # The user agent makes a series of requests on the origin server, after\r
1395 # each of which it receives a new cookie. All the cookies have the same\r
1396 # Path attribute and (default) domain. Because the request URLs all have\r
1397 # /acme as a prefix, and that matches the Path attribute, each request\r
1398 # contains all the cookies received so far.\r
1399\r
1400 def test_ietf_example_2(self):\r
1401 from cookielib import CookieJar, DefaultCookiePolicy\r
1402\r
1403 # 5.2 Example 2\r
1404 #\r
1405 # This example illustrates the effect of the Path attribute. All detail\r
1406 # of request and response headers has been omitted. Assume the user agent\r
1407 # has no stored cookies.\r
1408\r
1409 c = CookieJar(DefaultCookiePolicy(rfc2965=True))\r
1410\r
1411 # Imagine the user agent has received, in response to earlier requests,\r
1412 # the response headers\r
1413 #\r
1414 # Set-Cookie2: Part_Number="Rocket_Launcher_0001"; Version="1";\r
1415 # Path="/acme"\r
1416 #\r
1417 # and\r
1418 #\r
1419 # Set-Cookie2: Part_Number="Riding_Rocket_0023"; Version="1";\r
1420 # Path="/acme/ammo"\r
1421\r
1422 interact_2965(\r
1423 c, "http://www.acme.com/acme/ammo/specific",\r
1424 'Part_Number="Rocket_Launcher_0001"; Version="1"; Path="/acme"',\r
1425 'Part_Number="Riding_Rocket_0023"; Version="1"; Path="/acme/ammo"')\r
1426\r
1427 # A subsequent request by the user agent to the (same) server for URLs of\r
1428 # the form /acme/ammo/... would include the following request header:\r
1429 #\r
1430 # Cookie: $Version="1";\r
1431 # Part_Number="Riding_Rocket_0023"; $Path="/acme/ammo";\r
1432 # Part_Number="Rocket_Launcher_0001"; $Path="/acme"\r
1433 #\r
1434 # Note that the NAME=VALUE pair for the cookie with the more specific Path\r
1435 # attribute, /acme/ammo, comes before the one with the less specific Path\r
1436 # attribute, /acme. Further note that the same cookie name appears more\r
1437 # than once.\r
1438\r
1439 cookie = interact_2965(c, "http://www.acme.com/acme/ammo/...")\r
1440 self.assertTrue(\r
1441 re.search(r"Riding_Rocket_0023.*Rocket_Launcher_0001", cookie))\r
1442\r
1443 # A subsequent request by the user agent to the (same) server for a URL of\r
1444 # the form /acme/parts/ would include the following request header:\r
1445 #\r
1446 # Cookie: $Version="1"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"\r
1447 #\r
1448 # Here, the second cookie's Path attribute /acme/ammo is not a prefix of\r
1449 # the request URL, /acme/parts/, so the cookie does not get forwarded to\r
1450 # the server.\r
1451\r
1452 cookie = interact_2965(c, "http://www.acme.com/acme/parts/")\r
1453 self.assertIn("Rocket_Launcher_0001", cookie)\r
1454 self.assertNotIn("Riding_Rocket_0023", cookie)\r
1455\r
1456 def test_rejection(self):\r
1457 # Test rejection of Set-Cookie2 responses based on domain, path, port.\r
1458 from cookielib import DefaultCookiePolicy, LWPCookieJar\r
1459\r
1460 pol = DefaultCookiePolicy(rfc2965=True)\r
1461\r
1462 c = LWPCookieJar(policy=pol)\r
1463\r
1464 max_age = "max-age=3600"\r
1465\r
1466 # illegal domain (no embedded dots)\r
1467 cookie = interact_2965(c, "http://www.acme.com",\r
1468 'foo=bar; domain=".com"; version=1')\r
1469 self.assertTrue(not c)\r
1470\r
1471 # legal domain\r
1472 cookie = interact_2965(c, "http://www.acme.com",\r
1473 'ping=pong; domain="acme.com"; version=1')\r
1474 self.assertEqual(len(c), 1)\r
1475\r
1476 # illegal domain (host prefix "www.a" contains a dot)\r
1477 cookie = interact_2965(c, "http://www.a.acme.com",\r
1478 'whiz=bang; domain="acme.com"; version=1')\r
1479 self.assertEqual(len(c), 1)\r
1480\r
1481 # legal domain\r
1482 cookie = interact_2965(c, "http://www.a.acme.com",\r
1483 'wow=flutter; domain=".a.acme.com"; version=1')\r
1484 self.assertEqual(len(c), 2)\r
1485\r
1486 # can't partially match an IP-address\r
1487 cookie = interact_2965(c, "http://125.125.125.125",\r
1488 'zzzz=ping; domain="125.125.125"; version=1')\r
1489 self.assertEqual(len(c), 2)\r
1490\r
1491 # illegal path (must be prefix of request path)\r
1492 cookie = interact_2965(c, "http://www.sol.no",\r
1493 'blah=rhubarb; domain=".sol.no"; path="/foo"; '\r
1494 'version=1')\r
1495 self.assertEqual(len(c), 2)\r
1496\r
1497 # legal path\r
1498 cookie = interact_2965(c, "http://www.sol.no/foo/bar",\r
1499 'bing=bong; domain=".sol.no"; path="/foo"; '\r
1500 'version=1')\r
1501 self.assertEqual(len(c), 3)\r
1502\r
1503 # illegal port (request-port not in list)\r
1504 cookie = interact_2965(c, "http://www.sol.no",\r
1505 'whiz=ffft; domain=".sol.no"; port="90,100"; '\r
1506 'version=1')\r
1507 self.assertEqual(len(c), 3)\r
1508\r
1509 # legal port\r
1510 cookie = interact_2965(\r
1511 c, "http://www.sol.no",\r
1512 r'bang=wallop; version=1; domain=".sol.no"; '\r
1513 r'port="90,100, 80,8080"; '\r
1514 r'max-age=100; Comment = "Just kidding! (\"|\\\\) "')\r
1515 self.assertEqual(len(c), 4)\r
1516\r
1517 # port attribute without any value (current port)\r
1518 cookie = interact_2965(c, "http://www.sol.no",\r
1519 'foo9=bar; version=1; domain=".sol.no"; port; '\r
1520 'max-age=100;')\r
1521 self.assertEqual(len(c), 5)\r
1522\r
1523 # encoded path\r
1524 # LWP has this test, but unescaping allowed path characters seems\r
1525 # like a bad idea, so I think this should fail:\r
1526## cookie = interact_2965(c, "http://www.sol.no/foo/",\r
1527## r'foo8=bar; version=1; path="/%66oo"')\r
1528 # but this is OK, because '<' is not an allowed HTTP URL path\r
1529 # character:\r
1530 cookie = interact_2965(c, "http://www.sol.no/<oo/",\r
1531 r'foo8=bar; version=1; path="/%3coo"')\r
1532 self.assertEqual(len(c), 6)\r
1533\r
1534 # save and restore\r
1535 filename = test_support.TESTFN\r
1536\r
1537 try:\r
1538 c.save(filename, ignore_discard=True)\r
1539 old = repr(c)\r
1540\r
1541 c = LWPCookieJar(policy=pol)\r
1542 c.load(filename, ignore_discard=True)\r
1543 finally:\r
1544 try: os.unlink(filename)\r
1545 except OSError: pass\r
1546\r
1547 self.assertEqual(old, repr(c))\r
1548\r
1549 def test_url_encoding(self):\r
1550 # Try some URL encodings of the PATHs.\r
1551 # (the behaviour here has changed from libwww-perl)\r
1552 from cookielib import CookieJar, DefaultCookiePolicy\r
1553\r
1554 c = CookieJar(DefaultCookiePolicy(rfc2965=True))\r
1555 interact_2965(c, "http://www.acme.com/foo%2f%25/%3c%3c%0Anew%E5/%E5",\r
1556 "foo = bar; version = 1")\r
1557\r
1558 cookie = interact_2965(\r
1559