]>
git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Python-2.7.2/Lib/Cookie.py
5 # Copyright 2000 by Timothy O'Malley <timo@alum.mit.edu>
9 # Permission to use, copy, modify, and distribute this software
10 # and its documentation for any purpose and without fee is hereby
11 # granted, provided that the above copyright notice appear in all
12 # copies and that both that copyright notice and this permission
13 # notice appear in supporting documentation, and that the name of
14 # Timothy O'Malley not be used in advertising or publicity
15 # pertaining to distribution of the software without specific, written
18 # Timothy O'Malley DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
19 # SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20 # AND FITNESS, IN NO EVENT SHALL Timothy O'Malley BE LIABLE FOR
21 # ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
24 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25 # PERFORMANCE OF THIS SOFTWARE.
29 # Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp
30 # by Timothy O'Malley <timo@alum.mit.edu>
32 # Cookie.py is a Python module for the handling of HTTP
33 # cookies as a Python dictionary. See RFC 2109 for more
34 # information on cookies.
36 # The original idea to treat Cookies as a dictionary came from
37 # Dave Mitchell (davem@magnet.com) in 1995, when he released the
38 # first version of nscookie.py.
43 Here's a sample session to show how to use this module.
44 At the moment, this is the only documentation.
53 Most of the time you start by creating a cookie. Cookies come in
54 three flavors, each with slightly different encoding semantics, but
57 >>> C = Cookie.SimpleCookie()
58 >>> C = Cookie.SerialCookie()
59 >>> C = Cookie.SmartCookie()
61 [Note: Long-time users of Cookie.py will remember using
62 Cookie.Cookie() to create an Cookie object. Although deprecated, it
63 is still supported by the code. See the Backward Compatibility notes
64 for more information.]
66 Once you've created your Cookie, you can add values just as if it were
69 >>> C = Cookie.SmartCookie()
70 >>> C["fig"] = "newton"
71 >>> C["sugar"] = "wafer"
73 'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'
75 Notice that the printable representation of a Cookie is the
76 appropriate format for a Set-Cookie: header. This is the
77 default behavior. You can change the header and printed
78 attributes by using the .output() function
80 >>> C = Cookie.SmartCookie()
81 >>> C["rocky"] = "road"
82 >>> C["rocky"]["path"] = "/cookie"
83 >>> print C.output(header="Cookie:")
84 Cookie: rocky=road; Path=/cookie
85 >>> print C.output(attrs=[], header="Cookie:")
88 The load() method of a Cookie extracts cookies from a string. In a
89 CGI script, you would use this method to extract the cookies from the
90 HTTP_COOKIE environment variable.
92 >>> C = Cookie.SmartCookie()
93 >>> C.load("chips=ahoy; vienna=finger")
95 'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'
97 The load() method is darn-tootin smart about identifying cookies
98 within a string. Escaped quotation marks, nested semicolons, and other
99 such trickeries do not confuse it.
101 >>> C = Cookie.SmartCookie()
102 >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
104 Set-Cookie: keebler="E=everybody; L=\"Loves
\"; fudge
=\012;"
106 Each element of the Cookie also supports all of the RFC 2109
107 Cookie attributes. Here's an example which sets the Path
110 >>> C = Cookie.SmartCookie()
111 >>> C["oreo
"] = "doublestuff
"
112 >>> C["oreo
"]["path
"] = "/"
114 Set-Cookie: oreo=doublestuff; Path=/
116 Each dictionary element has a 'value' attribute, which gives you
117 back the value associated with the key.
119 >>> C = Cookie.SmartCookie()
120 >>> C["twix
"] = "none
for you
"
128 As mentioned before, there are three different flavors of Cookie
129 objects, each with different encoding/decoding semantics. This
130 section briefly discusses the differences.
134 The SimpleCookie expects that all values should be standard strings.
135 Just to be sure, SimpleCookie invokes the str() builtin to convert
136 the value to a string, when the values are set dictionary-style.
138 >>> C = Cookie.SimpleCookie()
140 >>> C["string
"] = "seven
"
141 >>> C["number
"].value
143 >>> C["string
"].value
146 'Set-Cookie: number=7\r\nSet-Cookie: string=seven'
151 The SerialCookie expects that all values should be serialized using
152 cPickle (or pickle, if cPickle isn't available). As a result of
153 serializing, SerialCookie can save almost any Python object to a
154 value, and recover the exact same object when the cookie has been
155 returned. (SerialCookie can yield some strange-looking cookie
158 >>> C = Cookie.SerialCookie()
160 >>> C["string
"] = "seven
"
161 >>> C["number
"].value
163 >>> C["string
"].value
166 'Set-Cookie: number="I7
\\012."\r\nSet-Cookie: string="S
\'seven
\'\\012p1
\\012."'
168 Be warned, however, if SerialCookie cannot de-serialize a value (because
169 it isn't a valid pickle'd object), IT WILL RAISE AN EXCEPTION.
174 The SmartCookie combines aspects of each of the other two flavors.
175 When setting a value in a dictionary-fashion, the SmartCookie will
176 serialize (ala cPickle) the value *if and only if* it isn't a
177 Python string. String objects are *not* serialized. Similarly,
178 when the load() method parses out values, it attempts to de-serialize
179 the value. If it fails, then it fallsback to treating the value
182 >>> C = Cookie.SmartCookie()
184 >>> C["string
"] = "seven
"
185 >>> C["number
"].value
187 >>> C["string
"].value
190 'Set-Cookie: number="I7
\\012."\r\nSet-Cookie: string=seven'
193 Backwards Compatibility
194 -----------------------
196 In order to keep compatibilty with earlier versions of Cookie.py,
197 it is still possible to use Cookie.Cookie() to create a Cookie. In
198 fact, this simply returns a SmartCookie.
200 >>> C = Cookie.Cookie()
201 >>> print C.__class__.__name__
208 # |----helps out font-lock
211 # Import our required modules
216 from cPickle
import dumps
, loads
218 from pickle
import dumps
, loads
222 __all__
= ["CookieError","BaseCookie","SimpleCookie","SerialCookie",
223 "SmartCookie","Cookie"]
226 _semispacejoin
= '; '.join
227 _spacejoin
= ' '.join
230 # Define an exception visible to External modules
232 class CookieError(Exception):
236 # These quoting routines conform to the RFC2109 specification, which in
237 # turn references the character definitions from RFC2068. They provide
238 # a two-way quoting algorithm. Any non-text character is translated
239 # into a 4 character sequence: a forward-slash followed by the
240 # three-digit octal equivalent of the character. Any '\' or '"' is
241 # quoted with a preceeding '\' slash.
243 # These are taken from RFC2068 and RFC2109.
244 # _LegalChars is the list of chars which don't require "'s
245 # _Translator hash-table for fast quoting
247 _LegalChars
= string
.ascii_letters
+ string
.digits
+ "!#$%&'*+-.^_`|~"
249 '\000' : '\\000', '\001' : '\\001', '\002' : '\\002',
250 '\003' : '\\003', '\004' : '\\004', '\005' : '\\005',
251 '\006' : '\\006', '\007' : '\\007', '\010' : '\\010',
252 '\011' : '\\011', '\012' : '\\012', '\013' : '\\013',
253 '\014' : '\\014', '\015' : '\\015', '\016' : '\\016',
254 '\017' : '\\017', '\020' : '\\020', '\021' : '\\021',
255 '\022' : '\\022', '\023' : '\\023', '\024' : '\\024',
256 '\025' : '\\025', '\026' : '\\026', '\027' : '\\027',
257 '\030' : '\\030', '\031' : '\\031', '\032' : '\\032',
258 '\033' : '\\033', '\034' : '\\034', '\035' : '\\035',
259 '\036' : '\\036', '\037' : '\\037',
261 # Because of the way browsers really handle cookies (as opposed
262 # to what the RFC says) we also encode , and ;
264 ',' : '\\054', ';' : '\\073',
266 '"' : '\\"', '\\' : '\\\\',
268 '\177' : '\\177', '\200' : '\\200', '\201' : '\\201',
269 '\202' : '\\202', '\203' : '\\203', '\204' : '\\204',
270 '\205' : '\\205', '\206' : '\\206', '\207' : '\\207',
271 '\210' : '\\210', '\211' : '\\211', '\212' : '\\212',
272 '\213' : '\\213', '\214' : '\\214', '\215' : '\\215',
273 '\216' : '\\216', '\217' : '\\217', '\220' : '\\220',
274 '\221' : '\\221', '\222' : '\\222', '\223' : '\\223',
275 '\224' : '\\224', '\225' : '\\225', '\226' : '\\226',
276 '\227' : '\\227', '\230' : '\\230', '\231' : '\\231',
277 '\232' : '\\232', '\233' : '\\233', '\234' : '\\234',
278 '\235' : '\\235', '\236' : '\\236', '\237' : '\\237',
279 '\240' : '\\240', '\241' : '\\241', '\242' : '\\242',
280 '\243' : '\\243', '\244' : '\\244', '\245' : '\\245',
281 '\246' : '\\246', '\247' : '\\247', '\250' : '\\250',
282 '\251' : '\\251', '\252' : '\\252', '\253' : '\\253',
283 '\254' : '\\254', '\255' : '\\255', '\256' : '\\256',
284 '\257' : '\\257', '\260' : '\\260', '\261' : '\\261',
285 '\262' : '\\262', '\263' : '\\263', '\264' : '\\264',
286 '\265' : '\\265', '\266' : '\\266', '\267' : '\\267',
287 '\270' : '\\270', '\271' : '\\271', '\272' : '\\272',
288 '\273' : '\\273', '\274' : '\\274', '\275' : '\\275',
289 '\276' : '\\276', '\277' : '\\277', '\300' : '\\300',
290 '\301' : '\\301', '\302' : '\\302', '\303' : '\\303',
291 '\304' : '\\304', '\305' : '\\305', '\306' : '\\306',
292 '\307' : '\\307', '\310' : '\\310', '\311' : '\\311',
293 '\312' : '\\312', '\313' : '\\313', '\314' : '\\314',
294 '\315' : '\\315', '\316' : '\\316', '\317' : '\\317',
295 '\320' : '\\320', '\321' : '\\321', '\322' : '\\322',
296 '\323' : '\\323', '\324' : '\\324', '\325' : '\\325',
297 '\326' : '\\326', '\327' : '\\327', '\330' : '\\330',
298 '\331' : '\\331', '\332' : '\\332', '\333' : '\\333',
299 '\334' : '\\334', '\335' : '\\335', '\336' : '\\336',
300 '\337' : '\\337', '\340' : '\\340', '\341' : '\\341',
301 '\342' : '\\342', '\343' : '\\343', '\344' : '\\344',
302 '\345' : '\\345', '\346' : '\\346', '\347' : '\\347',
303 '\350' : '\\350', '\351' : '\\351', '\352' : '\\352',
304 '\353' : '\\353', '\354' : '\\354', '\355' : '\\355',
305 '\356' : '\\356', '\357' : '\\357', '\360' : '\\360',
306 '\361' : '\\361', '\362' : '\\362', '\363' : '\\363',
307 '\364' : '\\364', '\365' : '\\365', '\366' : '\\366',
308 '\367' : '\\367', '\370' : '\\370', '\371' : '\\371',
309 '\372' : '\\372', '\373' : '\\373', '\374' : '\\374',
310 '\375' : '\\375', '\376' : '\\376', '\377' : '\\377'
313 _idmap
= ''.join(chr(x
) for x
in xrange(256))
315 def _quote(str, LegalChars
=_LegalChars
,
316 idmap
=_idmap
, translate
=string
.translate
):
318 # If the string does not need to be double-quoted,
319 # then just return the string. Otherwise, surround
320 # the string in doublequotes and precede quote (with a \)
321 # special characters.
323 if "" == translate(str, idmap
, LegalChars
):
326 return '"' + _nulljoin( map(_Translator
.get
, str, str) ) + '"'
330 _OctalPatt
= re
.compile(r
"\\[0-3][0-7][0-7]")
331 _QuotePatt
= re
.compile(r
"[\\].")
334 # If there aren't any doublequotes,
335 # then there can't be any special characters. See RFC 2109.
338 if str[0] != '"' or str[-1] != '"':
341 # We have to assume that we must decode this string.
347 # Check for special sequences. Examples:
355 Omatch
= _OctalPatt
.search(str, i
)
356 Qmatch
= _QuotePatt
.search(str, i
)
357 if not Omatch
and not Qmatch
: # Neither matched
362 if Omatch
: j
= Omatch
.start(0)
363 if Qmatch
: k
= Qmatch
.start(0)
364 if Qmatch
and ( not Omatch
or k
< j
): # QuotePatt matched
368 else: # OctalPatt matched
370 res
.append( chr( int(str[j
+1:j
+4], 8) ) )
372 return _nulljoin(res
)
375 # The _getdate() routine is used to set the expiration time in
376 # the cookie's HTTP header. By default, _getdate() returns the
377 # current time in the appropriate "expires" format for a
378 # Set-Cookie header. The one optional argument is an offset from
379 # now, in seconds. For example, an offset of -3600 means "one hour ago".
380 # The offset may be a floating point number.
383 _weekdayname
= ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
386 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
387 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
389 def _getdate(future
=0, weekdayname
=_weekdayname
, monthname
=_monthname
):
390 from time
import gmtime
, time
392 year
, month
, day
, hh
, mm
, ss
, wd
, y
, z
= gmtime(now
+ future
)
393 return "%s, %02d-%3s-%4d %02d:%02d:%02d GMT" % \
394 (weekdayname
[wd
], day
, monthname
[month
], year
, hh
, mm
, ss
)
398 # A class to hold ONE key,value pair.
399 # In a cookie, each such pair may have several attributes.
400 # so this class is used to keep the attributes associated
401 # with the appropriate key,value pair.
402 # This class also includes a coded_value attribute, which
403 # is used to hold the network representation of the
404 # value. This is most useful when Python objects are
405 # pickled for network transit.
409 # RFC 2109 lists these attributes as reserved:
410 # path comment domain
411 # max-age secure version
413 # For historical reasons, these attributes are also reserved:
416 # This is an extension from Microsoft:
419 # This dictionary provides a mapping from the lowercase
420 # variant on the left to the appropriate traditional
421 # formatting on the right.
422 _reserved
= { "expires" : "expires",
424 "comment" : "Comment",
426 "max-age" : "Max-Age",
428 "httponly" : "httponly",
429 "version" : "Version",
434 self
.key
= self
.value
= self
.coded_value
= None
436 # Set default attributes
437 for K
in self
._reserved
:
438 dict.__setitem
__(self
, K
, "")
441 def __setitem__(self
, K
, V
):
443 if not K
in self
._reserved
:
444 raise CookieError("Invalid Attribute %s" % K
)
445 dict.__setitem
__(self
, K
, V
)
448 def isReservedKey(self
, K
):
449 return K
.lower() in self
._reserved
452 def set(self
, key
, val
, coded_val
,
453 LegalChars
=_LegalChars
,
454 idmap
=_idmap
, translate
=string
.translate
):
455 # First we verify that the key isn't a reserved word
456 # Second we make sure it only contains legal characters
457 if key
.lower() in self
._reserved
:
458 raise CookieError("Attempt to set a reserved key: %s" % key
)
459 if "" != translate(key
, idmap
, LegalChars
):
460 raise CookieError("Illegal key value: %s" % key
)
462 # It's a good key, so save it.
465 self
.coded_value
= coded_val
468 def output(self
, attrs
=None, header
= "Set-Cookie:"):
469 return "%s %s" % ( header
, self
.OutputString(attrs
) )
474 return '<%s: %s=%s>' % (self
.__class
__.__name
__,
475 self
.key
, repr(self
.value
) )
477 def js_output(self
, attrs
=None):
480 <script type="text/javascript">
482 document.cookie = \"%s\";
485 """ % ( self
.OutputString(attrs
).replace('"',r
'\"'), )
488 def OutputString(self
, attrs
=None):
489 # Build up our result
494 # First, the key=value pair
495 RA("%s=%s" % (self
.key
, self
.coded_value
))
497 # Now add any defined attributes
499 attrs
= self
._reserved
504 if K
not in attrs
: continue
505 if K
== "expires" and type(V
) == type(1):
506 RA("%s=%s" % (self
._reserved
[K
], _getdate(V
)))
507 elif K
== "max-age" and type(V
) == type(1):
508 RA("%s=%d" % (self
._reserved
[K
], V
))
510 RA(str(self
._reserved
[K
]))
511 elif K
== "httponly":
512 RA(str(self
._reserved
[K
]))
514 RA("%s=%s" % (self
._reserved
[K
], V
))
517 return _semispacejoin(result
)
524 # Pattern for finding cookie
526 # This used to be strict parsing based on the RFC2109 and RFC2068
527 # specifications. I have since discovered that MSIE 3.0x doesn't
528 # follow the character rules outlined in those specs. As a
529 # result, the parsing rules here are less strict.
532 _LegalCharsPatt
= r
"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"
533 _CookiePattern
= re
.compile(
534 r
"(?x)" # This is a Verbose pattern
535 r
"(?P<key>" # Start of group 'key'
536 ""+ _LegalCharsPatt
+"+?" # Any word of at least one letter, nongreedy
537 r
")" # End of group 'key'
538 r
"\s*=\s*" # Equal Sign
539 r
"(?P<val>" # Start of group 'val'
540 r
'"(?:[^\\"]|\\.)*"' # Any doublequoted string
542 r
"\w{3},\s[\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr
544 ""+ _LegalCharsPatt
+"*" # Any word or empty string
545 r
")" # End of group 'val'
546 r
"\s*;?" # Probably ending in a semi-colon
550 # At long last, here is the cookie class.
551 # Using this class is almost just like using a dictionary.
552 # See this module's docstring for example usage.
554 class BaseCookie(dict):
555 # A container class for a set of Morsels
558 def value_decode(self
, val
):
559 """real_value, coded_value = value_decode(STRING)
560 Called prior to setting a cookie's value from the network
561 representation. The VALUE is the value read from HTTP
563 Override this function to modify the behavior of cookies.
568 def value_encode(self
, val
):
569 """real_value, coded_value = value_encode(VALUE)
570 Called prior to setting a cookie's value from the dictionary
571 representation. The VALUE is the value being assigned.
572 Override this function to modify the behavior of cookies.
575 return strval
, strval
578 def __init__(self
, input=None):
579 if input: self
.load(input)
582 def __set(self
, key
, real_value
, coded_value
):
583 """Private method for setting a cookie's value"""
584 M
= self
.get(key
, Morsel())
585 M
.set(key
, real_value
, coded_value
)
586 dict.__setitem
__(self
, key
, M
)
589 def __setitem__(self
, key
, value
):
590 """Dictionary style assignment."""
591 rval
, cval
= self
.value_encode(value
)
592 self
.__set
(key
, rval
, cval
)
595 def output(self
, attrs
=None, header
="Set-Cookie:", sep
="\015\012"):
596 """Return a string suitable for HTTP."""
601 result
.append( V
.output(attrs
, header
) )
602 return sep
.join(result
)
612 L
.append( '%s=%s' % (K
,repr(V
.value
) ) )
613 return '<%s: %s>' % (self
.__class
__.__name
__, _spacejoin(L
))
615 def js_output(self
, attrs
=None):
616 """Return a string suitable for JavaScript."""
621 result
.append( V
.js_output(attrs
) )
622 return _nulljoin(result
)
625 def load(self
, rawdata
):
626 """Load cookies from a string (presumably HTTP_COOKIE) or
627 from a dictionary. Loading cookies from a dictionary 'd'
628 is equivalent to calling:
629 map(Cookie.__setitem__, d.keys(), d.values())
631 if type(rawdata
) == type(""):
632 self
.__ParseString
(rawdata
)
634 # self.update() wouldn't call our custom __setitem__
635 for k
, v
in rawdata
.items():
640 def __ParseString(self
, str, patt
=_CookiePattern
):
641 i
= 0 # Our starting point
642 n
= len(str) # Length of string
643 M
= None # current morsel
646 # Start looking for a cookie
647 match
= patt
.search(str, i
)
648 if not match
: break # No more cookies
650 K
,V
= match
.group("key"), match
.group("val")
653 # Parse the key, value in case it's metainfo
655 # We ignore attributes which pertain to the cookie
656 # mechanism as a whole. See RFC 2109.
657 # (Does anyone care?)
660 elif K
.lower() in Morsel
._reserved
:
664 rval
, cval
= self
.value_decode(V
)
665 self
.__set
(K
, rval
, cval
)
668 # end BaseCookie class
670 class SimpleCookie(BaseCookie
):
672 SimpleCookie supports strings as cookie values. When setting
673 the value using the dictionary assignment notation, SimpleCookie
674 calls the builtin str() to convert the value to a string. Values
675 received from HTTP are kept as strings.
677 def value_decode(self
, val
):
678 return _unquote( val
), val
679 def value_encode(self
, val
):
681 return strval
, _quote( strval
)
684 class SerialCookie(BaseCookie
):
686 SerialCookie supports arbitrary objects as cookie values. All
687 values are serialized (using cPickle) before being sent to the
688 client. All incoming values are assumed to be valid Pickle
689 representations. IF AN INCOMING VALUE IS NOT IN A VALID PICKLE
690 FORMAT, THEN AN EXCEPTION WILL BE RAISED.
692 Note: Large cookie values add overhead because they must be
693 retransmitted on every HTTP transaction.
695 Note: HTTP has a 2k limit on the size of a cookie. This class
696 does not check for this limit, so be careful!!!
698 def __init__(self
, input=None):
699 warnings
.warn("SerialCookie class is insecure; do not use it",
701 BaseCookie
.__init
__(self
, input)
703 def value_decode(self
, val
):
704 # This could raise an exception!
705 return loads( _unquote(val
) ), val
706 def value_encode(self
, val
):
707 return val
, _quote( dumps(val
) )
710 class SmartCookie(BaseCookie
):
712 SmartCookie supports arbitrary objects as cookie values. If the
713 object is a string, then it is quoted. If the object is not a
714 string, however, then SmartCookie will use cPickle to serialize
715 the object into a string representation.
717 Note: Large cookie values add overhead because they must be
718 retransmitted on every HTTP transaction.
720 Note: HTTP has a 2k limit on the size of a cookie. This class
721 does not check for this limit, so be careful!!!
723 def __init__(self
, input=None):
724 warnings
.warn("Cookie/SmartCookie class is insecure; do not use it",
726 BaseCookie
.__init
__(self
, input)
728 def value_decode(self
, val
):
729 strval
= _unquote(val
)
731 return loads(strval
), val
734 def value_encode(self
, val
):
735 if type(val
) == type(""):
736 return val
, _quote(val
)
738 return val
, _quote( dumps(val
) )
742 ###########################################################
743 # Backwards Compatibility: Don't break any existing code!
745 # We provide Cookie() as an alias for SmartCookie()
749 ###########################################################
752 import doctest
, Cookie
753 return doctest
.testmod(Cookie
)
755 if __name__
== "__main__":