]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/python/_MozillaCookieJar.py
dist/mkfile: run binds in subshell
[plan9front.git] / sys / lib / python / _MozillaCookieJar.py
1 """Mozilla / Netscape cookie loading / saving."""
2
3 import re, time
4
5 from cookielib import (_warn_unhandled_exception, FileCookieJar, LoadError,
6                        Cookie, MISSING_FILENAME_TEXT)
7
8 class MozillaCookieJar(FileCookieJar):
9     """
10
11     WARNING: you may want to backup your browser's cookies file if you use
12     this class to save cookies.  I *think* it works, but there have been
13     bugs in the past!
14
15     This class differs from CookieJar only in the format it uses to save and
16     load cookies to and from a file.  This class uses the Mozilla/Netscape
17     `cookies.txt' format.  lynx uses this file format, too.
18
19     Don't expect cookies saved while the browser is running to be noticed by
20     the browser (in fact, Mozilla on unix will overwrite your saved cookies if
21     you change them on disk while it's running; on Windows, you probably can't
22     save at all while the browser is running).
23
24     Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
25     Netscape cookies on saving.
26
27     In particular, the cookie version and port number information is lost,
28     together with information about whether or not Path, Port and Discard were
29     specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
30     domain as set in the HTTP header started with a dot (yes, I'm aware some
31     domains in Netscape files start with a dot and some don't -- trust me, you
32     really don't want to know any more about this).
33
34     Note that though Mozilla and Netscape use the same format, they use
35     slightly different headers.  The class saves cookies using the Netscape
36     header by default (Mozilla can cope with that).
37
38     """
39     magic_re = "#( Netscape)? HTTP Cookie File"
40     header = """\
41     # Netscape HTTP Cookie File
42     # http://www.netscape.com/newsref/std/cookie_spec.html
43     # This is a generated file!  Do not edit.
44
45 """
46
47     def _really_load(self, f, filename, ignore_discard, ignore_expires):
48         now = time.time()
49
50         magic = f.readline()
51         if not re.search(self.magic_re, magic):
52             f.close()
53             raise LoadError(
54                 "%r does not look like a Netscape format cookies file" %
55                 filename)
56
57         try:
58             while 1:
59                 line = f.readline()
60                 if line == "": break
61
62                 # last field may be absent, so keep any trailing tab
63                 if line.endswith("\n"): line = line[:-1]
64
65                 # skip comments and blank lines XXX what is $ for?
66                 if (line.strip().startswith(("#", "$")) or
67                     line.strip() == ""):
68                     continue
69
70                 domain, domain_specified, path, secure, expires, name, value = \
71                         line.split("\t")
72                 secure = (secure == "TRUE")
73                 domain_specified = (domain_specified == "TRUE")
74                 if name == "":
75                     # cookies.txt regards 'Set-Cookie: foo' as a cookie
76                     # with no name, whereas cookielib regards it as a
77                     # cookie with no value.
78                     name = value
79                     value = None
80
81                 initial_dot = domain.startswith(".")
82                 assert domain_specified == initial_dot
83
84                 discard = False
85                 if expires == "":
86                     expires = None
87                     discard = True
88
89                 # assume path_specified is false
90                 c = Cookie(0, name, value,
91                            None, False,
92                            domain, domain_specified, initial_dot,
93                            path, False,
94                            secure,
95                            expires,
96                            discard,
97                            None,
98                            None,
99                            {})
100                 if not ignore_discard and c.discard:
101                     continue
102                 if not ignore_expires and c.is_expired(now):
103                     continue
104                 self.set_cookie(c)
105
106         except IOError:
107             raise
108         except Exception:
109             _warn_unhandled_exception()
110             raise LoadError("invalid Netscape format cookies file %r: %r" %
111                             (filename, line))
112
113     def save(self, filename=None, ignore_discard=False, ignore_expires=False):
114         if filename is None:
115             if self.filename is not None: filename = self.filename
116             else: raise ValueError(MISSING_FILENAME_TEXT)
117
118         f = open(filename, "w")
119         try:
120             f.write(self.header)
121             now = time.time()
122             for cookie in self:
123                 if not ignore_discard and cookie.discard:
124                     continue
125                 if not ignore_expires and cookie.is_expired(now):
126                     continue
127                 if cookie.secure: secure = "TRUE"
128                 else: secure = "FALSE"
129                 if cookie.domain.startswith("."): initial_dot = "TRUE"
130                 else: initial_dot = "FALSE"
131                 if cookie.expires is not None:
132                     expires = str(cookie.expires)
133                 else:
134                     expires = ""
135                 if cookie.value is None:
136                     # cookies.txt regards 'Set-Cookie: foo' as a cookie
137                     # with no name, whereas cookielib regards it as a
138                     # cookie with no value.
139                     name = ""
140                     value = cookie.name
141                 else:
142                     name = cookie.name
143                     value = cookie.value
144                 f.write(
145                     "\t".join([cookie.domain, initial_dot, cookie.path,
146                                secure, expires, name, value])+
147                     "\n")
148         finally:
149             f.close()