1
"""Mozilla / Netscape cookie loading / saving.
3
Copyright 1997-1999 Gisle Aas (libwww-perl)
4
Copyright 2002-2003 John J Lee <jjl@pobox.com> (The Python port)
6
This code is free software; you can redistribute it and/or modify it under
7
the terms of the BSD License (see the file COPYING included with the
12
import sys, re, string, time
15
from _ClientCookie import CookieJar, Cookie, MISSING_FILENAME_TEXT
16
from _Util import startswith, endswith
17
from _Debug import getLogger
18
debug = getLogger("ClientCookie").debug
25
try: issubclass(Exception(), (Exception,))
27
real_issubclass = issubclass
28
from _Util import compat_issubclass
29
issubclass = compat_issubclass
33
class MozillaCookieJar(CookieJar):
36
WARNING: you may want to backup your browser's cookies file if you use
37
this class to save cookies. I *think* it works, but there have been
40
This class differs from CookieJar only in the format it uses to save and
41
load cookies to and from a file. This class uses the Mozilla/Netscape
42
`cookies.txt' format. lynx uses this file format, too.
44
Don't expect cookies saved while the browser is running to be noticed by
45
the browser (in fact, Mozilla on unix will overwrite your saved cookies if
46
you change them on disk while it's running; on Windows, you probably can't
47
save at all while the browser is running).
49
Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
50
Netscape cookies on saving.
52
In particular, the cookie version and port number information is lost,
53
together with information about whether or not Path, Port and Discard were
54
specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
55
domain as set in the HTTP header started with a dot (yes, I'm aware some
56
domains in Netscape files start with a dot and some don't -- trust me, you
57
really don't want to know any more about this).
59
Note that though Mozilla and Netscape use the same format, they use
60
slightly different headers. The class saves cookies using the Netscape
61
header by default (Mozilla can cope with that).
64
magic_re = "#( Netscape)? HTTP Cookie File"
66
# Netscape HTTP Cookie File
67
# http://www.netscape.com/newsref/std/cookie_spec.html
68
# This is a generated file! Do not edit.
72
def _really_load(self, f, filename, ignore_discard, ignore_expires):
76
if not re.search(self.magic_re, magic):
79
"%s does not look like a Netscape format cookies file" %
87
# last field may be absent, so keep any trailing tab
88
if endswith(line, "\n"): line = line[:-1]
90
# skip comments and blank lines XXX what is $ for?
91
if (startswith(string.strip(line), "#") or
92
startswith(string.strip(line), "$") or
93
string.strip(line) == ""):
96
domain, domain_specified, path, secure, expires, name, value = \
97
string.split(line, "\t")
98
secure = (secure == "TRUE")
99
domain_specified = (domain_specified == "TRUE")
100
if name == "": name = None
102
initial_dot = startswith(domain, ".")
103
assert domain_specified == initial_dot
110
# assume path_specified is false
111
c = Cookie(0, name, value,
113
domain, domain_specified, initial_dot,
121
if not ignore_discard and c.discard:
123
if not ignore_expires and c.is_expired(now):
128
reraise_unmasked_exceptions((IOError,))
129
raise IOError("invalid Netscape format file %s: %s" %
132
def save(self, filename=None, ignore_discard=False, ignore_expires=False):
134
if self.filename is not None: filename = self.filename
135
else: raise ValueError(MISSING_FILENAME_TEXT)
137
f = open(filename, "w")
141
debug("Saving Netscape cookies.txt file")
143
if not ignore_discard and cookie.discard:
144
debug(" Not saving %s: marked for discard", cookie.name)
146
if not ignore_expires and cookie.is_expired(now):
147
debug(" Not saving %s: expired", cookie.name)
149
if cookie.secure: secure = "TRUE"
150
else: secure = "FALSE"
151
if startswith(cookie.domain, "."): initial_dot = "TRUE"
152
else: initial_dot = "FALSE"
153
if cookie.expires is not None:
154
expires = str(cookie.expires)
157
if cookie.name is not None:
162
string.join([cookie.domain, initial_dot, cookie.path,
163
secure, expires, name, cookie.value], "\t")+