PageRenderTime 184ms CodeModel.GetById 70ms app.highlight 12ms RepoModel.GetById 99ms app.codeStats 0ms

/Lib/_MozillaCookieJar.py

http://unladen-swallow.googlecode.com/
Python | 149 lines | 140 code | 6 blank | 3 comment | 15 complexity | f72af3996e593566dc3b373f45862fee MD5 | raw file
  1"""Mozilla / Netscape cookie loading / saving."""
  2
  3import re, time
  4
  5from cookielib import (_warn_unhandled_exception, FileCookieJar, LoadError,
  6                       Cookie, MISSING_FILENAME_TEXT)
  7
  8class 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()