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

cgi.py (21861B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\cgi.py
      2 __version__ = '2.6'
      3 from operator import attrgetter
      4 import sys
      5 import os
      6 import urllib
      7 import UserDict
      8 import urlparse
      9 from warnings import filterwarnings, catch_warnings, warn
     10 with catch_warnings():
     11     if sys.py3kwarning:
     12         filterwarnings('ignore', '.*mimetools has been removed', DeprecationWarning)
     13         filterwarnings('ignore', '.*rfc822 has been removed', DeprecationWarning)
     14     import mimetools
     15     import rfc822
     16 try:
     17     from cStringIO import StringIO
     18 except ImportError:
     19     from StringIO import StringIO
     20 
     21 __all__ = ['MiniFieldStorage',
     22  'FieldStorage',
     23  'FormContentDict',
     24  'SvFormContentDict',
     25  'InterpFormContentDict',
     26  'FormContent',
     27  'parse',
     28  'parse_qs',
     29  'parse_qsl',
     30  'parse_multipart',
     31  'parse_header',
     32  'print_exception',
     33  'print_environ',
     34  'print_form',
     35  'print_directory',
     36  'print_arguments',
     37  'print_environ_usage',
     38  'escape']
     39 logfile = ''
     40 logfp = None
     41 
     42 def initlog(*allargs):
     43     global logfp
     44     global log
     45     if logfile and not logfp:
     46         try:
     47             logfp = open(logfile, 'a')
     48         except IOError:
     49             pass
     50 
     51     if not logfp:
     52         log = nolog
     53     else:
     54         log = dolog
     55     log(*allargs)
     56 
     57 
     58 def dolog(fmt, *args):
     59     logfp.write(fmt % args + '\n')
     60 
     61 
     62 def nolog(*allargs):
     63     pass
     64 
     65 
     66 log = initlog
     67 maxlen = 0
     68 
     69 def parse(fp = None, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
     70     global maxlen
     71     if fp is None:
     72         fp = sys.stdin
     73     if 'REQUEST_METHOD' not in environ:
     74         environ['REQUEST_METHOD'] = 'GET'
     75     if environ['REQUEST_METHOD'] == 'POST':
     76         ctype, pdict = parse_header(environ['CONTENT_TYPE'])
     77         if ctype == 'multipart/form-data':
     78             return parse_multipart(fp, pdict)
     79         if ctype == 'application/x-www-form-urlencoded':
     80             clength = int(environ['CONTENT_LENGTH'])
     81             if maxlen and clength > maxlen:
     82                 raise ValueError, 'Maximum content length exceeded'
     83             qs = fp.read(clength)
     84         else:
     85             qs = ''
     86         if 'QUERY_STRING' in environ:
     87             if qs:
     88                 qs = qs + '&'
     89             qs = qs + environ['QUERY_STRING']
     90         elif sys.argv[1:]:
     91             if qs:
     92                 qs = qs + '&'
     93             qs = qs + sys.argv[1]
     94         environ['QUERY_STRING'] = qs
     95     elif 'QUERY_STRING' in environ:
     96         qs = environ['QUERY_STRING']
     97     else:
     98         if sys.argv[1:]:
     99             qs = sys.argv[1]
    100         else:
    101             qs = ''
    102         environ['QUERY_STRING'] = qs
    103     return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
    104 
    105 
    106 def parse_qs(qs, keep_blank_values = 0, strict_parsing = 0):
    107     warn('cgi.parse_qs is deprecated, use urlparse.parse_qs instead', PendingDeprecationWarning, 2)
    108     return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
    109 
    110 
    111 def parse_qsl(qs, keep_blank_values = 0, strict_parsing = 0):
    112     warn('cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead', PendingDeprecationWarning, 2)
    113     return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
    114 
    115 
    116 def parse_multipart(fp, pdict):
    117     boundary = ''
    118     if 'boundary' in pdict:
    119         boundary = pdict['boundary']
    120     if not valid_boundary(boundary):
    121         raise ValueError, 'Invalid boundary in multipart form: %r' % (boundary,)
    122     nextpart = '--' + boundary
    123     lastpart = '--' + boundary + '--'
    124     partdict = {}
    125     terminator = ''
    126     while terminator != lastpart:
    127         bytes = -1
    128         data = None
    129         if terminator:
    130             headers = mimetools.Message(fp)
    131             clength = headers.getheader('content-length')
    132             if clength:
    133                 try:
    134                     bytes = int(clength)
    135                 except ValueError:
    136                     pass
    137 
    138             if bytes > 0:
    139                 if maxlen and bytes > maxlen:
    140                     raise ValueError, 'Maximum content length exceeded'
    141                 data = fp.read(bytes)
    142             else:
    143                 data = ''
    144         lines = []
    145         while 1:
    146             line = fp.readline()
    147             if not line:
    148                 terminator = lastpart
    149                 break
    150             if line[:2] == '--':
    151                 terminator = line.strip()
    152                 if terminator in (nextpart, lastpart):
    153                     break
    154             lines.append(line)
    155 
    156         if data is None:
    157             continue
    158         if bytes < 0:
    159             if lines:
    160                 line = lines[-1]
    161                 if line[-2:] == '\r\n':
    162                     line = line[:-2]
    163                 elif line[-1:] == '\n':
    164                     line = line[:-1]
    165                 lines[-1] = line
    166                 data = ''.join(lines)
    167         line = headers['content-disposition']
    168         if not line:
    169             continue
    170         key, params = parse_header(line)
    171         if key != 'form-data':
    172             continue
    173         if 'name' in params:
    174             name = params['name']
    175         else:
    176             continue
    177         if name in partdict:
    178             partdict[name].append(data)
    179         else:
    180             partdict[name] = [data]
    181 
    182     return partdict
    183 
    184 
    185 def _parseparam(s):
    186     while s[:1] == ';':
    187         s = s[1:]
    188         end = s.find(';')
    189         while end > 0 and s.count('"', 0, end) % 2:
    190             end = s.find(';', end + 1)
    191 
    192         if end < 0:
    193             end = len(s)
    194         f = s[:end]
    195         yield f.strip()
    196         s = s[end:]
    197 
    198 
    199 def parse_header(line):
    200     parts = _parseparam(';' + line)
    201     key = parts.next()
    202     pdict = {}
    203     for p in parts:
    204         i = p.find('=')
    205         if i >= 0:
    206             name = p[:i].strip().lower()
    207             value = p[i + 1:].strip()
    208             if len(value) >= 2 and value[0] == value[-1] == '"':
    209                 value = value[1:-1]
    210                 value = value.replace('\\\\', '\\').replace('\\"', '"')
    211             pdict[name] = value
    212 
    213     return (key, pdict)
    214 
    215 
    216 class MiniFieldStorage():
    217     filename = None
    218     list = None
    219     type = None
    220     file = None
    221     type_options = {}
    222     disposition = None
    223     disposition_options = {}
    224     headers = {}
    225 
    226     def __init__(self, name, value):
    227         self.name = name
    228         self.value = value
    229 
    230     def __repr__(self):
    231         return 'MiniFieldStorage(%r, %r)' % (self.name, self.value)
    232 
    233 
    234 class FieldStorage():
    235 
    236     def __init__(self, fp = None, headers = None, outerboundary = '', environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
    237         method = 'GET'
    238         self.keep_blank_values = keep_blank_values
    239         self.strict_parsing = strict_parsing
    240         if 'REQUEST_METHOD' in environ:
    241             method = environ['REQUEST_METHOD'].upper()
    242         self.qs_on_post = None
    243         if method == 'GET' or method == 'HEAD':
    244             if 'QUERY_STRING' in environ:
    245                 qs = environ['QUERY_STRING']
    246             elif sys.argv[1:]:
    247                 qs = sys.argv[1]
    248             else:
    249                 qs = ''
    250             fp = StringIO(qs)
    251             if headers is None:
    252                 headers = {'content-type': 'application/x-www-form-urlencoded'}
    253         if headers is None:
    254             headers = {}
    255             if method == 'POST':
    256                 headers['content-type'] = 'application/x-www-form-urlencoded'
    257             if 'CONTENT_TYPE' in environ:
    258                 headers['content-type'] = environ['CONTENT_TYPE']
    259             if 'QUERY_STRING' in environ:
    260                 self.qs_on_post = environ['QUERY_STRING']
    261             if 'CONTENT_LENGTH' in environ:
    262                 headers['content-length'] = environ['CONTENT_LENGTH']
    263         self.fp = fp or sys.stdin
    264         self.headers = headers
    265         self.outerboundary = outerboundary
    266         cdisp, pdict = '', {}
    267         if 'content-disposition' in self.headers:
    268             cdisp, pdict = parse_header(self.headers['content-disposition'])
    269         self.disposition = cdisp
    270         self.disposition_options = pdict
    271         self.name = None
    272         if 'name' in pdict:
    273             self.name = pdict['name']
    274         self.filename = None
    275         if 'filename' in pdict:
    276             self.filename = pdict['filename']
    277         if 'content-type' in self.headers:
    278             ctype, pdict = parse_header(self.headers['content-type'])
    279         elif self.outerboundary or method != 'POST':
    280             ctype, pdict = 'text/plain', {}
    281         else:
    282             ctype, pdict = 'application/x-www-form-urlencoded', {}
    283         self.type = ctype
    284         self.type_options = pdict
    285         self.innerboundary = ''
    286         if 'boundary' in pdict:
    287             self.innerboundary = pdict['boundary']
    288         clen = -1
    289         if 'content-length' in self.headers:
    290             try:
    291                 clen = int(self.headers['content-length'])
    292             except ValueError:
    293                 pass
    294 
    295             if maxlen and clen > maxlen:
    296                 raise ValueError, 'Maximum content length exceeded'
    297         self.length = clen
    298         self.list = self.file = None
    299         self.done = 0
    300         if ctype == 'application/x-www-form-urlencoded':
    301             self.read_urlencoded()
    302         elif ctype[:10] == 'multipart/':
    303             self.read_multi(environ, keep_blank_values, strict_parsing)
    304         else:
    305             self.read_single()
    306 
    307     def __repr__(self):
    308         return 'FieldStorage(%r, %r, %r)' % (self.name, self.filename, self.value)
    309 
    310     def __iter__(self):
    311         return iter(self.keys())
    312 
    313     def __getattr__(self, name):
    314         if name != 'value':
    315             raise AttributeError, name
    316         if self.file:
    317             self.file.seek(0)
    318             value = self.file.read()
    319             self.file.seek(0)
    320         elif self.list is not None:
    321             value = self.list
    322         else:
    323             value = None
    324         return value
    325 
    326     def __getitem__(self, key):
    327         if self.list is None:
    328             raise TypeError, 'not indexable'
    329         found = []
    330         for item in self.list:
    331             if item.name == key:
    332                 found.append(item)
    333 
    334         if not found:
    335             raise KeyError, key
    336         if len(found) == 1:
    337             return found[0]
    338         else:
    339             return found
    340 
    341     def getvalue(self, key, default = None):
    342         if key in self:
    343             value = self[key]
    344             if type(value) is type([]):
    345                 return map(attrgetter('value'), value)
    346             else:
    347                 return value.value
    348         else:
    349             return default
    350 
    351     def getfirst(self, key, default = None):
    352         if key in self:
    353             value = self[key]
    354             if type(value) is type([]):
    355                 return value[0].value
    356             else:
    357                 return value.value
    358         else:
    359             return default
    360 
    361     def getlist(self, key):
    362         if key in self:
    363             value = self[key]
    364             if type(value) is type([]):
    365                 return map(attrgetter('value'), value)
    366             else:
    367                 return [value.value]
    368         else:
    369             return []
    370 
    371     def keys(self):
    372         if self.list is None:
    373             raise TypeError, 'not indexable'
    374         return list(set((item.name for item in self.list)))
    375 
    376     def has_key(self, key):
    377         if self.list is None:
    378             raise TypeError, 'not indexable'
    379         return any((item.name == key for item in self.list))
    380 
    381     def __contains__(self, key):
    382         if self.list is None:
    383             raise TypeError, 'not indexable'
    384         return any((item.name == key for item in self.list))
    385 
    386     def __len__(self):
    387         return len(self.keys())
    388 
    389     def __nonzero__(self):
    390         return bool(self.list)
    391 
    392     def read_urlencoded(self):
    393         qs = self.fp.read(self.length)
    394         if self.qs_on_post:
    395             qs += '&' + self.qs_on_post
    396         self.list = list = []
    397         for key, value in urlparse.parse_qsl(qs, self.keep_blank_values, self.strict_parsing):
    398             list.append(MiniFieldStorage(key, value))
    399 
    400         self.skip_lines()
    401 
    402     FieldStorageClass = None
    403 
    404     def read_multi(self, environ, keep_blank_values, strict_parsing):
    405         ib = self.innerboundary
    406         if not valid_boundary(ib):
    407             raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
    408         self.list = []
    409         if self.qs_on_post:
    410             for key, value in urlparse.parse_qsl(self.qs_on_post, self.keep_blank_values, self.strict_parsing):
    411                 self.list.append(MiniFieldStorage(key, value))
    412 
    413             FieldStorageClass = None
    414         klass = self.FieldStorageClass or self.__class__
    415         part = klass(self.fp, {}, ib, environ, keep_blank_values, strict_parsing)
    416         while not part.done:
    417             headers = rfc822.Message(self.fp)
    418             part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing)
    419             self.list.append(part)
    420 
    421         self.skip_lines()
    422 
    423     def read_single(self):
    424         if self.length >= 0:
    425             self.read_binary()
    426             self.skip_lines()
    427         else:
    428             self.read_lines()
    429         self.file.seek(0)
    430 
    431     bufsize = 8192
    432 
    433     def read_binary(self):
    434         self.file = self.make_file('b')
    435         todo = self.length
    436         if todo >= 0:
    437             while todo > 0:
    438                 data = self.fp.read(min(todo, self.bufsize))
    439                 if not data:
    440                     self.done = -1
    441                     break
    442                 self.file.write(data)
    443                 todo = todo - len(data)
    444 
    445     def read_lines(self):
    446         self.file = self.__file = StringIO()
    447         if self.outerboundary:
    448             self.read_lines_to_outerboundary()
    449         else:
    450             self.read_lines_to_eof()
    451 
    452     def __write(self, line):
    453         if self.__file is not None:
    454             if self.__file.tell() + len(line) > 1000:
    455                 self.file = self.make_file('')
    456                 self.file.write(self.__file.getvalue())
    457                 self.__file = None
    458         self.file.write(line)
    459 
    460     def read_lines_to_eof(self):
    461         while 1:
    462             line = self.fp.readline(65536)
    463             if not line:
    464                 self.done = -1
    465                 break
    466             self.__write(line)
    467 
    468     def read_lines_to_outerboundary(self):
    469         next = '--' + self.outerboundary
    470         last = next + '--'
    471         delim = ''
    472         last_line_lfend = True
    473         while 1:
    474             line = self.fp.readline(65536)
    475             if not line:
    476                 self.done = -1
    477                 break
    478             if line[:2] == '--' and last_line_lfend:
    479                 strippedline = line.strip()
    480                 if strippedline == next:
    481                     break
    482                 if strippedline == last:
    483                     self.done = 1
    484                     break
    485             odelim = delim
    486             if line[-2:] == '\r\n':
    487                 delim = '\r\n'
    488                 line = line[:-2]
    489                 last_line_lfend = True
    490             elif line[-1] == '\n':
    491                 delim = '\n'
    492                 line = line[:-1]
    493                 last_line_lfend = True
    494             else:
    495                 delim = ''
    496                 last_line_lfend = False
    497             self.__write(odelim + line)
    498 
    499     def skip_lines(self):
    500         if not self.outerboundary or self.done:
    501             return
    502         next = '--' + self.outerboundary
    503         last = next + '--'
    504         last_line_lfend = True
    505         while 1:
    506             line = self.fp.readline(65536)
    507             if not line:
    508                 self.done = -1
    509                 break
    510             if line[:2] == '--' and last_line_lfend:
    511                 strippedline = line.strip()
    512                 if strippedline == next:
    513                     break
    514                 if strippedline == last:
    515                     self.done = 1
    516                     break
    517             last_line_lfend = line.endswith('\n')
    518 
    519     def make_file(self, binary = None):
    520         import tempfile
    521         return tempfile.TemporaryFile('w+b')
    522 
    523 
    524 class FormContentDict(UserDict.UserDict):
    525 
    526     def __init__(self, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
    527         self.dict = self.data = parse(environ=environ, keep_blank_values=keep_blank_values, strict_parsing=strict_parsing)
    528         self.query_string = environ['QUERY_STRING']
    529 
    530 
    531 class SvFormContentDict(FormContentDict):
    532 
    533     def __getitem__(self, key):
    534         if len(self.dict[key]) > 1:
    535             raise IndexError, 'expecting a single value'
    536         return self.dict[key][0]
    537 
    538     def getlist(self, key):
    539         return self.dict[key]
    540 
    541     def values(self):
    542         result = []
    543         for value in self.dict.values():
    544             if len(value) == 1:
    545                 result.append(value[0])
    546             else:
    547                 result.append(value)
    548 
    549         return result
    550 
    551     def items(self):
    552         result = []
    553         for key, value in self.dict.items():
    554             if len(value) == 1:
    555                 result.append((key, value[0]))
    556             else:
    557                 result.append((key, value))
    558 
    559         return result
    560 
    561 
    562 class InterpFormContentDict(SvFormContentDict):
    563 
    564     def __getitem__(self, key):
    565         v = SvFormContentDict.__getitem__(self, key)
    566         if v[0] in '0123456789+-.':
    567             try:
    568                 return int(v)
    569             except ValueError:
    570                 try:
    571                     return float(v)
    572                 except ValueError:
    573                     pass
    574 
    575         return v.strip()
    576 
    577     def values(self):
    578         result = []
    579         for key in self.keys():
    580             try:
    581                 result.append(self[key])
    582             except IndexError:
    583                 result.append(self.dict[key])
    584 
    585         return result
    586 
    587     def items(self):
    588         result = []
    589         for key in self.keys():
    590             try:
    591                 result.append((key, self[key]))
    592             except IndexError:
    593                 result.append((key, self.dict[key]))
    594 
    595         return result
    596 
    597 
    598 class FormContent(FormContentDict):
    599 
    600     def values(self, key):
    601         if key in self.dict:
    602             return self.dict[key]
    603         else:
    604             return None
    605 
    606     def indexed_value(self, key, location):
    607         if key in self.dict:
    608             if len(self.dict[key]) > location:
    609                 return self.dict[key][location]
    610             else:
    611                 return None
    612         else:
    613             return None
    614 
    615     def value(self, key):
    616         if key in self.dict:
    617             return self.dict[key][0]
    618         else:
    619             return None
    620 
    621     def length(self, key):
    622         return len(self.dict[key])
    623 
    624     def stripped(self, key):
    625         if key in self.dict:
    626             return self.dict[key][0].strip()
    627         else:
    628             return None
    629 
    630     def pars(self):
    631         return self.dict
    632 
    633 
    634 def test(environ = os.environ):
    635     global maxlen
    636     print 'Content-type: text/html'
    637     print
    638     sys.stderr = sys.stdout
    639     try:
    640         form = FieldStorage()
    641         print_directory()
    642         print_arguments()
    643         print_form(form)
    644         print_environ(environ)
    645         print_environ_usage()
    646 
    647         def f():
    648             exec 'testing print_exception() -- <I>italics?</I>'
    649 
    650         def g(f = f):
    651             f()
    652 
    653         print '<H3>What follows is a test, not an actual exception:</H3>'
    654         g()
    655     except:
    656         print_exception()
    657 
    658     print '<H1>Second try with a small maxlen...</H1>'
    659     maxlen = 50
    660     try:
    661         form = FieldStorage()
    662         print_directory()
    663         print_arguments()
    664         print_form(form)
    665         print_environ(environ)
    666     except:
    667         print_exception()
    668 
    669 
    670 def print_exception(type = None, value = None, tb = None, limit = None):
    671     if type is None:
    672         type, value, tb = sys.exc_info()
    673     import traceback
    674     print
    675     print '<H3>Traceback (most recent call last):</H3>'
    676     list = traceback.format_tb(tb, limit) + traceback.format_exception_only(type, value)
    677     print '<PRE>%s<B>%s</B></PRE>' % (escape(''.join(list[:-1])), escape(list[-1]))
    678     del tb
    679 
    680 
    681 def print_environ(environ = os.environ):
    682     keys = environ.keys()
    683     keys.sort()
    684     print
    685     print '<H3>Shell Environment:</H3>'
    686     print '<DL>'
    687     for key in keys:
    688         print '<DT>', escape(key), '<DD>', escape(environ[key])
    689 
    690     print '</DL>'
    691     print
    692 
    693 
    694 def print_form(form):
    695     keys = form.keys()
    696     keys.sort()
    697     print
    698     print '<H3>Form Contents:</H3>'
    699     if not keys:
    700         print '<P>No form fields.'
    701     print '<DL>'
    702     for key in keys:
    703         print '<DT>' + escape(key) + ':',
    704         value = form[key]
    705         print '<i>' + escape(repr(type(value))) + '</i>'
    706         print '<DD>' + escape(repr(value))
    707 
    708     print '</DL>'
    709     print
    710 
    711 
    712 def print_directory():
    713     print
    714     print '<H3>Current Working Directory:</H3>'
    715     try:
    716         pwd = os.getcwd()
    717     except os.error as msg:
    718         print 'os.error:', escape(str(msg))
    719     else:
    720         print escape(pwd)
    721 
    722     print
    723 
    724 
    725 def print_arguments():
    726     print
    727     print '<H3>Command Line Arguments:</H3>'
    728     print
    729     print sys.argv
    730     print
    731 
    732 
    733 def print_environ_usage():
    734     print '\n<H3>These environment variables could have been set:</H3>\n<UL>\n<LI>AUTH_TYPE\n<LI>CONTENT_LENGTH\n<LI>CONTENT_TYPE\n<LI>DATE_GMT\n<LI>DATE_LOCAL\n<LI>DOCUMENT_NAME\n<LI>DOCUMENT_ROOT\n<LI>DOCUMENT_URI\n<LI>GATEWAY_INTERFACE\n<LI>LAST_MODIFIED\n<LI>PATH\n<LI>PATH_INFO\n<LI>PATH_TRANSLATED\n<LI>QUERY_STRING\n<LI>REMOTE_ADDR\n<LI>REMOTE_HOST\n<LI>REMOTE_IDENT\n<LI>REMOTE_USER\n<LI>REQUEST_METHOD\n<LI>SCRIPT_NAME\n<LI>SERVER_NAME\n<LI>SERVER_PORT\n<LI>SERVER_PROTOCOL\n<LI>SERVER_ROOT\n<LI>SERVER_SOFTWARE\n</UL>\nIn addition, HTTP headers sent by the server may be passed in the\nenvironment as well.  Here are some common variable names:\n<UL>\n<LI>HTTP_ACCEPT\n<LI>HTTP_CONNECTION\n<LI>HTTP_HOST\n<LI>HTTP_PRAGMA\n<LI>HTTP_REFERER\n<LI>HTTP_USER_AGENT\n</UL>\n'
    735 
    736 
    737 def escape(s, quote = None):
    738     s = s.replace('&', '&amp;')
    739     s = s.replace('<', '&lt;')
    740     s = s.replace('>', '&gt;')
    741     if quote:
    742         s = s.replace('"', '&quot;')
    743     return s
    744 
    745 
    746 def valid_boundary(s, _vb_pattern = '^[ -~]{0,200}[!-~]$'):
    747     import re
    748     return re.match(_vb_pattern, s)
    749 
    750 
    751 if __name__ == '__main__':
    752     test()