NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

httputil.py (9473B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\lib\httputil.py
      2 from binascii import b2a_base64
      3 from cherrypy._cpcompat import BaseHTTPRequestHandler, HTTPDate, ntob, ntou, reversed, sorted
      4 from cherrypy._cpcompat import basestring, iteritems, unicodestr, unquote_qs
      5 response_codes = BaseHTTPRequestHandler.responses.copy()
      6 response_codes[500] = ('Internal Server Error', 'The server encountered an unexpected condition which prevented it from fulfilling the request.')
      7 response_codes[503] = ('Service Unavailable', 'The server is currently unable to handle the request due to a temporary overloading or maintenance of the server.')
      8 import re
      9 import urllib
     10 
     11 def urljoin(*atoms):
     12     url = '/'.join([ x for x in atoms if x ])
     13     while '//' in url:
     14         url = url.replace('//', '/')
     15 
     16     return url or '/'
     17 
     18 
     19 def protocol_from_http(protocol_str):
     20     return (int(protocol_str[5]), int(protocol_str[7]))
     21 
     22 
     23 def get_ranges(headervalue, content_length):
     24     if not headervalue:
     25         return None
     26     result = []
     27     bytesunit, byteranges = headervalue.split('=', 1)
     28     for brange in byteranges.split(','):
     29         start, stop = [ x.strip() for x in brange.split('-', 1) ]
     30         if start:
     31             if not stop:
     32                 stop = content_length - 1
     33             start, stop = int(start), int(stop)
     34             if start >= content_length:
     35                 continue
     36             if stop < start:
     37                 return None
     38             result.append((start, stop + 1))
     39         else:
     40             if not stop:
     41                 return None
     42             result.append((content_length - int(stop), content_length))
     43 
     44     return result
     45 
     46 
     47 class HeaderElement(object):
     48 
     49     def __init__(self, value, params = None):
     50         self.value = value
     51         if params is None:
     52             params = {}
     53         self.params = params
     54 
     55     def __cmp__(self, other):
     56         return cmp(self.value, other.value)
     57 
     58     def __str__(self):
     59         p = [ ';%s=%s' % (k, v) for k, v in iteritems(self.params) ]
     60         return '%s%s' % (self.value, ''.join(p))
     61 
     62     def __unicode__(self):
     63         return ntou(self.__str__())
     64 
     65     def parse(elementstr):
     66         atoms = [ x.strip() for x in elementstr.split(';') if x.strip() ]
     67         if not atoms:
     68             initial_value = ''
     69         else:
     70             initial_value = atoms.pop(0).strip()
     71         params = {}
     72         for atom in atoms:
     73             atom = [ x.strip() for x in atom.split('=', 1) if x.strip() ]
     74             key = atom.pop(0)
     75             if atom:
     76                 val = atom[0]
     77             else:
     78                 val = ''
     79             params[key] = val
     80 
     81         return (initial_value, params)
     82 
     83     parse = staticmethod(parse)
     84 
     85     def from_str(cls, elementstr):
     86         ival, params = cls.parse(elementstr)
     87         return cls(ival, params)
     88 
     89     from_str = classmethod(from_str)
     90 
     91 
     92 q_separator = re.compile('; *q *=')
     93 
     94 class AcceptElement(HeaderElement):
     95 
     96     def from_str(cls, elementstr):
     97         qvalue = None
     98         atoms = q_separator.split(elementstr, 1)
     99         media_range = atoms.pop(0).strip()
    100         if atoms:
    101             qvalue = HeaderElement.from_str(atoms[0].strip())
    102         media_type, params = cls.parse(media_range)
    103         if qvalue is not None:
    104             params['q'] = qvalue
    105         return cls(media_type, params)
    106 
    107     from_str = classmethod(from_str)
    108 
    109     def qvalue(self):
    110         val = self.params.get('q', '1')
    111         if isinstance(val, HeaderElement):
    112             val = val.value
    113         return float(val)
    114 
    115     qvalue = property(qvalue, doc='The qvalue, or priority, of this value.')
    116 
    117     def __cmp__(self, other):
    118         diff = cmp(self.qvalue, other.qvalue)
    119         if diff == 0:
    120             diff = cmp(str(self), str(other))
    121         return diff
    122 
    123 
    124 def header_elements(fieldname, fieldvalue):
    125     if not fieldvalue:
    126         return []
    127     result = []
    128     for element in fieldvalue.split(','):
    129         if fieldname.startswith('Accept') or fieldname == 'TE':
    130             hv = AcceptElement.from_str(element)
    131         else:
    132             hv = HeaderElement.from_str(element)
    133         result.append(hv)
    134 
    135     return list(reversed(sorted(result)))
    136 
    137 
    138 def decode_TEXT(value):
    139     from email.Header import decode_header
    140     atoms = decode_header(value)
    141     decodedvalue = ''
    142     for atom, charset in atoms:
    143         if charset is not None:
    144             atom = atom.decode(charset)
    145         decodedvalue += atom
    146 
    147     return decodedvalue
    148 
    149 
    150 def valid_status(status):
    151     if not status:
    152         status = 200
    153     status = str(status)
    154     parts = status.split(' ', 1)
    155     if len(parts) == 1:
    156         code, = parts
    157         reason = None
    158     else:
    159         code, reason = parts
    160         reason = reason.strip()
    161     try:
    162         code = int(code)
    163     except ValueError:
    164         raise ValueError('Illegal response status from server (%s is non-numeric).' % repr(code))
    165 
    166     if code < 100 or code > 599:
    167         raise ValueError('Illegal response status from server (%s is out of range).' % repr(code))
    168     if code not in response_codes:
    169         default_reason, message = ('', '')
    170     else:
    171         default_reason, message = response_codes[code]
    172     if reason is None:
    173         reason = default_reason
    174     return (code, reason, message)
    175 
    176 
    177 def _parse_qs(qs, keep_blank_values = 0, strict_parsing = 0, encoding = 'utf-8'):
    178     pairs = [ s2 for s1 in qs.split('&') for s2 in s1.split(';') ]
    179     d = {}
    180     for name_value in pairs:
    181         if not name_value and not strict_parsing:
    182             continue
    183         nv = name_value.split('=', 1)
    184         if len(nv) != 2:
    185             if strict_parsing:
    186                 raise ValueError('bad query field: %r' % (name_value,))
    187             if keep_blank_values:
    188                 nv.append('')
    189             else:
    190                 continue
    191         if len(nv[1]) or keep_blank_values:
    192             name = unquote_qs(nv[0], encoding)
    193             value = unquote_qs(nv[1], encoding)
    194             if name in d:
    195                 if not isinstance(d[name], list):
    196                     d[name] = [d[name]]
    197                 d[name].append(value)
    198             else:
    199                 d[name] = value
    200 
    201     return d
    202 
    203 
    204 image_map_pattern = re.compile('[0-9]+,[0-9]+')
    205 
    206 def parse_query_string(query_string, keep_blank_values = True, encoding = 'utf-8'):
    207     if image_map_pattern.match(query_string):
    208         pm = query_string.split(',')
    209         pm = {'x': int(pm[0]),
    210          'y': int(pm[1])}
    211     else:
    212         pm = _parse_qs(query_string, keep_blank_values, encoding=encoding)
    213     return pm
    214 
    215 
    216 class CaseInsensitiveDict(dict):
    217 
    218     def __getitem__(self, key):
    219         return dict.__getitem__(self, str(key).title())
    220 
    221     def __setitem__(self, key, value):
    222         dict.__setitem__(self, str(key).title(), value)
    223 
    224     def __delitem__(self, key):
    225         dict.__delitem__(self, str(key).title())
    226 
    227     def __contains__(self, key):
    228         return dict.__contains__(self, str(key).title())
    229 
    230     def get(self, key, default = None):
    231         return dict.get(self, str(key).title(), default)
    232 
    233     def has_key(self, key):
    234         return dict.has_key(self, str(key).title())
    235 
    236     def update(self, E):
    237         for k in E.keys():
    238             self[str(k).title()] = E[k]
    239 
    240     def fromkeys(cls, seq, value = None):
    241         newdict = cls()
    242         for k in seq:
    243             newdict[str(k).title()] = value
    244 
    245         return newdict
    246 
    247     fromkeys = classmethod(fromkeys)
    248 
    249     def setdefault(self, key, x = None):
    250         key = str(key).title()
    251         try:
    252             return self[key]
    253         except KeyError:
    254             self[key] = x
    255             return x
    256 
    257     def pop(self, key, default):
    258         return dict.pop(self, str(key).title(), default)
    259 
    260 
    261 header_translate_table = ''.join([ chr(i) for i in xrange(256) ])
    262 header_translate_deletechars = ''.join([ chr(i) for i in xrange(32) ]) + chr(127)
    263 
    264 class HeaderMap(CaseInsensitiveDict):
    265     protocol = (1, 1)
    266     encodings = ['ISO-8859-1']
    267     use_rfc_2047 = True
    268 
    269     def elements(self, key):
    270         key = str(key).title()
    271         value = self.get(key)
    272         return header_elements(key, value)
    273 
    274     def values(self, key):
    275         return [ e.value for e in self.elements(key) ]
    276 
    277     def output(self):
    278         header_list = []
    279         for k, v in self.items():
    280             if isinstance(k, unicodestr):
    281                 k = self.encode(k)
    282             if not isinstance(v, basestring):
    283                 v = str(v)
    284             if isinstance(v, unicodestr):
    285                 v = self.encode(v)
    286             k = k.translate(header_translate_table, header_translate_deletechars)
    287             v = v.translate(header_translate_table, header_translate_deletechars)
    288             header_list.append((k, v))
    289 
    290         return header_list
    291 
    292     def encode(self, v):
    293         for enc in self.encodings:
    294             try:
    295                 return v.encode(enc)
    296             except UnicodeEncodeError:
    297                 continue
    298 
    299         if self.protocol == (1, 1) and self.use_rfc_2047:
    300             v = b2a_base64(v.encode('utf-8'))
    301             return ntob('=?utf-8?b?') + v.strip(ntob('\n')) + ntob('?=')
    302         raise ValueError('Could not encode header part %r using any of the encodings %r.' % (v, self.encodings))
    303 
    304 
    305 class Host(object):
    306     ip = '0.0.0.0'
    307     port = 80
    308     name = 'unknown.tld'
    309 
    310     def __init__(self, ip, port, name = None):
    311         self.ip = ip
    312         self.port = port
    313         if name is None:
    314             name = ip
    315         self.name = name
    316 
    317     def __repr__(self):
    318         return 'httputil.Host(%r, %r, %r)' % (self.ip, self.port, self.name)