~vcs-imports/clientcookie/trunk

« back to all changes in this revision

Viewing changes to ClientCookie/_MozillaCookieJar.py

  • Committer: jjlee
  • Date: 2004-03-31 19:36:11 UTC
  • Revision ID: svn-v4:fd0d7bf2-dfb6-0310-8d31-b7ecfe96aada:user/jjlee/wwwsearch/ClientCookie:3571
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 getLogger
 
18
debug = getLogger("ClientCookie").debug
 
19
 
 
20
try: True
 
21
except NameError:
 
22
    True = 1
 
23
    False = 0
 
24
 
 
25
try: issubclass(Exception(), (Exception,))
 
26
except TypeError:
 
27
    real_issubclass = issubclass
 
28
    from _Util import compat_issubclass
 
29
    issubclass = compat_issubclass
 
30
    del compat_issubclass
 
31
 
 
32
 
 
33
class MozillaCookieJar(CookieJar):
 
34
    """
 
35
 
 
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
 
38
    bugs in the past!
 
39
 
 
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.
 
43
 
 
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).
 
48
 
 
49
    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
 
50
    Netscape cookies on saving.
 
51
 
 
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).
 
58
 
 
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).
 
62
 
 
63
    """
 
64
    magic_re = "#( Netscape)? HTTP Cookie File"
 
65
    header = """\
 
66
    # Netscape HTTP Cookie File
 
67
    # http://www.netscape.com/newsref/std/cookie_spec.html
 
68
    # This is a generated file!  Do not edit.
 
69
 
 
70
"""
 
71
 
 
72
    def _really_load(self, f, filename, ignore_discard, ignore_expires):
 
73
        now = time.time()
 
74
 
 
75
        magic = f.readline()
 
76
        if not re.search(self.magic_re, magic):
 
77
            f.close()
 
78
            raise IOError(
 
79
                "%s does not look like a Netscape format cookies file" %
 
80
                filename)
 
81
 
 
82
        try:
 
83
            while 1:
 
84
                line = f.readline()
 
85
                if line == "": break
 
86
 
 
87
                # last field may be absent, so keep any trailing tab
 
88
                if endswith(line, "\n"): line = line[:-1]
 
89
 
 
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) == ""):
 
94
                    continue
 
95
 
 
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
 
101
 
 
102
                initial_dot = startswith(domain, ".")
 
103
                assert domain_specified == initial_dot
 
104
 
 
105
                discard = False
 
106
                if expires == "":
 
107
                    expires = None
 
108
                    discard = True
 
109
 
 
110
                # assume path_specified is false
 
111
                c = Cookie(0, name, value,
 
112
                           None, False,
 
113
                           domain, domain_specified, initial_dot,
 
114
                           path, False,
 
115
                           secure,
 
116
                           expires,
 
117
                           discard,
 
118
                           None,
 
119
                           None,
 
120
                           {})
 
121
                if not ignore_discard and c.discard:
 
122
                    continue
 
123
                if not ignore_expires and c.is_expired(now):
 
124
                    continue
 
125
                self.set_cookie(c)
 
126
 
 
127
        except:
 
128
            reraise_unmasked_exceptions((IOError,))
 
129
            raise IOError("invalid Netscape format file %s: %s" %
 
130
                          (filename, line))
 
131
 
 
132
    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
 
133
        if filename is None:
 
134
            if self.filename is not None: filename = self.filename
 
135
            else: raise ValueError(MISSING_FILENAME_TEXT)
 
136
 
 
137
        f = open(filename, "w")
 
138
        try:
 
139
            f.write(self.header)
 
140
            now = time.time()
 
141
            debug("Saving Netscape cookies.txt file")
 
142
            for cookie in self:
 
143
                if not ignore_discard and cookie.discard:
 
144
                    debug("   Not saving %s: marked for discard", cookie.name)
 
145
                    continue
 
146
                if not ignore_expires and cookie.is_expired(now):
 
147
                    debug("   Not saving %s: expired", cookie.name)
 
148
                    continue
 
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)
 
155
                else:
 
156
                    expires = ""
 
157
                if cookie.name is not None:
 
158
                    name = cookie.name
 
159
                else:
 
160
                    name = ""
 
161
                f.write(
 
162
                    string.join([cookie.domain, initial_dot, cookie.path,
 
163
                                 secure, expires, name, cookie.value], "\t")+
 
164
                    "\n")
 
165
        finally:
 
166
            f.close()