cookie.py
来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 743 行 · 第 1/2 页
PY
743 行
# The _getdate() routine is used to set the expiration time in# the cookie's HTTP header. By default, _getdate() returns the# current time in the appropriate "expires" format for a# Set-Cookie header. The one optional argument is an offset from# now, in seconds. For example, an offset of -3600 means "one hour ago".# The offset may be a floating point number.#_weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']_monthname = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']def _getdate(future=0, weekdayname=_weekdayname, monthname=_monthname): from time import gmtime, time now = time() year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future) return "%s, %02d-%3s-%4d %02d:%02d:%02d GMT" % \ (weekdayname[wd], day, monthname[month], year, hh, mm, ss)## A class to hold ONE key,value pair.# In a cookie, each such pair may have several attributes.# so this class is used to keep the attributes associated# with the appropriate key,value pair.# This class also includes a coded_value attribute, which# is used to hold the network representation of the# value. This is most useful when Python objects are# pickled for network transit.#class Morsel(UserDict): # RFC 2109 lists these attributes as reserved: # path comment domain # max-age secure version # # For historical reasons, these attributes are also reserved: # expires # # This dictionary provides a mapping from the lowercase # variant on the left to the appropriate traditional # formatting on the right. _reserved = { "expires" : "expires", "path" : "Path", "comment" : "Comment", "domain" : "Domain", "max-age" : "Max-Age", "secure" : "secure", "version" : "Version", } _reserved_keys = _reserved.keys() def __init__(self): # Set defaults self.key = self.value = self.coded_value = None UserDict.__init__(self) # Set default attributes for K in self._reserved_keys: UserDict.__setitem__(self, K, "") # end __init__ def __setitem__(self, K, V): K = string.lower(K) if not K in self._reserved_keys: raise CookieError("Invalid Attribute %s" % K) UserDict.__setitem__(self, K, V) # end __setitem__ def isReservedKey(self, K): return string.lower(K) in self._reserved_keys # end isReservedKey def set(self, key, val, coded_val, LegalChars=_LegalChars, idmap=string._idmap, translate=string.translate ): # First we verify that the key isn't a reserved word # Second we make sure it only contains legal characters if string.lower(key) in self._reserved_keys: raise CookieError("Attempt to set a reserved key: %s" % key) if "" != translate(key, idmap, LegalChars): raise CookieError("Illegal key value: %s" % key) # It's a good key, so save it. self.key = key self.value = val self.coded_value = coded_val # end set def output(self, attrs=None, header = "Set-Cookie:"): return "%s %s" % ( header, self.OutputString(attrs) ) __str__ = output def __repr__(self): return '<%s: %s=%s>' % (self.__class__.__name__, self.key, repr(self.value) ) def js_output(self, attrs=None): # Print javascript return """ <SCRIPT LANGUAGE="JavaScript"> <!-- begin hiding document.cookie = \"%s\" // end hiding --> </script> """ % ( self.OutputString(attrs), ) # end js_output() def OutputString(self, attrs=None): # Build up our result # result = [] RA = result.append # First, the key=value pair RA("%s=%s;" % (self.key, self.coded_value)) # Now add any defined attributes if attrs is None: attrs = self._reserved_keys items = self.items() items.sort() for K,V in items: if V == "": continue if K not in attrs: continue if K == "expires" and type(V) == type(1): RA("%s=%s;" % (self._reserved[K], _getdate(V))) elif K == "max-age" and type(V) == type(1): RA("%s=%d;" % (self._reserved[K], V)) elif K == "secure": RA("%s;" % self._reserved[K]) else: RA("%s=%s;" % (self._reserved[K], V)) # Return the result return string.join(result, " ") # end OutputString# end Morsel class## Pattern for finding cookie## This used to be strict parsing based on the RFC2109 and RFC2068# specifications. I have since discovered that MSIE 3.0x doesn't# follow the character rules outlined in those specs. As a# result, the parsing rules here are less strict.#_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"_CookiePattern = re.compile( r"(?x)" # This is a Verbose pattern r"(?P<key>" # Start of group 'key' ""+ _LegalCharsPatt +"+?" # Any word of at least one letter, nongreedy r")" # End of group 'key' r"\s*=\s*" # Equal Sign r"(?P<val>" # Start of group 'val' r'"(?:[^\\"]|\\.)*"' # Any doublequoted string r"|" # or ""+ _LegalCharsPatt +"*" # Any word or empty string r")" # End of group 'val' r"\s*;?" # Probably ending in a semi-colon )# At long last, here is the cookie class.# Using this class is almost just like using a dictionary.# See this module's docstring for example usage.#class BaseCookie(UserDict): # A container class for a set of Morsels # def value_decode(self, val): """real_value, coded_value = value_decode(STRING) Called prior to setting a cookie's value from the network representation. The VALUE is the value read from HTTP header. Override this function to modify the behavior of cookies. """ return val, val # end value_encode def value_encode(self, val): """real_value, coded_value = value_encode(VALUE) Called prior to setting a cookie's value from the dictionary representation. The VALUE is the value being assigned. Override this function to modify the behavior of cookies. """ strval = str(val) return strval, strval # end value_encode def __init__(self, input=None): UserDict.__init__(self) if input: self.load(input) # end __init__ def __set(self, key, real_value, coded_value): """Private method for setting a cookie's value""" M = self.get(key, Morsel()) M.set(key, real_value, coded_value) UserDict.__setitem__(self, key, M) # end __set def __setitem__(self, key, value): """Dictionary style assignment.""" rval, cval = self.value_encode(value) self.__set(key, rval, cval) # end __setitem__ def output(self, attrs=None, header="Set-Cookie:", sep="\n"): """Return a string suitable for HTTP.""" result = [] items = self.items() items.sort() for K,V in items: result.append( V.output(attrs, header) ) return string.join(result, sep) # end output __str__ = output def __repr__(self): L = [] items = self.items() items.sort() for K,V in items: L.append( '%s=%s' % (K,repr(V.value) ) ) return '<%s: %s>' % (self.__class__.__name__, string.join(L)) def js_output(self, attrs=None): """Return a string suitable for JavaScript.""" result = [] items = self.items() items.sort() for K,V in items: result.append( V.js_output(attrs) ) return string.join(result, "") # end js_output def load(self, rawdata): """Load cookies from a string (presumably HTTP_COOKIE) or from a dictionary. Loading cookies from a dictionary 'd' is equivalent to calling: map(Cookie.__setitem__, d.keys(), d.values()) """ if type(rawdata) == type(""): self.__ParseString(rawdata) else: self.update(rawdata) return # end load() def __ParseString(self, str, patt=_CookiePattern): i = 0 # Our starting point n = len(str) # Length of string M = None # current morsel while 0 <= i < n: # Start looking for a cookie match = patt.search(str, i) if not match: break # No more cookies K,V = match.group("key"), match.group("val") i = match.end(0) # Parse the key, value in case it's metainfo if K[0] == "$": # We ignore attributes which pertain to the cookie # mechanism as a whole. See RFC 2109. # (Does anyone care?) if M: M[ K[1:] ] = V elif string.lower(K) in Morsel._reserved_keys: if M: M[ K ] = _unquote(V) else: rval, cval = self.value_decode(V) self.__set(K, rval, cval) M = self[K] # end __ParseString# end BaseCookie classclass SimpleCookie(BaseCookie): """SimpleCookie SimpleCookie supports strings as cookie values. When setting the value using the dictionary assignment notation, SimpleCookie calls the builtin str() to convert the value to a string. Values received from HTTP are kept as strings. """ def value_decode(self, val): return _unquote( val ), val def value_encode(self, val): strval = str(val) return strval, _quote( strval )# end SimpleCookieclass SerialCookie(BaseCookie): """SerialCookie SerialCookie supports arbitrary objects as cookie values. All values are serialized (using cPickle) before being sent to the client. All incoming values are assumed to be valid Pickle representations. IF AN INCOMING VALUE IS NOT IN A VALID PICKLE FORMAT, THEN AN EXCEPTION WILL BE RAISED. Note: Large cookie values add overhead because they must be retransmitted on every HTTP transaction. Note: HTTP has a 2k limit on the size of a cookie. This class does not check for this limit, so be careful!!! """ def value_decode(self, val): # This could raise an exception! return loads( _unquote(val) ), val def value_encode(self, val): return val, _quote( dumps(val) )# end SerialCookieclass SmartCookie(BaseCookie): """SmartCookie SmartCookie supports arbitrary objects as cookie values. If the object is a string, then it is quoted. If the object is not a string, however, then SmartCookie will use cPickle to serialize the object into a string representation. Note: Large cookie values add overhead because they must be retransmitted on every HTTP transaction. Note: HTTP has a 2k limit on the size of a cookie. This class does not check for this limit, so be careful!!! """ def value_decode(self, val): strval = _unquote(val) try: return loads(strval), val except: return strval, val def value_encode(self, val): if type(val) == type(""): return val, _quote(val) else: return val, _quote( dumps(val) )# end SmartCookie############################################################ Backwards Compatibility: Don't break any existing code!# We provide Cookie() as an alias for SmartCookie()Cookie = SmartCookie############################################################def _test(): import doctest, Cookie return doctest.testmod(Cookie)if __name__ == "__main__": _test()#Local Variables:#tab-width: 4#end:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?