Cookie.py (11241B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\Cookie.py 2 import string 3 try: 4 from cPickle import dumps, loads 5 except ImportError: 6 from pickle import dumps, loads 7 8 import re, warnings 9 __all__ = ['CookieError', 10 'BaseCookie', 11 'SimpleCookie', 12 'SerialCookie', 13 'SmartCookie', 14 'Cookie'] 15 _nulljoin = ''.join 16 _semispacejoin = '; '.join 17 _spacejoin = ' '.join 18 19 class CookieError(Exception): 20 pass 21 22 23 _LegalChars = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~" 24 _Translator = {'\x00': '\\000', 25 '\x01': '\\001', 26 '\x02': '\\002', 27 '\x03': '\\003', 28 '\x04': '\\004', 29 '\x05': '\\005', 30 '\x06': '\\006', 31 '\x07': '\\007', 32 '\x08': '\\010', 33 '\t': '\\011', 34 '\n': '\\012', 35 '\x0b': '\\013', 36 '\x0c': '\\014', 37 '\r': '\\015', 38 '\x0e': '\\016', 39 '\x0f': '\\017', 40 '\x10': '\\020', 41 '\x11': '\\021', 42 '\x12': '\\022', 43 '\x13': '\\023', 44 '\x14': '\\024', 45 '\x15': '\\025', 46 '\x16': '\\026', 47 '\x17': '\\027', 48 '\x18': '\\030', 49 '\x19': '\\031', 50 '\x1a': '\\032', 51 '\x1b': '\\033', 52 '\x1c': '\\034', 53 '\x1d': '\\035', 54 '\x1e': '\\036', 55 '\x1f': '\\037', 56 '"': '\\"', 57 '\\': '\\\\', 58 '\x7f': '\\177', 59 '\x80': '\\200', 60 '\x81': '\\201', 61 '\x82': '\\202', 62 '\x83': '\\203', 63 '\x84': '\\204', 64 '\x85': '\\205', 65 '\x86': '\\206', 66 '\x87': '\\207', 67 '\x88': '\\210', 68 '\x89': '\\211', 69 '\x8a': '\\212', 70 '\x8b': '\\213', 71 '\x8c': '\\214', 72 '\x8d': '\\215', 73 '\x8e': '\\216', 74 '\x8f': '\\217', 75 '\x90': '\\220', 76 '\x91': '\\221', 77 '\x92': '\\222', 78 '\x93': '\\223', 79 '\x94': '\\224', 80 '\x95': '\\225', 81 '\x96': '\\226', 82 '\x97': '\\227', 83 '\x98': '\\230', 84 '\x99': '\\231', 85 '\x9a': '\\232', 86 '\x9b': '\\233', 87 '\x9c': '\\234', 88 '\x9d': '\\235', 89 '\x9e': '\\236', 90 '\x9f': '\\237', 91 '\xa0': '\\240', 92 '\xa1': '\\241', 93 '\xa2': '\\242', 94 '\xa3': '\\243', 95 '\xa4': '\\244', 96 '\xa5': '\\245', 97 '\xa6': '\\246', 98 '\xa7': '\\247', 99 '\xa8': '\\250', 100 '\xa9': '\\251', 101 '\xaa': '\\252', 102 '\xab': '\\253', 103 '\xac': '\\254', 104 '\xad': '\\255', 105 '\xae': '\\256', 106 '\xaf': '\\257', 107 '\xb0': '\\260', 108 '\xb1': '\\261', 109 '\xb2': '\\262', 110 '\xb3': '\\263', 111 '\xb4': '\\264', 112 '\xb5': '\\265', 113 '\xb6': '\\266', 114 '\xb7': '\\267', 115 '\xb8': '\\270', 116 '\xb9': '\\271', 117 '\xba': '\\272', 118 '\xbb': '\\273', 119 '\xbc': '\\274', 120 '\xbd': '\\275', 121 '\xbe': '\\276', 122 '\xbf': '\\277', 123 '\xc0': '\\300', 124 '\xc1': '\\301', 125 '\xc2': '\\302', 126 '\xc3': '\\303', 127 '\xc4': '\\304', 128 '\xc5': '\\305', 129 '\xc6': '\\306', 130 '\xc7': '\\307', 131 '\xc8': '\\310', 132 '\xc9': '\\311', 133 '\xca': '\\312', 134 '\xcb': '\\313', 135 '\xcc': '\\314', 136 '\xcd': '\\315', 137 '\xce': '\\316', 138 '\xcf': '\\317', 139 '\xd0': '\\320', 140 '\xd1': '\\321', 141 '\xd2': '\\322', 142 '\xd3': '\\323', 143 '\xd4': '\\324', 144 '\xd5': '\\325', 145 '\xd6': '\\326', 146 '\xd7': '\\327', 147 '\xd8': '\\330', 148 '\xd9': '\\331', 149 '\xda': '\\332', 150 '\xdb': '\\333', 151 '\xdc': '\\334', 152 '\xdd': '\\335', 153 '\xde': '\\336', 154 '\xdf': '\\337', 155 '\xe0': '\\340', 156 '\xe1': '\\341', 157 '\xe2': '\\342', 158 '\xe3': '\\343', 159 '\xe4': '\\344', 160 '\xe5': '\\345', 161 '\xe6': '\\346', 162 '\xe7': '\\347', 163 '\xe8': '\\350', 164 '\xe9': '\\351', 165 '\xea': '\\352', 166 '\xeb': '\\353', 167 '\xec': '\\354', 168 '\xed': '\\355', 169 '\xee': '\\356', 170 '\xef': '\\357', 171 '\xf0': '\\360', 172 '\xf1': '\\361', 173 '\xf2': '\\362', 174 '\xf3': '\\363', 175 '\xf4': '\\364', 176 '\xf5': '\\365', 177 '\xf6': '\\366', 178 '\xf7': '\\367', 179 '\xf8': '\\370', 180 '\xf9': '\\371', 181 '\xfa': '\\372', 182 '\xfb': '\\373', 183 '\xfc': '\\374', 184 '\xfd': '\\375', 185 '\xfe': '\\376', 186 '\xff': '\\377'} 187 _idmap = ''.join((chr(x) for x in xrange(256))) 188 189 def _quote(str, LegalChars = _LegalChars, idmap = _idmap, translate = string.translate): 190 if '' == translate(str, idmap, LegalChars): 191 return str 192 else: 193 return '"' + _nulljoin(map(_Translator.get, str, str)) + '"' 194 195 196 _OctalPatt = re.compile('\\\\[0-3][0-7][0-7]') 197 _QuotePatt = re.compile('[\\\\].') 198 199 def _unquote(str): 200 if len(str) < 2: 201 return str 202 if str[0] != '"' or str[-1] != '"': 203 return str 204 str = str[1:-1] 205 i = 0 206 n = len(str) 207 res = [] 208 while 0 <= i < n: 209 Omatch = _OctalPatt.search(str, i) 210 Qmatch = _QuotePatt.search(str, i) 211 if not Omatch and not Qmatch: 212 res.append(str[i:]) 213 break 214 j = k = -1 215 if Omatch: 216 j = Omatch.start(0) 217 if Qmatch: 218 k = Qmatch.start(0) 219 if Qmatch and (not Omatch or k < j): 220 res.append(str[i:k]) 221 res.append(str[k + 1]) 222 i = k + 2 223 else: 224 res.append(str[i:j]) 225 res.append(chr(int(str[j + 1:j + 4], 8))) 226 i = j + 4 227 228 return _nulljoin(res) 229 230 231 _weekdayname = ['Mon', 232 'Tue', 233 'Wed', 234 'Thu', 235 'Fri', 236 'Sat', 237 'Sun'] 238 _monthname = [None, 239 'Jan', 240 'Feb', 241 'Mar', 242 'Apr', 243 'May', 244 'Jun', 245 'Jul', 246 'Aug', 247 'Sep', 248 'Oct', 249 'Nov', 250 'Dec'] 251 252 def _getdate(future = 0, weekdayname = _weekdayname, monthname = _monthname): 253 from time import gmtime, time 254 now = time() 255 year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future) 256 return '%s, %02d-%3s-%4d %02d:%02d:%02d GMT' % (weekdayname[wd], 257 day, 258 monthname[month], 259 year, 260 hh, 261 mm, 262 ss) 263 264 265 class Morsel(dict): 266 _reserved = {'expires': 'expires', 267 'path': 'Path', 268 'comment': 'Comment', 269 'domain': 'Domain', 270 'max-age': 'Max-Age', 271 'secure': 'secure', 272 'httponly': 'httponly', 273 'version': 'Version'} 274 275 def __init__(self): 276 self.key = self.value = self.coded_value = None 277 for K in self._reserved: 278 dict.__setitem__(self, K, '') 279 280 def __setitem__(self, K, V): 281 K = K.lower() 282 if K not in self._reserved: 283 raise CookieError('Invalid Attribute %s' % K) 284 dict.__setitem__(self, K, V) 285 286 def isReservedKey(self, K): 287 return K.lower() in self._reserved 288 289 def set(self, key, val, coded_val, LegalChars = _LegalChars, idmap = _idmap, translate = string.translate): 290 if key.lower() in self._reserved: 291 raise CookieError('Attempt to set a reserved key: %s' % key) 292 if '' != translate(key, idmap, LegalChars): 293 raise CookieError('Illegal key value: %s' % key) 294 self.key = key 295 self.value = val 296 self.coded_value = coded_val 297 298 def output(self, attrs = None, header = 'Set-Cookie:'): 299 return '%s %s' % (header, self.OutputString(attrs)) 300 301 __str__ = output 302 303 def __repr__(self): 304 return '<%s: %s=%s>' % (self.__class__.__name__, self.key, repr(self.value)) 305 306 def js_output(self, attrs = None): 307 return '\n <script type="text/javascript">\n <!-- begin hiding\n document.cookie = "%s";\n // end hiding -->\n </script>\n ' % (self.OutputString(attrs).replace('"', '\\"'),) 308 309 def OutputString(self, attrs = None): 310 result = [] 311 RA = result.append 312 RA('%s=%s' % (self.key, self.coded_value)) 313 if attrs is None: 314 attrs = self._reserved 315 items = self.items() 316 items.sort() 317 for K, V in items: 318 if V == '': 319 continue 320 if K not in attrs: 321 continue 322 if K == 'expires' and type(V) == type(1): 323 RA('%s=%s' % (self._reserved[K], _getdate(V))) 324 elif K == 'max-age' and type(V) == type(1): 325 RA('%s=%d' % (self._reserved[K], V)) 326 elif K == 'secure': 327 RA(str(self._reserved[K])) 328 elif K == 'httponly': 329 RA(str(self._reserved[K])) 330 else: 331 RA('%s=%s' % (self._reserved[K], V)) 332 333 return _semispacejoin(result) 334 335 336 _LegalCharsPatt = "[\\w\\d!#%&'~_`><@,:/\\$\\*\\+\\-\\.\\^\\|\\)\\(\\?\\}\\{\\=]" 337 _CookiePattern = re.compile('(?x)(?P<key>' + _LegalCharsPatt + '+?)\\s*=\\s*(?P<val>"(?:[^\\\\"]|\\\\.)*"|\\w{3},\\s[\\w\\d-]{9,11}\\s[\\d:]{8}\\sGMT|' + _LegalCharsPatt + '*)\\s*;?') 338 339 class BaseCookie(dict): 340 341 def value_decode(self, val): 342 return (val, val) 343 344 def value_encode(self, val): 345 strval = str(val) 346 return (strval, strval) 347 348 def __init__(self, input = None): 349 if input: 350 self.load(input) 351 352 def __set(self, key, real_value, coded_value): 353 M = self.get(key, Morsel()) 354 M.set(key, real_value, coded_value) 355 dict.__setitem__(self, key, M) 356 357 def __setitem__(self, key, value): 358 rval, cval = self.value_encode(value) 359 self.__set(key, rval, cval) 360 361 def output(self, attrs = None, header = 'Set-Cookie:', sep = '\r\n'): 362 result = [] 363 items = self.items() 364 items.sort() 365 for K, V in items: 366 result.append(V.output(attrs, header)) 367 368 return sep.join(result) 369 370 __str__ = output 371 372 def __repr__(self): 373 L = [] 374 items = self.items() 375 items.sort() 376 for K, V in items: 377 L.append('%s=%s' % (K, repr(V.value))) 378 379 return '<%s: %s>' % (self.__class__.__name__, _spacejoin(L)) 380 381 def js_output(self, attrs = None): 382 result = [] 383 items = self.items() 384 items.sort() 385 for K, V in items: 386 result.append(V.js_output(attrs)) 387 388 return _nulljoin(result) 389 390 def load(self, rawdata): 391 if type(rawdata) == type(''): 392 self.__ParseString(rawdata) 393 else: 394 for k, v in rawdata.items(): 395 self[k] = v 396 397 def __ParseString(self, str, patt = _CookiePattern): 398 i = 0 399 n = len(str) 400 M = None 401 while 0 <= i < n: 402 match = patt.search(str, i) 403 if not match: 404 break 405 K, V = match.group('key'), match.group('val') 406 i = match.end(0) 407 if K[0] == '$': 408 if M: 409 M[K[1:]] = V 410 elif K.lower() in Morsel._reserved: 411 if M: 412 M[K] = _unquote(V) 413 else: 414 rval, cval = self.value_decode(V) 415 self.__set(K, rval, cval) 416 M = self[K] 417 418 419 class SimpleCookie(BaseCookie): 420 421 def value_decode(self, val): 422 return (_unquote(val), val) 423 424 def value_encode(self, val): 425 strval = str(val) 426 return (strval, _quote(strval)) 427 428 429 class SerialCookie(BaseCookie): 430 431 def __init__(self, input = None): 432 warnings.warn('SerialCookie class is insecure; do not use it', DeprecationWarning) 433 BaseCookie.__init__(self, input) 434 435 def value_decode(self, val): 436 return (loads(_unquote(val)), val) 437 438 def value_encode(self, val): 439 return (val, _quote(dumps(val))) 440 441 442 class SmartCookie(BaseCookie): 443 444 def __init__(self, input = None): 445 warnings.warn('Cookie/SmartCookie class is insecure; do not use it', DeprecationWarning) 446 BaseCookie.__init__(self, input) 447 448 def value_decode(self, val): 449 strval = _unquote(val) 450 try: 451 return (loads(strval), val) 452 except: 453 return (strval, val) 454 455 def value_encode(self, val): 456 if type(val) == type(''): 457 return (val, _quote(val)) 458 else: 459 return (val, _quote(dumps(val))) 460 461 462 Cookie = SmartCookie 463 464 def _test(): 465 import doctest, Cookie 466 return doctest.testmod(Cookie) 467 468 469 if __name__ == '__main__': 470 _test()