update documentation extraction script (use .cc instead of .h)
[ardour.git] / tools / bug_tool / ClientCookie / _MozillaCookieJar.py
1 """Mozilla / Netscape cookie loading / saving.
2
3 Copyright 1997-1999 Gisle Aas (libwww-perl)
4 Copyright 2002-2003 John J Lee <jjl@pobox.com> (The Python port)
5
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
8 distribution).
9
10 """
11
12 import sys, re, string, time
13
14 import ClientCookie
15 from _ClientCookie import CookieJar, Cookie, MISSING_FILENAME_TEXT
16 from _Util import startswith, endswith
17 from _Debug import debug
18
19 try: True
20 except NameError:
21     True = 1
22     False = 0
23
24 try: issubclass(Exception(), (Exception,))
25 except TypeError:
26     real_issubclass = issubclass
27     from _Util import compat_issubclass
28     issubclass = compat_issubclass
29     del compat_issubclass
30
31
32 class MozillaCookieJar(CookieJar):
33     """
34
35     WARNING: you may want to backup your browser's cookies file if you use
36     this class to save cookies.  I *think* it works, but there have been
37     bugs in the past!
38
39     This class differs from CookieJar only in the format it uses to save and
40     load cookies to and from a file.  This class uses the Netscape/Mozilla
41     `cookies.txt' format.
42
43     Don't expect cookies saved while the browser is running to be noticed by
44     the browser (in fact, Mozilla on unix will overwrite your saved cookies if
45     you change them on disk while it's running; on Windows, you probably can't
46     save at all while the browser is running).
47
48     Note that the Netscape/Mozilla format will downgrade RFC2965 cookies to
49     Netscape cookies on saving.
50
51     In particular, the cookie version and port number information is lost,
52     together with information about whether or not Path, Port and Discard were
53     specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
54     domain as set in the HTTP header started with a dot (yes, I'm aware some
55     domains in Netscape files start with a dot and some don't -- trust me, you
56     really don't want to know any more about this).
57
58     Note that though Mozilla and Netscape use the same format, they use
59     slightly different headers.  The class saves cookies using the Netscape
60     header by default (Mozilla can cope with that).
61
62     """
63     magic_re = "#( Netscape)? HTTP Cookie File"
64     header = """\
65     # Netscape HTTP Cookie File
66     # http://www.netscape.com/newsref/std/cookie_spec.html
67     # This is a generated file!  Do not edit.
68
69 """
70
71     def _really_load(self, f, filename, ignore_discard, ignore_expires):
72         now = time.time()
73
74         magic = f.readline()
75         if not re.search(self.magic_re, magic):
76             f.close()
77             raise IOError(
78                 "%s does not look like a Netscape format cookies file" %
79                 filename)
80
81         try:
82             while 1:
83                 line = f.readline()
84                 if line == "": break
85
86                 # last field may be absent, so keep any trailing tab
87                 if endswith(line, "\n"): line = line[:-1]
88
89                 # skip comments and blank lines XXX what is $ for?
90                 if (startswith(string.strip(line), "#") or
91                     startswith(string.strip(line), "$") or
92                     string.strip(line) == ""):
93                     continue
94
95                 domain, domain_specified, path, secure, expires, name, value = \
96                         string.split(line, "\t")
97                 secure = (secure == "TRUE")
98                 domain_specified = (domain_specified == "TRUE")
99                 if name == "": name = None
100
101                 initial_dot = startswith(domain, ".")
102                 assert domain_specified == initial_dot
103
104                 discard = False
105                 if expires == "":
106                     expires = None
107                     discard = True
108
109                 # assume path_specified is false
110                 c = Cookie(0, name, value,
111                            None, False,
112                            domain, domain_specified, initial_dot,
113                            path, False,
114                            secure,
115                            expires,
116                            discard,
117                            None,
118                            None,
119                            {})
120                 if not ignore_discard and c.discard:
121                     continue
122                 if not ignore_expires and c.is_expired(now):
123                     continue
124                 self.set_cookie(c)
125
126         except:
127             unmasked = (KeyboardInterrupt, SystemExit)
128             if ClientCookie.CLIENTCOOKIE_DEBUG:
129                 unmasked = (Exception,)
130             etype = sys.exc_info()[0]
131             if issubclass(etype, IOError) or \
132                    issubclass(etype, unmasked):
133                 raise
134             raise IOError("invalid Netscape format file %s: %s" %
135                           (filename, line))
136
137     def save(self, filename=None, ignore_discard=False, ignore_expires=False):
138         if filename is None:
139             if self.filename is not None: filename = self.filename
140             else: raise ValueError(MISSING_FILENAME_TEXT)
141
142         f = open(filename, "w")
143         try:
144             f.write(self.header)
145             now = time.time()
146             debug("Saving Netscape cookies.txt file")
147             for cookie in self:
148                 if not ignore_discard and cookie.discard:
149                     debug("   Not saving %s: marked for discard" % cookie.name)
150                     continue
151                 if not ignore_expires and cookie.is_expired(now):
152                     debug("   Not saving %s: expired" % cookie.name)
153                     continue
154                 if cookie.secure: secure = "TRUE"
155                 else: secure = "FALSE"
156                 if startswith(cookie.domain, "."): initial_dot = "TRUE"
157                 else: initial_dot = "FALSE"
158                 if cookie.expires is not None:
159                     expires = str(cookie.expires)
160                 else:
161                     expires = ""
162                 if cookie.name is not None:
163                     name = cookie.name
164                 else:
165                     name = ""
166                 f.write(
167                     string.join([cookie.domain, initial_dot, cookie.path,
168                                  secure, expires, name, cookie.value], "\t")+
169                     "\n")
170         finally:
171             f.close()