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