PageRenderTime 65ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/lib-python/2/test/test_cookielib.py

https://bitbucket.org/kcr/pypy
Python | 1762 lines | 1720 code | 26 blank | 16 comment | 16 complexity | 5464bada82114d9cfd130f172de6fc53 MD5 | raw file
Possible License(s): Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. # -*- coding: latin-1 -*-
  2. """Tests for cookielib.py."""
  3. import cookielib
  4. import os
  5. import re
  6. import time
  7. from unittest import TestCase
  8. from test import test_support
  9. class DateTimeTests(TestCase):
  10. def test_time2isoz(self):
  11. from cookielib import time2isoz
  12. base = 1019227000
  13. day = 24*3600
  14. self.assertEqual(time2isoz(base), "2002-04-19 14:36:40Z")
  15. self.assertEqual(time2isoz(base+day), "2002-04-20 14:36:40Z")
  16. self.assertEqual(time2isoz(base+2*day), "2002-04-21 14:36:40Z")
  17. self.assertEqual(time2isoz(base+3*day), "2002-04-22 14:36:40Z")
  18. az = time2isoz()
  19. bz = time2isoz(500000)
  20. for text in (az, bz):
  21. self.assertTrue(re.search(r"^\d{4}-\d\d-\d\d \d\d:\d\d:\d\dZ$", text),
  22. "bad time2isoz format: %s %s" % (az, bz))
  23. def test_http2time(self):
  24. from cookielib import http2time
  25. def parse_date(text):
  26. return time.gmtime(http2time(text))[:6]
  27. self.assertEqual(parse_date("01 Jan 2001"), (2001, 1, 1, 0, 0, 0.0))
  28. # this test will break around year 2070
  29. self.assertEqual(parse_date("03-Feb-20"), (2020, 2, 3, 0, 0, 0.0))
  30. # this test will break around year 2048
  31. self.assertEqual(parse_date("03-Feb-98"), (1998, 2, 3, 0, 0, 0.0))
  32. def test_http2time_formats(self):
  33. from cookielib import http2time, time2isoz
  34. # test http2time for supported dates. Test cases with 2 digit year
  35. # will probably break in year 2044.
  36. tests = [
  37. 'Thu, 03 Feb 1994 00:00:00 GMT', # proposed new HTTP format
  38. 'Thursday, 03-Feb-94 00:00:00 GMT', # old rfc850 HTTP format
  39. 'Thursday, 03-Feb-1994 00:00:00 GMT', # broken rfc850 HTTP format
  40. '03 Feb 1994 00:00:00 GMT', # HTTP format (no weekday)
  41. '03-Feb-94 00:00:00 GMT', # old rfc850 (no weekday)
  42. '03-Feb-1994 00:00:00 GMT', # broken rfc850 (no weekday)
  43. '03-Feb-1994 00:00 GMT', # broken rfc850 (no weekday, no seconds)
  44. '03-Feb-1994 00:00', # broken rfc850 (no weekday, no seconds, no tz)
  45. '03-Feb-94', # old rfc850 HTTP format (no weekday, no time)
  46. '03-Feb-1994', # broken rfc850 HTTP format (no weekday, no time)
  47. '03 Feb 1994', # proposed new HTTP format (no weekday, no time)
  48. # A few tests with extra space at various places
  49. ' 03 Feb 1994 0:00 ',
  50. ' 03-Feb-1994 ',
  51. ]
  52. test_t = 760233600 # assume broken POSIX counting of seconds
  53. result = time2isoz(test_t)
  54. expected = "1994-02-03 00:00:00Z"
  55. self.assertEqual(result, expected,
  56. "%s => '%s' (%s)" % (test_t, result, expected))
  57. for s in tests:
  58. t = http2time(s)
  59. t2 = http2time(s.lower())
  60. t3 = http2time(s.upper())
  61. self.assertTrue(t == t2 == t3 == test_t,
  62. "'%s' => %s, %s, %s (%s)" % (s, t, t2, t3, test_t))
  63. def test_http2time_garbage(self):
  64. from cookielib import http2time
  65. for test in [
  66. '',
  67. 'Garbage',
  68. 'Mandag 16. September 1996',
  69. '01-00-1980',
  70. '01-13-1980',
  71. '00-01-1980',
  72. '32-01-1980',
  73. '01-01-1980 25:00:00',
  74. '01-01-1980 00:61:00',
  75. '01-01-1980 00:00:62',
  76. ]:
  77. self.assertTrue(http2time(test) is None,
  78. "http2time(%s) is not None\n"
  79. "http2time(test) %s" % (test, http2time(test))
  80. )
  81. class HeaderTests(TestCase):
  82. def test_parse_ns_headers_expires(self):
  83. from cookielib import parse_ns_headers
  84. # quotes should be stripped
  85. expected = [[('foo', 'bar'), ('expires', 2209069412L), ('version', '0')]]
  86. for hdr in [
  87. 'foo=bar; expires=01 Jan 2040 22:23:32 GMT',
  88. 'foo=bar; expires="01 Jan 2040 22:23:32 GMT"',
  89. ]:
  90. self.assertEqual(parse_ns_headers([hdr]), expected)
  91. def test_parse_ns_headers_version(self):
  92. from cookielib import parse_ns_headers
  93. # quotes should be stripped
  94. expected = [[('foo', 'bar'), ('version', '1')]]
  95. for hdr in [
  96. 'foo=bar; version="1"',
  97. 'foo=bar; Version="1"',
  98. ]:
  99. self.assertEqual(parse_ns_headers([hdr]), expected)
  100. def test_parse_ns_headers_special_names(self):
  101. # names such as 'expires' are not special in first name=value pair
  102. # of Set-Cookie: header
  103. from cookielib import parse_ns_headers
  104. # Cookie with name 'expires'
  105. hdr = 'expires=01 Jan 2040 22:23:32 GMT'
  106. expected = [[("expires", "01 Jan 2040 22:23:32 GMT"), ("version", "0")]]
  107. self.assertEqual(parse_ns_headers([hdr]), expected)
  108. def test_join_header_words(self):
  109. from cookielib import join_header_words
  110. joined = join_header_words([[("foo", None), ("bar", "baz")]])
  111. self.assertEqual(joined, "foo; bar=baz")
  112. self.assertEqual(join_header_words([[]]), "")
  113. def test_split_header_words(self):
  114. from cookielib import split_header_words
  115. tests = [
  116. ("foo", [[("foo", None)]]),
  117. ("foo=bar", [[("foo", "bar")]]),
  118. (" foo ", [[("foo", None)]]),
  119. (" foo= ", [[("foo", "")]]),
  120. (" foo=", [[("foo", "")]]),
  121. (" foo= ; ", [[("foo", "")]]),
  122. (" foo= ; bar= baz ", [[("foo", ""), ("bar", "baz")]]),
  123. ("foo=bar bar=baz", [[("foo", "bar"), ("bar", "baz")]]),
  124. # doesn't really matter if this next fails, but it works ATM
  125. ("foo= bar=baz", [[("foo", "bar=baz")]]),
  126. ("foo=bar;bar=baz", [[("foo", "bar"), ("bar", "baz")]]),
  127. ('foo bar baz', [[("foo", None), ("bar", None), ("baz", None)]]),
  128. ("a, b, c", [[("a", None)], [("b", None)], [("c", None)]]),
  129. (r'foo; bar=baz, spam=, foo="\,\;\"", bar= ',
  130. [[("foo", None), ("bar", "baz")],
  131. [("spam", "")], [("foo", ',;"')], [("bar", "")]]),
  132. ]
  133. for arg, expect in tests:
  134. try:
  135. result = split_header_words([arg])
  136. except:
  137. import traceback, StringIO
  138. f = StringIO.StringIO()
  139. traceback.print_exc(None, f)
  140. result = "(error -- traceback follows)\n\n%s" % f.getvalue()
  141. self.assertEqual(result, expect, """
  142. When parsing: '%s'
  143. Expected: '%s'
  144. Got: '%s'
  145. """ % (arg, expect, result))
  146. def test_roundtrip(self):
  147. from cookielib import split_header_words, join_header_words
  148. tests = [
  149. ("foo", "foo"),
  150. ("foo=bar", "foo=bar"),
  151. (" foo ", "foo"),
  152. ("foo=", 'foo=""'),
  153. ("foo=bar bar=baz", "foo=bar; bar=baz"),
  154. ("foo=bar;bar=baz", "foo=bar; bar=baz"),
  155. ('foo bar baz', "foo; bar; baz"),
  156. (r'foo="\"" bar="\\"', r'foo="\""; bar="\\"'),
  157. ('foo,,,bar', 'foo, bar'),
  158. ('foo=bar,bar=baz', 'foo=bar, bar=baz'),
  159. ('text/html; charset=iso-8859-1',
  160. 'text/html; charset="iso-8859-1"'),
  161. ('foo="bar"; port="80,81"; discard, bar=baz',
  162. 'foo=bar; port="80,81"; discard, bar=baz'),
  163. (r'Basic realm="\"foo\\\\bar\""',
  164. r'Basic; realm="\"foo\\\\bar\""')
  165. ]
  166. for arg, expect in tests:
  167. input = split_header_words([arg])
  168. res = join_header_words(input)
  169. self.assertEqual(res, expect, """
  170. When parsing: '%s'
  171. Expected: '%s'
  172. Got: '%s'
  173. Input was: '%s'
  174. """ % (arg, expect, res, input))
  175. class FakeResponse:
  176. def __init__(self, headers=[], url=None):
  177. """
  178. headers: list of RFC822-style 'Key: value' strings
  179. """
  180. import mimetools, StringIO
  181. f = StringIO.StringIO("\n".join(headers))
  182. self._headers = mimetools.Message(f)
  183. self._url = url
  184. def info(self): return self._headers
  185. def interact_2965(cookiejar, url, *set_cookie_hdrs):
  186. return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie2")
  187. def interact_netscape(cookiejar, url, *set_cookie_hdrs):
  188. return _interact(cookiejar, url, set_cookie_hdrs, "Set-Cookie")
  189. def _interact(cookiejar, url, set_cookie_hdrs, hdr_name):
  190. """Perform a single request / response cycle, returning Cookie: header."""
  191. from urllib2 import Request
  192. req = Request(url)
  193. cookiejar.add_cookie_header(req)
  194. cookie_hdr = req.get_header("Cookie", "")
  195. headers = []
  196. for hdr in set_cookie_hdrs:
  197. headers.append("%s: %s" % (hdr_name, hdr))
  198. res = FakeResponse(headers, url)
  199. cookiejar.extract_cookies(res, req)
  200. return cookie_hdr
  201. class FileCookieJarTests(TestCase):
  202. def test_lwp_valueless_cookie(self):
  203. # cookies with no value should be saved and loaded consistently
  204. from cookielib import LWPCookieJar
  205. filename = test_support.TESTFN
  206. c = LWPCookieJar()
  207. interact_netscape(c, "http://www.acme.com/", 'boo')
  208. self.assertEqual(c._cookies["www.acme.com"]["/"]["boo"].value, None)
  209. try:
  210. c.save(filename, ignore_discard=True)
  211. c = LWPCookieJar()
  212. c.load(filename, ignore_discard=True)
  213. finally:
  214. try: os.unlink(filename)
  215. except OSError: pass
  216. self.assertEqual(c._cookies["www.acme.com"]["/"]["boo"].value, None)
  217. def test_bad_magic(self):
  218. from cookielib import LWPCookieJar, MozillaCookieJar, LoadError
  219. # IOErrors (eg. file doesn't exist) are allowed to propagate
  220. filename = test_support.TESTFN
  221. for cookiejar_class in LWPCookieJar, MozillaCookieJar:
  222. c = cookiejar_class()
  223. try:
  224. c.load(filename="for this test to work, a file with this "
  225. "filename should not exist")
  226. except IOError, exc:
  227. # exactly IOError, not LoadError
  228. self.assertEqual(exc.__class__, IOError)
  229. else:
  230. self.fail("expected IOError for invalid filename")
  231. # Invalid contents of cookies file (eg. bad magic string)
  232. # causes a LoadError.
  233. try:
  234. f = open(filename, "w")
  235. f.write("oops\n")
  236. for cookiejar_class in LWPCookieJar, MozillaCookieJar:
  237. c = cookiejar_class()
  238. self.assertRaises(LoadError, c.load, filename)
  239. finally:
  240. try: os.unlink(filename)
  241. except OSError: pass
  242. class CookieTests(TestCase):
  243. # XXX
  244. # Get rid of string comparisons where not actually testing str / repr.
  245. # .clear() etc.
  246. # IP addresses like 50 (single number, no dot) and domain-matching
  247. # functions (and is_HDN)? See draft RFC 2965 errata.
  248. # Strictness switches
  249. # is_third_party()
  250. # unverifiability / third-party blocking
  251. # Netscape cookies work the same as RFC 2965 with regard to port.
  252. # Set-Cookie with negative max age.
  253. # If turn RFC 2965 handling off, Set-Cookie2 cookies should not clobber
  254. # Set-Cookie cookies.
  255. # Cookie2 should be sent if *any* cookies are not V1 (ie. V0 OR V2 etc.).
  256. # Cookies (V1 and V0) with no expiry date should be set to be discarded.
  257. # RFC 2965 Quoting:
  258. # Should accept unquoted cookie-attribute values? check errata draft.
  259. # Which are required on the way in and out?
  260. # Should always return quoted cookie-attribute values?
  261. # Proper testing of when RFC 2965 clobbers Netscape (waiting for errata).
  262. # Path-match on return (same for V0 and V1).
  263. # RFC 2965 acceptance and returning rules
  264. # Set-Cookie2 without version attribute is rejected.
  265. # Netscape peculiarities list from Ronald Tschalar.
  266. # The first two still need tests, the rest are covered.
  267. ## - Quoting: only quotes around the expires value are recognized as such
  268. ## (and yes, some folks quote the expires value); quotes around any other
  269. ## value are treated as part of the value.
  270. ## - White space: white space around names and values is ignored
  271. ## - Default path: if no path parameter is given, the path defaults to the
  272. ## path in the request-uri up to, but not including, the last '/'. Note
  273. ## that this is entirely different from what the spec says.
  274. ## - Commas and other delimiters: Netscape just parses until the next ';'.
  275. ## This means it will allow commas etc inside values (and yes, both
  276. ## commas and equals are commonly appear in the cookie value). This also
  277. ## means that if you fold multiple Set-Cookie header fields into one,
  278. ## comma-separated list, it'll be a headache to parse (at least my head
  279. ## starts hurting everytime I think of that code).
  280. ## - Expires: You'll get all sorts of date formats in the expires,
  281. ## including emtpy expires attributes ("expires="). Be as flexible as you
  282. ## can, and certainly don't expect the weekday to be there; if you can't
  283. ## parse it, just ignore it and pretend it's a session cookie.
  284. ## - Domain-matching: Netscape uses the 2-dot rule for _all_ domains, not
  285. ## just the 7 special TLD's listed in their spec. And folks rely on
  286. ## that...
  287. def test_domain_return_ok(self):
  288. # test optimization: .domain_return_ok() should filter out most
  289. # domains in the CookieJar before we try to access them (because that
  290. # may require disk access -- in particular, with MSIECookieJar)
  291. # This is only a rough check for performance reasons, so it's not too
  292. # critical as long as it's sufficiently liberal.
  293. import cookielib, urllib2
  294. pol = cookielib.DefaultCookiePolicy()
  295. for url, domain, ok in [
  296. ("http://foo.bar.com/", "blah.com", False),
  297. ("http://foo.bar.com/", "rhubarb.blah.com", False),
  298. ("http://foo.bar.com/", "rhubarb.foo.bar.com", False),
  299. ("http://foo.bar.com/", ".foo.bar.com", True),
  300. ("http://foo.bar.com/", "foo.bar.com", True),
  301. ("http://foo.bar.com/", ".bar.com", True),
  302. ("http://foo.bar.com/", "com", True),
  303. ("http://foo.com/", "rhubarb.foo.com", False),
  304. ("http://foo.com/", ".foo.com", True),
  305. ("http://foo.com/", "foo.com", True),
  306. ("http://foo.com/", "com", True),
  307. ("http://foo/", "rhubarb.foo", False),
  308. ("http://foo/", ".foo", True),
  309. ("http://foo/", "foo", True),
  310. ("http://foo/", "foo.local", True),
  311. ("http://foo/", ".local", True),
  312. ]:
  313. request = urllib2.Request(url)
  314. r = pol.domain_return_ok(domain, request)
  315. if ok: self.assertTrue(r)
  316. else: self.assertTrue(not r)
  317. def test_missing_value(self):
  318. from cookielib import MozillaCookieJar, lwp_cookie_str
  319. # missing = sign in Cookie: header is regarded by Mozilla as a missing
  320. # name, and by cookielib as a missing value
  321. filename = test_support.TESTFN
  322. c = MozillaCookieJar(filename)
  323. interact_netscape(c, "http://www.acme.com/", 'eggs')
  324. interact_netscape(c, "http://www.acme.com/", '"spam"; path=/foo/')
  325. cookie = c._cookies["www.acme.com"]["/"]["eggs"]
  326. self.assertTrue(cookie.value is None)
  327. self.assertEqual(cookie.name, "eggs")
  328. cookie = c._cookies["www.acme.com"]['/foo/']['"spam"']
  329. self.assertTrue(cookie.value is None)
  330. self.assertEqual(cookie.name, '"spam"')
  331. self.assertEqual(lwp_cookie_str(cookie), (
  332. r'"spam"; path="/foo/"; domain="www.acme.com"; '
  333. 'path_spec; discard; version=0'))
  334. old_str = repr(c)
  335. c.save(ignore_expires=True, ignore_discard=True)
  336. try:
  337. c = MozillaCookieJar(filename)
  338. c.revert(ignore_expires=True, ignore_discard=True)
  339. finally:
  340. os.unlink(c.filename)
  341. # cookies unchanged apart from lost info re. whether path was specified
  342. self.assertEqual(
  343. repr(c),
  344. re.sub("path_specified=%s" % True, "path_specified=%s" % False,
  345. old_str)
  346. )
  347. self.assertEqual(interact_netscape(c, "http://www.acme.com/foo/"),
  348. '"spam"; eggs')
  349. def test_rfc2109_handling(self):
  350. # RFC 2109 cookies are handled as RFC 2965 or Netscape cookies,
  351. # dependent on policy settings
  352. from cookielib import CookieJar, DefaultCookiePolicy
  353. for rfc2109_as_netscape, rfc2965, version in [
  354. # default according to rfc2965 if not explicitly specified
  355. (None, False, 0),
  356. (None, True, 1),
  357. # explicit rfc2109_as_netscape
  358. (False, False, None), # version None here means no cookie stored
  359. (False, True, 1),
  360. (True, False, 0),
  361. (True, True, 0),
  362. ]:
  363. policy = DefaultCookiePolicy(
  364. rfc2109_as_netscape=rfc2109_as_netscape,
  365. rfc2965=rfc2965)
  366. c = CookieJar(policy)
  367. interact_netscape(c, "http://www.example.com/", "ni=ni; Version=1")
  368. try:
  369. cookie = c._cookies["www.example.com"]["/"]["ni"]
  370. except KeyError:
  371. self.assertTrue(version is None) # didn't expect a stored cookie
  372. else:
  373. self.assertEqual(cookie.version, version)
  374. # 2965 cookies are unaffected
  375. interact_2965(c, "http://www.example.com/",
  376. "foo=bar; Version=1")
  377. if rfc2965:
  378. cookie2965 = c._cookies["www.example.com"]["/"]["foo"]
  379. self.assertEqual(cookie2965.version, 1)
  380. def test_ns_parser(self):
  381. from cookielib import CookieJar, DEFAULT_HTTP_PORT
  382. c = CookieJar()
  383. interact_netscape(c, "http://www.acme.com/",
  384. 'spam=eggs; DoMain=.acme.com; port; blArgh="feep"')
  385. interact_netscape(c, "http://www.acme.com/", 'ni=ni; port=80,8080')
  386. interact_netscape(c, "http://www.acme.com:80/", 'nini=ni')
  387. interact_netscape(c, "http://www.acme.com:80/", 'foo=bar; expires=')
  388. interact_netscape(c, "http://www.acme.com:80/", 'spam=eggs; '
  389. 'expires="Foo Bar 25 33:22:11 3022"')
  390. cookie = c._cookies[".acme.com"]["/"]["spam"]
  391. self.assertEqual(cookie.domain, ".acme.com")
  392. self.assertTrue(cookie.domain_specified)
  393. self.assertEqual(cookie.port, DEFAULT_HTTP_PORT)
  394. self.assertTrue(not cookie.port_specified)
  395. # case is preserved
  396. self.assertTrue(cookie.has_nonstandard_attr("blArgh") and
  397. not cookie.has_nonstandard_attr("blargh"))
  398. cookie = c._cookies["www.acme.com"]["/"]["ni"]
  399. self.assertEqual(cookie.domain, "www.acme.com")
  400. self.assertTrue(not cookie.domain_specified)
  401. self.assertEqual(cookie.port, "80,8080")
  402. self.assertTrue(cookie.port_specified)
  403. cookie = c._cookies["www.acme.com"]["/"]["nini"]
  404. self.assertTrue(cookie.port is None)
  405. self.assertTrue(not cookie.port_specified)
  406. # invalid expires should not cause cookie to be dropped
  407. foo = c._cookies["www.acme.com"]["/"]["foo"]
  408. spam = c._cookies["www.acme.com"]["/"]["foo"]
  409. self.assertTrue(foo.expires is None)
  410. self.assertTrue(spam.expires is None)
  411. def test_ns_parser_special_names(self):
  412. # names such as 'expires' are not special in first name=value pair
  413. # of Set-Cookie: header
  414. from cookielib import CookieJar
  415. c = CookieJar()
  416. interact_netscape(c, "http://www.acme.com/", 'expires=eggs')
  417. interact_netscape(c, "http://www.acme.com/", 'version=eggs; spam=eggs')
  418. cookies = c._cookies["www.acme.com"]["/"]
  419. self.assertTrue('expires' in cookies)
  420. self.assertTrue('version' in cookies)
  421. def test_expires(self):
  422. from cookielib import time2netscape, CookieJar
  423. # if expires is in future, keep cookie...
  424. c = CookieJar()
  425. future = time2netscape(time.time()+3600)
  426. interact_netscape(c, "http://www.acme.com/", 'spam="bar"; expires=%s' %
  427. future)
  428. self.assertEqual(len(c), 1)
  429. now = time2netscape(time.time()-1)
  430. # ... and if in past or present, discard it
  431. interact_netscape(c, "http://www.acme.com/", 'foo="eggs"; expires=%s' %
  432. now)
  433. h = interact_netscape(c, "http://www.acme.com/")
  434. self.assertEqual(len(c), 1)
  435. self.assertTrue('spam="bar"' in h and "foo" not in h)
  436. # max-age takes precedence over expires, and zero max-age is request to
  437. # delete both new cookie and any old matching cookie
  438. interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; expires=%s' %
  439. future)
  440. interact_netscape(c, "http://www.acme.com/", 'bar="bar"; expires=%s' %
  441. future)
  442. self.assertEqual(len(c), 3)
  443. interact_netscape(c, "http://www.acme.com/", 'eggs="bar"; '
  444. 'expires=%s; max-age=0' % future)
  445. interact_netscape(c, "http://www.acme.com/", 'bar="bar"; '
  446. 'max-age=0; expires=%s' % future)
  447. h = interact_netscape(c, "http://www.acme.com/")
  448. self.assertEqual(len(c), 1)
  449. # test expiry at end of session for cookies with no expires attribute
  450. interact_netscape(c, "http://www.rhubarb.net/", 'whum="fizz"')
  451. self.assertEqual(len(c), 2)
  452. c.clear_session_cookies()
  453. self.assertEqual(len(c), 1)
  454. self.assertIn('spam="bar"', h)
  455. # XXX RFC 2965 expiry rules (some apply to V0 too)
  456. def test_default_path(self):
  457. from cookielib import CookieJar, DefaultCookiePolicy
  458. # RFC 2965
  459. pol = DefaultCookiePolicy(rfc2965=True)
  460. c = CookieJar(pol)
  461. interact_2965(c, "http://www.acme.com/", 'spam="bar"; Version="1"')
  462. self.assertIn("/", c._cookies["www.acme.com"])
  463. c = CookieJar(pol)
  464. interact_2965(c, "http://www.acme.com/blah", 'eggs="bar"; Version="1"')
  465. self.assertIn("/", c._cookies["www.acme.com"])
  466. c = CookieJar(pol)
  467. interact_2965(c, "http://www.acme.com/blah/rhubarb",
  468. 'eggs="bar"; Version="1"')
  469. self.assertIn("/blah/", c._cookies["www.acme.com"])
  470. c = CookieJar(pol)
  471. interact_2965(c, "http://www.acme.com/blah/rhubarb/",
  472. 'eggs="bar"; Version="1"')
  473. self.assertIn("/blah/rhubarb/", c._cookies["www.acme.com"])
  474. # Netscape
  475. c = CookieJar()
  476. interact_netscape(c, "http://www.acme.com/", 'spam="bar"')
  477. self.assertIn("/", c._cookies["www.acme.com"])
  478. c = CookieJar()
  479. interact_netscape(c, "http://www.acme.com/blah", 'eggs="bar"')
  480. self.assertIn("/", c._cookies["www.acme.com"])
  481. c = CookieJar()
  482. interact_netscape(c, "http://www.acme.com/blah/rhubarb", 'eggs="bar"')
  483. self.assertIn("/blah", c._cookies["www.acme.com"])
  484. c = CookieJar()
  485. interact_netscape(c, "http://www.acme.com/blah/rhubarb/", 'eggs="bar"')
  486. self.assertIn("/blah/rhubarb", c._cookies["www.acme.com"])
  487. def test_default_path_with_query(self):
  488. cj = cookielib.CookieJar()
  489. uri = "http://example.com/?spam/eggs"
  490. value = 'eggs="bar"'
  491. interact_netscape(cj, uri, value)
  492. # default path does not include query, so is "/", not "/?spam"
  493. self.assertIn("/", cj._cookies["example.com"])
  494. # cookie is sent back to the same URI
  495. self.assertEqual(interact_netscape(cj, uri), value)
  496. def test_escape_path(self):
  497. from cookielib import escape_path
  498. cases = [
  499. # quoted safe
  500. ("/foo%2f/bar", "/foo%2F/bar"),
  501. ("/foo%2F/bar", "/foo%2F/bar"),
  502. # quoted %
  503. ("/foo%%/bar", "/foo%%/bar"),
  504. # quoted unsafe
  505. ("/fo%19o/bar", "/fo%19o/bar"),
  506. ("/fo%7do/bar", "/fo%7Do/bar"),
  507. # unquoted safe
  508. ("/foo/bar&", "/foo/bar&"),
  509. ("/foo//bar", "/foo//bar"),
  510. ("\176/foo/bar", "\176/foo/bar"),
  511. # unquoted unsafe
  512. ("/foo\031/bar", "/foo%19/bar"),
  513. ("/\175foo/bar", "/%7Dfoo/bar"),
  514. # unicode
  515. (u"/foo/bar\uabcd", "/foo/bar%EA%AF%8D"), # UTF-8 encoded
  516. ]
  517. for arg, result in cases:
  518. self.assertEqual(escape_path(arg), result)
  519. def test_request_path(self):
  520. from urllib2 import Request
  521. from cookielib import request_path
  522. # with parameters
  523. req = Request("http://www.example.com/rheum/rhaponticum;"
  524. "foo=bar;sing=song?apples=pears&spam=eggs#ni")
  525. self.assertEqual(request_path(req),
  526. "/rheum/rhaponticum;foo=bar;sing=song")
  527. # without parameters
  528. req = Request("http://www.example.com/rheum/rhaponticum?"
  529. "apples=pears&spam=eggs#ni")
  530. self.assertEqual(request_path(req), "/rheum/rhaponticum")
  531. # missing final slash
  532. req = Request("http://www.example.com")
  533. self.assertEqual(request_path(req), "/")
  534. def test_request_port(self):
  535. from urllib2 import Request
  536. from cookielib import request_port, DEFAULT_HTTP_PORT
  537. req = Request("http://www.acme.com:1234/",
  538. headers={"Host": "www.acme.com:4321"})
  539. self.assertEqual(request_port(req), "1234")
  540. req = Request("http://www.acme.com/",
  541. headers={"Host": "www.acme.com:4321"})
  542. self.assertEqual(request_port(req), DEFAULT_HTTP_PORT)
  543. def test_request_host(self):
  544. from urllib2 import Request
  545. from cookielib import request_host
  546. # this request is illegal (RFC2616, 14.2.3)
  547. req = Request("http://1.1.1.1/",
  548. headers={"Host": "www.acme.com:80"})
  549. # libwww-perl wants this response, but that seems wrong (RFC 2616,
  550. # section 5.2, point 1., and RFC 2965 section 1, paragraph 3)
  551. #self.assertEqual(request_host(req), "www.acme.com")
  552. self.assertEqual(request_host(req), "1.1.1.1")
  553. req = Request("http://www.acme.com/",
  554. headers={"Host": "irrelevant.com"})
  555. self.assertEqual(request_host(req), "www.acme.com")
  556. # not actually sure this one is valid Request object, so maybe should
  557. # remove test for no host in url in request_host function?
  558. req = Request("/resource.html",
  559. headers={"Host": "www.acme.com"})
  560. self.assertEqual(request_host(req), "www.acme.com")
  561. # port shouldn't be in request-host
  562. req = Request("http://www.acme.com:2345/resource.html",
  563. headers={"Host": "www.acme.com:5432"})
  564. self.assertEqual(request_host(req), "www.acme.com")
  565. def test_is_HDN(self):
  566. from cookielib import is_HDN
  567. self.assertTrue(is_HDN("foo.bar.com"))
  568. self.assertTrue(is_HDN("1foo2.3bar4.5com"))
  569. self.assertTrue(not is_HDN("192.168.1.1"))
  570. self.assertTrue(not is_HDN(""))
  571. self.assertTrue(not is_HDN("."))
  572. self.assertTrue(not is_HDN(".foo.bar.com"))
  573. self.assertTrue(not is_HDN("..foo"))
  574. self.assertTrue(not is_HDN("foo."))
  575. def test_reach(self):
  576. from cookielib import reach
  577. self.assertEqual(reach("www.acme.com"), ".acme.com")
  578. self.assertEqual(reach("acme.com"), "acme.com")
  579. self.assertEqual(reach("acme.local"), ".local")
  580. self.assertEqual(reach(".local"), ".local")
  581. self.assertEqual(reach(".com"), ".com")
  582. self.assertEqual(reach("."), ".")
  583. self.assertEqual(reach(""), "")
  584. self.assertEqual(reach("192.168.0.1"), "192.168.0.1")
  585. def test_domain_match(self):
  586. from cookielib import domain_match, user_domain_match
  587. self.assertTrue(domain_match("192.168.1.1", "192.168.1.1"))
  588. self.assertTrue(not domain_match("192.168.1.1", ".168.1.1"))
  589. self.assertTrue(domain_match("x.y.com", "x.Y.com"))
  590. self.assertTrue(domain_match("x.y.com", ".Y.com"))
  591. self.assertTrue(not domain_match("x.y.com", "Y.com"))
  592. self.assertTrue(domain_match("a.b.c.com", ".c.com"))
  593. self.assertTrue(not domain_match(".c.com", "a.b.c.com"))
  594. self.assertTrue(domain_match("example.local", ".local"))
  595. self.assertTrue(not domain_match("blah.blah", ""))
  596. self.assertTrue(not domain_match("", ".rhubarb.rhubarb"))
  597. self.assertTrue(domain_match("", ""))
  598. self.assertTrue(user_domain_match("acme.com", "acme.com"))
  599. self.assertTrue(not user_domain_match("acme.com", ".acme.com"))
  600. self.assertTrue(user_domain_match("rhubarb.acme.com", ".acme.com"))
  601. self.assertTrue(user_domain_match("www.rhubarb.acme.com", ".acme.com"))
  602. self.assertTrue(user_domain_match("x.y.com", "x.Y.com"))
  603. self.assertTrue(user_domain_match("x.y.com", ".Y.com"))
  604. self.assertTrue(not user_domain_match("x.y.com", "Y.com"))
  605. self.assertTrue(user_domain_match("y.com", "Y.com"))
  606. self.assertTrue(not user_domain_match(".y.com", "Y.com"))
  607. self.assertTrue(user_domain_match(".y.com", ".Y.com"))
  608. self.assertTrue(user_domain_match("x.y.com", ".com"))
  609. self.assertTrue(not user_domain_match("x.y.com", "com"))
  610. self.assertTrue(not user_domain_match("x.y.com", "m"))
  611. self.assertTrue(not user_domain_match("x.y.com", ".m"))
  612. self.assertTrue(not user_domain_match("x.y.com", ""))
  613. self.assertTrue(not user_domain_match("x.y.com", "."))
  614. self.assertTrue(user_domain_match("192.168.1.1", "192.168.1.1"))
  615. # not both HDNs, so must string-compare equal to match
  616. self.assertTrue(not user_domain_match("192.168.1.1", ".168.1.1"))
  617. self.assertTrue(not user_domain_match("192.168.1.1", "."))
  618. # empty string is a special case
  619. self.assertTrue(not user_domain_match("192.168.1.1", ""))
  620. def test_wrong_domain(self):
  621. # Cookies whose effective request-host name does not domain-match the
  622. # domain are rejected.
  623. # XXX far from complete
  624. from cookielib import CookieJar
  625. c = CookieJar()
  626. interact_2965(c, "http://www.nasty.com/",
  627. 'foo=bar; domain=friendly.org; Version="1"')
  628. self.assertEqual(len(c), 0)
  629. def test_strict_domain(self):
  630. # Cookies whose domain is a country-code tld like .co.uk should
  631. # not be set if CookiePolicy.strict_domain is true.
  632. from cookielib import CookieJar, DefaultCookiePolicy
  633. cp = DefaultCookiePolicy(strict_domain=True)
  634. cj = CookieJar(policy=cp)
  635. interact_netscape(cj, "http://example.co.uk/", 'no=problemo')
  636. interact_netscape(cj, "http://example.co.uk/",
  637. 'okey=dokey; Domain=.example.co.uk')
  638. self.assertEqual(len(cj), 2)
  639. for pseudo_tld in [".co.uk", ".org.za", ".tx.us", ".name.us"]:
  640. interact_netscape(cj, "http://example.%s/" % pseudo_tld,
  641. 'spam=eggs; Domain=.co.uk')
  642. self.assertEqual(len(cj), 2)
  643. def test_two_component_domain_ns(self):
  644. # Netscape: .www.bar.com, www.bar.com, .bar.com, bar.com, no domain
  645. # should all get accepted, as should .acme.com, acme.com and no domain
  646. # for 2-component domains like acme.com.
  647. from cookielib import CookieJar, DefaultCookiePolicy
  648. c = CookieJar()
  649. # two-component V0 domain is OK
  650. interact_netscape(c, "http://foo.net/", 'ns=bar')
  651. self.assertEqual(len(c), 1)
  652. self.assertEqual(c._cookies["foo.net"]["/"]["ns"].value, "bar")
  653. self.assertEqual(interact_netscape(c, "http://foo.net/"), "ns=bar")
  654. # *will* be returned to any other domain (unlike RFC 2965)...
  655. self.assertEqual(interact_netscape(c, "http://www.foo.net/"),
  656. "ns=bar")
  657. # ...unless requested otherwise
  658. pol = DefaultCookiePolicy(
  659. strict_ns_domain=DefaultCookiePolicy.DomainStrictNonDomain)
  660. c.set_policy(pol)
  661. self.assertEqual(interact_netscape(c, "http://www.foo.net/"), "")
  662. # unlike RFC 2965, even explicit two-component domain is OK,
  663. # because .foo.net matches foo.net
  664. interact_netscape(c, "http://foo.net/foo/",
  665. 'spam1=eggs; domain=foo.net')
  666. # even if starts with a dot -- in NS rules, .foo.net matches foo.net!
  667. interact_netscape(c, "http://foo.net/foo/bar/",
  668. 'spam2=eggs; domain=.foo.net')
  669. self.assertEqual(len(c), 3)
  670. self.assertEqual(c._cookies[".foo.net"]["/foo"]["spam1"].value,
  671. "eggs")
  672. self.assertEqual(c._cookies[".foo.net"]["/foo/bar"]["spam2"].value,
  673. "eggs")
  674. self.assertEqual(interact_netscape(c, "http://foo.net/foo/bar/"),
  675. "spam2=eggs; spam1=eggs; ns=bar")
  676. # top-level domain is too general
  677. interact_netscape(c, "http://foo.net/", 'nini="ni"; domain=.net')
  678. self.assertEqual(len(c), 3)
  679. ## # Netscape protocol doesn't allow non-special top level domains (such
  680. ## # as co.uk) in the domain attribute unless there are at least three
  681. ## # dots in it.
  682. # Oh yes it does! Real implementations don't check this, and real
  683. # cookies (of course) rely on that behaviour.
  684. interact_netscape(c, "http://foo.co.uk", 'nasty=trick; domain=.co.uk')
  685. ## self.assertEqual(len(c), 2)
  686. self.assertEqual(len(c), 4)
  687. def test_two_component_domain_rfc2965(self):
  688. from cookielib import CookieJar, DefaultCookiePolicy
  689. pol = DefaultCookiePolicy(rfc2965=True)
  690. c = CookieJar(pol)
  691. # two-component V1 domain is OK
  692. interact_2965(c, "http://foo.net/", 'foo=bar; Version="1"')
  693. self.assertEqual(len(c), 1)
  694. self.assertEqual(c._cookies["foo.net"]["/"]["foo"].value, "bar")
  695. self.assertEqual(interact_2965(c, "http://foo.net/"),
  696. "$Version=1; foo=bar")
  697. # won't be returned to any other domain (because domain was implied)
  698. self.assertEqual(interact_2965(c, "http://www.foo.net/"), "")
  699. # unless domain is given explicitly, because then it must be
  700. # rewritten to start with a dot: foo.net --> .foo.net, which does
  701. # not domain-match foo.net
  702. interact_2965(c, "http://foo.net/foo",
  703. 'spam=eggs; domain=foo.net; path=/foo; Version="1"')
  704. self.assertEqual(len(c), 1)
  705. self.assertEqual(interact_2965(c, "http://foo.net/foo"),
  706. "$Version=1; foo=bar")
  707. # explicit foo.net from three-component domain www.foo.net *does* get
  708. # set, because .foo.net domain-matches .foo.net
  709. interact_2965(c, "http://www.foo.net/foo/",
  710. 'spam=eggs; domain=foo.net; Version="1"')
  711. self.assertEqual(c._cookies[".foo.net"]["/foo/"]["spam"].value,
  712. "eggs")
  713. self.assertEqual(len(c), 2)
  714. self.assertEqual(interact_2965(c, "http://foo.net/foo/"),
  715. "$Version=1; foo=bar")
  716. self.assertEqual(interact_2965(c, "http://www.foo.net/foo/"),
  717. '$Version=1; spam=eggs; $Domain="foo.net"')
  718. # top-level domain is too general
  719. interact_2965(c, "http://foo.net/",
  720. 'ni="ni"; domain=".net"; Version="1"')
  721. self.assertEqual(len(c), 2)
  722. # RFC 2965 doesn't require blocking this
  723. interact_2965(c, "http://foo.co.uk/",
  724. 'nasty=trick; domain=.co.uk; Version="1"')
  725. self.assertEqual(len(c), 3)
  726. def test_domain_allow(self):
  727. from cookielib import CookieJar, DefaultCookiePolicy
  728. from urllib2 import Request
  729. c = CookieJar(policy=DefaultCookiePolicy(
  730. blocked_domains=["acme.com"],
  731. allowed_domains=["www.acme.com"]))
  732. req = Request("http://acme.com/")
  733. headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"]
  734. res = FakeResponse(headers, "http://acme.com/")
  735. c.extract_cookies(res, req)
  736. self.assertEqual(len(c), 0)
  737. req = Request("http://www.acme.com/")
  738. res = FakeResponse(headers, "http://www.acme.com/")
  739. c.extract_cookies(res, req)
  740. self.assertEqual(len(c), 1)
  741. req = Request("http://www.coyote.com/")
  742. res = FakeResponse(headers, "http://www.coyote.com/")
  743. c.extract_cookies(res, req)
  744. self.assertEqual(len(c), 1)
  745. # set a cookie with non-allowed domain...
  746. req = Request("http://www.coyote.com/")
  747. res = FakeResponse(headers, "http://www.coyote.com/")
  748. cookies = c.make_cookies(res, req)
  749. c.set_cookie(cookies[0])
  750. self.assertEqual(len(c), 2)
  751. # ... and check is doesn't get returned
  752. c.add_cookie_header(req)
  753. self.assertTrue(not req.has_header("Cookie"))
  754. def test_domain_block(self):
  755. from cookielib import CookieJar, DefaultCookiePolicy
  756. from urllib2 import Request
  757. pol = DefaultCookiePolicy(
  758. rfc2965=True, blocked_domains=[".acme.com"])
  759. c = CookieJar(policy=pol)
  760. headers = ["Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/"]
  761. req = Request("http://www.acme.com/")
  762. res = FakeResponse(headers, "http://www.acme.com/")
  763. c.extract_cookies(res, req)
  764. self.assertEqual(len(c), 0)
  765. p = pol.set_blocked_domains(["acme.com"])
  766. c.extract_cookies(res, req)
  767. self.assertEqual(len(c), 1)
  768. c.clear()
  769. req = Request("http://www.roadrunner.net/")
  770. res = FakeResponse(headers, "http://www.roadrunner.net/")
  771. c.extract_cookies(res, req)
  772. self.assertEqual(len(c), 1)
  773. req = Request("http://www.roadrunner.net/")
  774. c.add_cookie_header(req)
  775. self.assertTrue((req.has_header("Cookie") and
  776. req.has_header("Cookie2")))
  777. c.clear()
  778. pol.set_blocked_domains([".acme.com"])
  779. c.extract_cookies(res, req)
  780. self.assertEqual(len(c), 1)
  781. # set a cookie with blocked domain...
  782. req = Request("http://www.acme.com/")
  783. res = FakeResponse(headers, "http://www.acme.com/")
  784. cookies = c.make_cookies(res, req)
  785. c.set_cookie(cookies[0])
  786. self.assertEqual(len(c), 2)
  787. # ... and check is doesn't get returned
  788. c.add_cookie_header(req)
  789. self.assertTrue(not req.has_header("Cookie"))
  790. def test_secure(self):
  791. from cookielib import CookieJar, DefaultCookiePolicy
  792. for ns in True, False:
  793. for whitespace in " ", "":
  794. c = CookieJar()
  795. if ns:
  796. pol = DefaultCookiePolicy(rfc2965=False)
  797. int = interact_netscape
  798. vs = ""
  799. else:
  800. pol = DefaultCookiePolicy(rfc2965=True)
  801. int = interact_2965
  802. vs = "; Version=1"
  803. c.set_policy(pol)
  804. url = "http://www.acme.com/"
  805. int(c, url, "foo1=bar%s%s" % (vs, whitespace))
  806. int(c, url, "foo2=bar%s; secure%s" % (vs, whitespace))
  807. self.assertTrue(
  808. not c._cookies["www.acme.com"]["/"]["foo1"].secure,
  809. "non-secure cookie registered secure")
  810. self.assertTrue(
  811. c._cookies["www.acme.com"]["/"]["foo2"].secure,
  812. "secure cookie registered non-secure")
  813. def test_quote_cookie_value(self):
  814. from cookielib import CookieJar, DefaultCookiePolicy
  815. c = CookieJar(policy=DefaultCookiePolicy(rfc2965=True))
  816. interact_2965(c, "http://www.acme.com/", r'foo=\b"a"r; Version=1')
  817. h = interact_2965(c, "http://www.acme.com/")
  818. self.assertEqual(h, r'$Version=1; foo=\\b\"a\"r')
  819. def test_missing_final_slash(self):
  820. # Missing slash from request URL's abs_path should be assumed present.
  821. from cookielib import CookieJar, DefaultCookiePolicy
  822. from urllib2 import Request
  823. url = "http://www.acme.com"
  824. c = CookieJar(DefaultCookiePolicy(rfc2965=True))
  825. interact_2965(c, url, "foo=bar; Version=1")
  826. req = Request(url)
  827. self.assertEqual(len(c), 1)
  828. c.add_cookie_header(req)
  829. self.assertTrue(req.has_header("Cookie"))
  830. def test_domain_mirror(self):
  831. from cookielib import CookieJar, DefaultCookiePolicy
  832. pol = DefaultCookiePolicy(rfc2965=True)
  833. c = CookieJar(pol)
  834. url = "http://foo.bar.com/"
  835. interact_2965(c, url, "spam=eggs; Version=1")
  836. h = interact_2965(c, url)
  837. self.assertNotIn("Domain", h,
  838. "absent domain returned with domain present")
  839. c = CookieJar(pol)
  840. url = "http://foo.bar.com/"
  841. interact_2965(c, url, 'spam=eggs; Version=1; Domain=.bar.com')
  842. h = interact_2965(c, url)
  843. self.assertIn('$Domain=".bar.com"', h, "domain not returned")
  844. c = CookieJar(pol)
  845. url = "http://foo.bar.com/"
  846. # note missing initial dot in Domain
  847. interact_2965(c, url, 'spam=eggs; Version=1; Domain=bar.com')
  848. h = interact_2965(c, url)
  849. self.assertIn('$Domain="bar.com"', h, "domain not returned")
  850. def test_path_mirror(self):
  851. from cookielib import CookieJar, DefaultCookiePolicy
  852. pol = DefaultCookiePolicy(rfc2965=True)
  853. c = CookieJar(pol)
  854. url = "http://foo.bar.com/"
  855. interact_2965(c, url, "spam=eggs; Version=1")
  856. h = interact_2965(c, url)
  857. self.assertNotIn("Path", h, "absent path returned with path present")
  858. c = CookieJar(pol)
  859. url = "http://foo.bar.com/"
  860. interact_2965(c, url, 'spam=eggs; Version=1; Path=/')
  861. h = interact_2965(c, url)
  862. self.assertIn('$Path="/"', h, "path not returned")
  863. def test_port_mirror(self):
  864. from cookielib import CookieJar, DefaultCookiePolicy
  865. pol = DefaultCookiePolicy(rfc2965=True)
  866. c = CookieJar(pol)
  867. url = "http://foo.bar.com/"
  868. interact_2965(c, url, "spam=eggs; Version=1")
  869. h = interact_2965(c, url)
  870. self.assertNotIn("Port", h, "absent port returned with port present")
  871. c = CookieJar(pol)
  872. url = "http://foo.bar.com/"
  873. interact_2965(c, url, "spam=eggs; Version=1; Port")
  874. h = interact_2965(c, url)
  875. self.assertTrue(re.search("\$Port([^=]|$)", h),
  876. "port with no value not returned with no value")
  877. c = CookieJar(pol)
  878. url = "http://foo.bar.com/"
  879. interact_2965(c, url, 'spam=eggs; Version=1; Port="80"')
  880. h = interact_2965(c, url)
  881. self.assertIn('$Port="80"', h,
  882. "port with single value not returned with single value")
  883. c = CookieJar(pol)
  884. url = "http://foo.bar.com/"
  885. interact_2965(c, url, 'spam=eggs; Version=1; Port="80,8080"')
  886. h = interact_2965(c, url)
  887. self.assertIn('$Port="80,8080"', h,
  888. "port with multiple values not returned with multiple "
  889. "values")
  890. def test_no_return_comment(self):
  891. from cookielib import CookieJar, DefaultCookiePolicy
  892. c = CookieJar(DefaultCookiePolicy(rfc2965=True))
  893. url = "http://foo.bar.com/"
  894. interact_2965(c, url, 'spam=eggs; Version=1; '
  895. 'Comment="does anybody read these?"; '
  896. 'CommentURL="http://foo.bar.net/comment.html"')
  897. h = interact_2965(c, url)
  898. self.assertTrue(
  899. "Comment" not in h,
  900. "Comment or CommentURL cookie-attributes returned to server")
  901. def test_Cookie_iterator(self):
  902. from cookielib import CookieJar, Cookie, DefaultCookiePolicy
  903. cs = CookieJar(DefaultCookiePolicy(rfc2965=True))
  904. # add some random cookies
  905. interact_2965(cs, "http://blah.spam.org/", 'foo=eggs; Version=1; '
  906. 'Comment="does anybody read these?"; '
  907. 'CommentURL="http://foo.bar.net/comment.html"')
  908. interact_netscape(cs, "http://www.acme.com/blah/", "spam=bar; secure")
  909. interact_2965(cs, "http://www.acme.com/blah/",
  910. "foo=bar; secure; Version=1")
  911. interact_2965(cs, "http://www.acme.com/blah/",
  912. "foo=bar; path=/; Version=1")
  913. interact_2965(cs, "http://www.sol.no",
  914. r'bang=wallop; version=1; domain=".sol.no"; '
  915. r'port="90,100, 80,8080"; '
  916. r'max-age=100; Comment = "Just kidding! (\"|\\\\) "')
  917. versions = [1, 1, 1, 0, 1]
  918. names = ["bang", "foo", "foo", "spam", "foo"]
  919. domains = [".sol.no", "blah.spam.org", "www.acme.com",
  920. "www.acme.com", "www.acme.com"]
  921. paths = ["/", "/", "/", "/blah", "/blah/"]
  922. for i in range(4):
  923. i = 0
  924. for c in cs:
  925. self.assertIsInstance(c, Cookie)
  926. self.assertEqual(c.version, versions[i])
  927. self.assertEqual(c.name, names[i])
  928. self.assertEqual(c.domain, domains[i])
  929. self.assertEqual(c.path, paths[i])
  930. i = i + 1
  931. def test_parse_ns_headers(self):
  932. from cookielib import parse_ns_headers
  933. # missing domain value (invalid cookie)
  934. self.assertEqual(
  935. parse_ns_headers(["foo=bar; path=/; domain"]),
  936. [[("foo", "bar"),
  937. ("path", "/"), ("domain", None), ("version", "0")]]
  938. )
  939. # invalid expires value
  940. self.assertEqual(
  941. parse_ns_headers(["foo=bar; expires=Foo Bar 12 33:22:11 2000"]),
  942. [[("foo", "bar"), ("expires", None), ("version", "0")]]
  943. )
  944. # missing cookie value (valid cookie)
  945. self.assertEqual(
  946. parse_ns_headers(["foo"]),
  947. [[("foo", None), ("version", "0")]]
  948. )
  949. # shouldn't add version if header is empty
  950. self.assertEqual(parse_ns_headers([""]), [])
  951. def test_bad_cookie_header(self):
  952. def cookiejar_from_cookie_headers(headers):
  953. from cookielib import CookieJar
  954. from urllib2 import Request
  955. c = CookieJar()
  956. req = Request("http://www.example.com/")
  957. r = FakeResponse(headers, "http://www.example.com/")
  958. c.extract_cookies(r, req)
  959. return c
  960. # none of these bad headers should cause an exception to be raised
  961. for headers in [
  962. ["Set-Cookie: "], # actually, nothing wrong with this
  963. ["Set-Cookie2: "], # ditto
  964. # missing domain value
  965. ["Set-Cookie2: a=foo; path=/; Version=1; domain"],
  966. # bad max-age
  967. ["Set-Cookie: b=foo; max-age=oops"],
  968. # bad version
  969. ["Set-Cookie: b=foo; version=spam"],
  970. ]:
  971. c = cookiejar_from_cookie_headers(headers)
  972. # these bad cookies shouldn't be set
  973. self.assertEqual(len(c), 0)
  974. # cookie with invalid expires is treated as session cookie
  975. headers = ["Set-Cookie: c=foo; expires=Foo Bar 12 33:22:11 2000"]
  976. c = cookiejar_from_cookie_headers(headers)
  977. cookie = c._cookies["www.example.com"]["/"]["c"]
  978. self.assertTrue(cookie.expires is None)
  979. class LWPCookieTests(TestCase):
  980. # Tests taken from libwww-perl, with a few modifications and additions.
  981. def test_netscape_example_1(self):
  982. from cookielib import CookieJar, DefaultCookiePolicy
  983. from urllib2 import Request
  984. #-------------------------------------------------------------------
  985. # First we check that it works for the original example at
  986. # http://www.netscape.com/newsref/std/cookie_spec.html
  987. # Client requests a document, and receives in the response:
  988. #
  989. # Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT
  990. #
  991. # When client requests a URL in path "/" on this server, it sends:
  992. #
  993. # Cookie: CUSTOMER=WILE_E_COYOTE
  994. #
  995. # Client requests a document, and receives in the response:
  996. #
  997. # Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/
  998. #
  999. # When client requests a URL in path "/" on this server, it sends:
  1000. #
  1001. # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
  1002. #
  1003. # Client receives:
  1004. #
  1005. # Set-Cookie: SHIPPING=FEDEX; path=/fo
  1006. #
  1007. # When client requests a URL in path "/" on this server, it sends:
  1008. #
  1009. # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001
  1010. #
  1011. # When client requests a URL in path "/foo" on this server, it sends:
  1012. #
  1013. # Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001; SHIPPING=FEDEX
  1014. #
  1015. # The last Cookie is buggy, because both specifications say that the
  1016. # most specific cookie must be sent first. SHIPPING=FEDEX is the
  1017. # most specific and should thus be first.
  1018. year_plus_one = time.localtime()[0] + 1
  1019. headers = []
  1020. c = CookieJar(DefaultCookiePolicy(rfc2965 = True))
  1021. #req = Request("http://1.1.1.1/",
  1022. # headers={"Host": "www.acme.com:80"})
  1023. req = Request("http://www.acme.com:80/",
  1024. headers={"Host": "www.acme.com:80"})
  1025. headers.append(
  1026. "Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/ ; "
  1027. "expires=Wednesday, 09-Nov-%d 23:12:40…

Large files files are truncated, but you can click here to view the full file