home *** CD-ROM | disk | FTP | other *** search
/ Freelog 116 / FreelogNo116-JuilletSeptembre2013.iso / Bureautique / gImageReader / gimagereader_0.9-1_win32.exe / bin / httplib.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2011-03-24  |  35KB  |  1,202 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. '''HTTP/1.1 client library
  5.  
  6. <intro stuff goes here>
  7. <other stuff, too>
  8.  
  9. HTTPConnection goes through a number of "states", which define when a client
  10. may legally make another request or fetch the response for a particular
  11. request. This diagram details these state transitions:
  12.  
  13.     (null)
  14.       |
  15.       | HTTPConnection()
  16.       v
  17.     Idle
  18.       |
  19.       | putrequest()
  20.       v
  21.     Request-started
  22.       |
  23.       | ( putheader() )*  endheaders()
  24.       v
  25.     Request-sent
  26.       |
  27.       | response = getresponse()
  28.       v
  29.     Unread-response   [Response-headers-read]
  30.       |\\____________________
  31.       |                     |
  32.       | response.read()     | putrequest()
  33.       v                     v
  34.     Idle                  Req-started-unread-response
  35.                      ______/|
  36.                    /        |
  37.    response.read() |        | ( putheader() )*  endheaders()
  38.                    v        v
  39.        Request-started    Req-sent-unread-response
  40.                             |
  41.                             | response.read()
  42.                             v
  43.                           Request-sent
  44.  
  45. This diagram presents the following rules:
  46.   -- a second request may not be started until {response-headers-read}
  47.   -- a response [object] cannot be retrieved until {request-sent}
  48.   -- there is no differentiation between an unread response body and a
  49.      partially read response body
  50.  
  51. Note: this enforcement is applied by the HTTPConnection class. The
  52.       HTTPResponse class does not enforce this state machine, which
  53.       implies sophisticated clients may accelerate the request/response
  54.       pipeline. Caution should be taken, though: accelerating the states
  55.       beyond the above pattern may imply knowledge of the server\'s
  56.       connection-close behavior for certain requests. For example, it
  57.       is impossible to tell whether the server will close the connection
  58.       UNTIL the response headers have been read; this means that further
  59.       requests cannot be placed into the pipeline until it is known that
  60.       the server will NOT be closing the connection.
  61.  
  62. Logical State                  __state            __response
  63. -------------                  -------            ----------
  64. Idle                           _CS_IDLE           None
  65. Request-started                _CS_REQ_STARTED    None
  66. Request-sent                   _CS_REQ_SENT       None
  67. Unread-response                _CS_IDLE           <response_class>
  68. Req-started-unread-response    _CS_REQ_STARTED    <response_class>
  69. Req-sent-unread-response       _CS_REQ_SENT       <response_class>
  70. '''
  71. from array import array
  72. import os
  73. import socket
  74. from sys import py3kwarning
  75. from urlparse import urlsplit
  76. import warnings
  77. with warnings.catch_warnings():
  78.     if py3kwarning:
  79.         warnings.filterwarnings('ignore', '.*mimetools has been removed', DeprecationWarning)
  80.     import mimetools
  81.  
  82. try:
  83.     from cStringIO import StringIO
  84. except ImportError:
  85.     from StringIO import StringIO
  86.  
  87. __all__ = [
  88.     'HTTP',
  89.     'HTTPResponse',
  90.     'HTTPConnection',
  91.     'HTTPException',
  92.     'NotConnected',
  93.     'UnknownProtocol',
  94.     'UnknownTransferEncoding',
  95.     'UnimplementedFileMode',
  96.     'IncompleteRead',
  97.     'InvalidURL',
  98.     'ImproperConnectionState',
  99.     'CannotSendRequest',
  100.     'CannotSendHeader',
  101.     'ResponseNotReady',
  102.     'BadStatusLine',
  103.     'error',
  104.     'responses']
  105. HTTP_PORT = 80
  106. HTTPS_PORT = 443
  107. _UNKNOWN = 'UNKNOWN'
  108. _CS_IDLE = 'Idle'
  109. _CS_REQ_STARTED = 'Request-started'
  110. _CS_REQ_SENT = 'Request-sent'
  111. CONTINUE = 100
  112. SWITCHING_PROTOCOLS = 101
  113. PROCESSING = 102
  114. OK = 200
  115. CREATED = 201
  116. ACCEPTED = 202
  117. NON_AUTHORITATIVE_INFORMATION = 203
  118. NO_CONTENT = 204
  119. RESET_CONTENT = 205
  120. PARTIAL_CONTENT = 206
  121. MULTI_STATUS = 207
  122. IM_USED = 226
  123. MULTIPLE_CHOICES = 300
  124. MOVED_PERMANENTLY = 301
  125. FOUND = 302
  126. SEE_OTHER = 303
  127. NOT_MODIFIED = 304
  128. USE_PROXY = 305
  129. TEMPORARY_REDIRECT = 307
  130. BAD_REQUEST = 400
  131. UNAUTHORIZED = 401
  132. PAYMENT_REQUIRED = 402
  133. FORBIDDEN = 403
  134. NOT_FOUND = 404
  135. METHOD_NOT_ALLOWED = 405
  136. NOT_ACCEPTABLE = 406
  137. PROXY_AUTHENTICATION_REQUIRED = 407
  138. REQUEST_TIMEOUT = 408
  139. CONFLICT = 409
  140. GONE = 410
  141. LENGTH_REQUIRED = 411
  142. PRECONDITION_FAILED = 412
  143. REQUEST_ENTITY_TOO_LARGE = 413
  144. REQUEST_URI_TOO_LONG = 414
  145. UNSUPPORTED_MEDIA_TYPE = 415
  146. REQUESTED_RANGE_NOT_SATISFIABLE = 416
  147. EXPECTATION_FAILED = 417
  148. UNPROCESSABLE_ENTITY = 422
  149. LOCKED = 423
  150. FAILED_DEPENDENCY = 424
  151. UPGRADE_REQUIRED = 426
  152. INTERNAL_SERVER_ERROR = 500
  153. NOT_IMPLEMENTED = 501
  154. BAD_GATEWAY = 502
  155. SERVICE_UNAVAILABLE = 503
  156. GATEWAY_TIMEOUT = 504
  157. HTTP_VERSION_NOT_SUPPORTED = 505
  158. INSUFFICIENT_STORAGE = 507
  159. NOT_EXTENDED = 510
  160. responses = {
  161.     100: 'Continue',
  162.     101: 'Switching Protocols',
  163.     200: 'OK',
  164.     201: 'Created',
  165.     202: 'Accepted',
  166.     203: 'Non-Authoritative Information',
  167.     204: 'No Content',
  168.     205: 'Reset Content',
  169.     206: 'Partial Content',
  170.     300: 'Multiple Choices',
  171.     301: 'Moved Permanently',
  172.     302: 'Found',
  173.     303: 'See Other',
  174.     304: 'Not Modified',
  175.     305: 'Use Proxy',
  176.     306: '(Unused)',
  177.     307: 'Temporary Redirect',
  178.     400: 'Bad Request',
  179.     401: 'Unauthorized',
  180.     402: 'Payment Required',
  181.     403: 'Forbidden',
  182.     404: 'Not Found',
  183.     405: 'Method Not Allowed',
  184.     406: 'Not Acceptable',
  185.     407: 'Proxy Authentication Required',
  186.     408: 'Request Timeout',
  187.     409: 'Conflict',
  188.     410: 'Gone',
  189.     411: 'Length Required',
  190.     412: 'Precondition Failed',
  191.     413: 'Request Entity Too Large',
  192.     414: 'Request-URI Too Long',
  193.     415: 'Unsupported Media Type',
  194.     416: 'Requested Range Not Satisfiable',
  195.     417: 'Expectation Failed',
  196.     500: 'Internal Server Error',
  197.     501: 'Not Implemented',
  198.     502: 'Bad Gateway',
  199.     503: 'Service Unavailable',
  200.     504: 'Gateway Timeout',
  201.     505: 'HTTP Version Not Supported' }
  202. MAXAMOUNT = 1048576
  203.  
  204. class HTTPMessage(mimetools.Message):
  205.     
  206.     def addheader(self, key, value):
  207.         '''Add header for field key handling repeats.'''
  208.         prev = self.dict.get(key)
  209.         if prev is None:
  210.             self.dict[key] = value
  211.         else:
  212.             combined = ', '.join((prev, value))
  213.             self.dict[key] = combined
  214.  
  215.     
  216.     def addcontinue(self, key, more):
  217.         '''Add more field data from a continuation line.'''
  218.         prev = self.dict[key]
  219.         self.dict[key] = prev + '\n ' + more
  220.  
  221.     
  222.     def readheaders(self):
  223.         '''Read header lines.
  224.  
  225.         Read header lines up to the entirely blank line that terminates them.
  226.         The (normally blank) line that ends the headers is skipped, but not
  227.         included in the returned list.  If a non-header line ends the headers,
  228.         (which is an error), an attempt is made to backspace over it; it is
  229.         never included in the returned list.
  230.  
  231.         The variable self.status is set to the empty string if all went well,
  232.         otherwise it is an error message.  The variable self.headers is a
  233.         completely uninterpreted list of lines contained in the header (so
  234.         printing them will reproduce the header exactly as it appears in the
  235.         file).
  236.  
  237.         If multiple header fields with the same name occur, they are combined
  238.         according to the rules in RFC 2616 sec 4.2:
  239.  
  240.         Appending each subsequent field-value to the first, each separated
  241.         by a comma. The order in which header fields with the same field-name
  242.         are received is significant to the interpretation of the combined
  243.         field value.
  244.         '''
  245.         self.dict = { }
  246.         self.unixfrom = ''
  247.         self.headers = hlist = []
  248.         self.status = ''
  249.         headerseen = ''
  250.         firstline = 1
  251.         startofline = None
  252.         unread = None
  253.         tell = None
  254.         if hasattr(self.fp, 'unread'):
  255.             unread = self.fp.unread
  256.         elif self.seekable:
  257.             tell = self.fp.tell
  258.         while True:
  259.             if tell:
  260.                 
  261.                 try:
  262.                     startofline = tell()
  263.                 except IOError:
  264.                     startofline = None
  265.                     tell = None
  266.                     self.seekable = 0
  267.                 
  268.  
  269.             line = self.fp.readline()
  270.             if not line:
  271.                 self.status = 'EOF in headers'
  272.                 break
  273.             if firstline and line.startswith('From '):
  274.                 self.unixfrom = self.unixfrom + line
  275.                 continue
  276.             firstline = 0
  277.             if headerseen and line[0] in ' \t':
  278.                 hlist.append(line)
  279.                 self.addcontinue(headerseen, line.strip())
  280.                 continue
  281.             elif self.iscomment(line):
  282.                 continue
  283.             elif self.islast(line):
  284.                 break
  285.             headerseen = self.isheader(line)
  286.             if headerseen:
  287.                 hlist.append(line)
  288.                 self.addheader(headerseen, line[len(headerseen) + 1:].strip())
  289.                 continue
  290.                 continue
  291.             if not self.dict:
  292.                 self.status = 'No headers'
  293.             else:
  294.                 self.status = 'Non-header line where header expected'
  295.             if unread:
  296.                 unread(line)
  297.             elif tell:
  298.                 self.fp.seek(startofline)
  299.             else:
  300.                 self.status = self.status + '; bad seek'
  301.             break
  302.  
  303.  
  304.  
  305. class HTTPResponse:
  306.     
  307.     def __init__(self, sock, debuglevel = 0, strict = 0, method = None, buffering = False):
  308.         if buffering:
  309.             self.fp = sock.makefile('rb')
  310.         else:
  311.             self.fp = sock.makefile('rb', 0)
  312.         self.debuglevel = debuglevel
  313.         self.strict = strict
  314.         self._method = method
  315.         self.msg = None
  316.         self.version = _UNKNOWN
  317.         self.status = _UNKNOWN
  318.         self.reason = _UNKNOWN
  319.         self.chunked = _UNKNOWN
  320.         self.chunk_left = _UNKNOWN
  321.         self.length = _UNKNOWN
  322.         self.will_close = _UNKNOWN
  323.  
  324.     
  325.     def _read_status(self):
  326.         line = self.fp.readline()
  327.         if self.debuglevel > 0:
  328.             print 'reply:', repr(line)
  329.         if not line:
  330.             raise BadStatusLine(line)
  331.         
  332.         try:
  333.             (version, status, reason) = line.split(None, 2)
  334.         except ValueError:
  335.             
  336.             try:
  337.                 (version, status) = line.split(None, 1)
  338.                 reason = ''
  339.             except ValueError:
  340.                 version = ''
  341.             
  342.  
  343.  
  344.         if not version.startswith('HTTP/'):
  345.             if self.strict:
  346.                 self.close()
  347.                 raise BadStatusLine(line)
  348.             self.fp = LineAndFileWrapper(line, self.fp)
  349.             return ('HTTP/0.9', 200, '')
  350.         
  351.         try:
  352.             status = int(status)
  353.             if status < 100 or status > 999:
  354.                 raise BadStatusLine(line)
  355.         except ValueError:
  356.             raise BadStatusLine(line)
  357.  
  358.         return (version, status, reason)
  359.  
  360.     
  361.     def begin(self):
  362.         if self.msg is not None:
  363.             return None
  364.         if True:
  365.             (version, status, reason) = self._read_status()
  366.             if status != CONTINUE:
  367.                 break
  368.             while True:
  369.                 skip = self.fp.readline().strip()
  370.                 if not skip:
  371.                     break
  372.                 if self.debuglevel > 0:
  373.                     print 'header:', skip
  374.                     continue
  375.             self.status = status
  376.             self.reason = reason.strip()
  377.             if version == 'HTTP/1.0':
  378.                 self.version = 10
  379.             elif version.startswith('HTTP/1.'):
  380.                 self.version = 11
  381.             elif version == 'HTTP/0.9':
  382.                 self.version = 9
  383.             else:
  384.                 raise UnknownProtocol(version)
  385.             if None.version == 9:
  386.                 self.length = None
  387.                 self.chunked = 0
  388.                 self.will_close = 1
  389.                 self.msg = HTTPMessage(StringIO())
  390.                 return None
  391.             self.msg = None(self.fp, 0)
  392.             if self.debuglevel > 0:
  393.                 for hdr in self.msg.headers:
  394.                     print 'header:', hdr,
  395.                 
  396.             self.msg.fp = None
  397.             tr_enc = self.msg.getheader('transfer-encoding')
  398.             if tr_enc and tr_enc.lower() == 'chunked':
  399.                 self.chunked = 1
  400.                 self.chunk_left = None
  401.             else:
  402.                 self.chunked = 0
  403.         self.will_close = self._check_close()
  404.         length = self.msg.getheader('content-length')
  405.         if length and not (self.chunked):
  406.             
  407.             try:
  408.                 self.length = int(length)
  409.             except ValueError:
  410.                 self.length = None
  411.  
  412.             if self.length < 0:
  413.                 self.length = None
  414.             
  415.         else:
  416.             self.length = None
  417.         if not status == NO_CONTENT and status == NOT_MODIFIED:
  418.             if status <= status:
  419.                 pass
  420.             elif status < 200 or self._method == 'HEAD':
  421.                 self.length = 0
  422.             if not (self.will_close) and not (self.chunked) and self.length is None:
  423.                 self.will_close = 1
  424.             return None
  425.  
  426.     
  427.     def _check_close(self):
  428.         conn = self.msg.getheader('connection')
  429.         if self.version == 11:
  430.             conn = self.msg.getheader('connection')
  431.             if conn and 'close' in conn.lower():
  432.                 return True
  433.             return None
  434.         if None.msg.getheader('keep-alive'):
  435.             return False
  436.         if None and 'keep-alive' in conn.lower():
  437.             return False
  438.         pconn = None.msg.getheader('proxy-connection')
  439.         if pconn and 'keep-alive' in pconn.lower():
  440.             return False
  441.  
  442.     
  443.     def close(self):
  444.         if self.fp:
  445.             self.fp.close()
  446.             self.fp = None
  447.  
  448.     
  449.     def isclosed(self):
  450.         return self.fp is None
  451.  
  452.     
  453.     def read(self, amt = None):
  454.         if self.fp is None:
  455.             return ''
  456.         if None._method == 'HEAD':
  457.             self.close()
  458.             return ''
  459.         if None.chunked:
  460.             return self._read_chunked(amt)
  461.         if None is None:
  462.             if self.length is None:
  463.                 s = self.fp.read()
  464.             else:
  465.                 s = self._safe_read(self.length)
  466.                 self.length = 0
  467.             self.close()
  468.             return s
  469.         if None.length is not None and amt > self.length:
  470.             amt = self.length
  471.         
  472.         s = self.fp.read(amt)
  473.         if self.length is not None:
  474.             self.length -= len(s)
  475.             if not self.length:
  476.                 self.close()
  477.             
  478.         return s
  479.  
  480.     
  481.     def _read_chunked(self, amt):
  482.         if not self.chunked != _UNKNOWN:
  483.             raise AssertionError
  484.         chunk_left = None.chunk_left
  485.         value = []
  486.         while True:
  487.             if chunk_left is None:
  488.                 line = self.fp.readline()
  489.                 i = line.find(';')
  490.                 if i >= 0:
  491.                     line = line[:i]
  492.                 
  493.                 try:
  494.                     chunk_left = int(line, 16)
  495.                 except ValueError:
  496.                     self.close()
  497.                     raise IncompleteRead(''.join(value))
  498.  
  499.                 if chunk_left == 0:
  500.                     break
  501.                 
  502.             if amt is None:
  503.                 value.append(self._safe_read(chunk_left))
  504.             elif amt < chunk_left:
  505.                 value.append(self._safe_read(amt))
  506.                 self.chunk_left = chunk_left - amt
  507.                 return ''.join(value)
  508.             if amt == chunk_left:
  509.                 value.append(self._safe_read(amt))
  510.                 self._safe_read(2)
  511.                 self.chunk_left = None
  512.                 return ''.join(value)
  513.             None.append(self._safe_read(chunk_left))
  514.             amt -= chunk_left
  515.             self._safe_read(2)
  516.             chunk_left = None
  517.         while True:
  518.             line = self.fp.readline()
  519.             if not line:
  520.                 break
  521.             if line == '\r\n':
  522.                 break
  523.                 continue
  524.             self.close()
  525.             return ''.join(value)
  526.  
  527.     
  528.     def _safe_read(self, amt):
  529.         '''Read the number of bytes requested, compensating for partial reads.
  530.  
  531.         Normally, we have a blocking socket, but a read() can be interrupted
  532.         by a signal (resulting in a partial read).
  533.  
  534.         Note that we cannot distinguish between EOF and an interrupt when zero
  535.         bytes have been read. IncompleteRead() will be raised in this
  536.         situation.
  537.  
  538.         This function should be used when <amt> bytes "should" be present for
  539.         reading. If the bytes are truly not available (due to EOF), then the
  540.         IncompleteRead exception can be used to detect the problem.
  541.         '''
  542.         s = []
  543.         while amt > 0:
  544.             chunk = self.fp.read(min(amt, MAXAMOUNT))
  545.             if not chunk:
  546.                 raise IncompleteRead(''.join(s), amt)
  547.             s.append(chunk)
  548.             amt -= len(chunk)
  549.         return ''.join(s)
  550.  
  551.     
  552.     def fileno(self):
  553.         return self.fp.fileno()
  554.  
  555.     
  556.     def getheader(self, name, default = None):
  557.         if self.msg is None:
  558.             raise ResponseNotReady()
  559.         return self.msg.getheader(name, default)
  560.  
  561.     
  562.     def getheaders(self):
  563.         '''Return list of (header, value) tuples.'''
  564.         if self.msg is None:
  565.             raise ResponseNotReady()
  566.         return self.msg.items()
  567.  
  568.  
  569.  
  570. class HTTPConnection:
  571.     _http_vsn = 11
  572.     _http_vsn_str = 'HTTP/1.1'
  573.     response_class = HTTPResponse
  574.     default_port = HTTP_PORT
  575.     auto_open = 1
  576.     debuglevel = 0
  577.     strict = 0
  578.     
  579.     def __init__(self, host, port = None, strict = None, timeout = socket._GLOBAL_DEFAULT_TIMEOUT, source_address = None):
  580.         self.timeout = timeout
  581.         self.source_address = source_address
  582.         self.sock = None
  583.         self._buffer = []
  584.         self._HTTPConnection__response = None
  585.         self._HTTPConnection__state = _CS_IDLE
  586.         self._method = None
  587.         self._tunnel_host = None
  588.         self._tunnel_port = None
  589.         self._tunnel_headers = { }
  590.         self._set_hostport(host, port)
  591.         if strict is not None:
  592.             self.strict = strict
  593.  
  594.     
  595.     def set_tunnel(self, host, port = None, headers = None):
  596.         ''' Sets up the host and the port for the HTTP CONNECT Tunnelling.
  597.  
  598.         The headers argument should be a mapping of extra HTTP headers
  599.         to send with the CONNECT request.
  600.         '''
  601.         self._tunnel_host = host
  602.         self._tunnel_port = port
  603.         if headers:
  604.             self._tunnel_headers = headers
  605.         else:
  606.             self._tunnel_headers.clear()
  607.  
  608.     
  609.     def _set_hostport(self, host, port):
  610.         if port is None:
  611.             i = host.rfind(':')
  612.             j = host.rfind(']')
  613.             if i > j:
  614.                 
  615.                 try:
  616.                     port = int(host[i + 1:])
  617.                 except ValueError:
  618.                     raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:])
  619.  
  620.                 host = host[:i]
  621.             else:
  622.                 port = self.default_port
  623.             if host and host[0] == '[' and host[-1] == ']':
  624.                 host = host[1:-1]
  625.             
  626.         self.host = host
  627.         self.port = port
  628.  
  629.     
  630.     def set_debuglevel(self, level):
  631.         self.debuglevel = level
  632.  
  633.     
  634.     def _tunnel(self):
  635.         self._set_hostport(self._tunnel_host, self._tunnel_port)
  636.         self.send('CONNECT %s:%d HTTP/1.0\r\n' % (self.host, self.port))
  637.         for header, value in self._tunnel_headers.iteritems():
  638.             self.send('%s: %s\r\n' % (header, value))
  639.         
  640.         self.send('\r\n')
  641.         response = self.response_class(self.sock, strict = self.strict, method = self._method)
  642.         (version, code, message) = response._read_status()
  643.         if code != 200:
  644.             self.close()
  645.             raise socket.error('Tunnel connection failed: %d %s' % (code, message.strip()))
  646.         while True:
  647.             line = response.fp.readline()
  648.             if line == '\r\n':
  649.                 break
  650.                 continue
  651.             return None
  652.  
  653.     
  654.     def connect(self):
  655.         '''Connect to the host and port specified in __init__.'''
  656.         self.sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address)
  657.         if self._tunnel_host:
  658.             self._tunnel()
  659.  
  660.     
  661.     def close(self):
  662.         '''Close the connection to the HTTP server.'''
  663.         if self.sock:
  664.             self.sock.close()
  665.             self.sock = None
  666.         if self._HTTPConnection__response:
  667.             self._HTTPConnection__response.close()
  668.             self._HTTPConnection__response = None
  669.         self._HTTPConnection__state = _CS_IDLE
  670.  
  671.     
  672.     def send(self, data):
  673.         """Send `data' to the server."""
  674.         if self.sock is None:
  675.             if self.auto_open:
  676.                 self.connect()
  677.             else:
  678.                 raise NotConnected()
  679.         if self.debuglevel > 0:
  680.             print 'send:', repr(data)
  681.         blocksize = 8192
  682.         if hasattr(data, 'read') and not isinstance(data, array):
  683.             if self.debuglevel > 0:
  684.                 print 'sendIng a read()able'
  685.             datablock = data.read(blocksize)
  686.             while datablock:
  687.                 self.sock.sendall(datablock)
  688.                 datablock = data.read(blocksize)
  689.         else:
  690.             self.sock.sendall(data)
  691.  
  692.     
  693.     def _output(self, s):
  694.         '''Add a line of output to the current request buffer.
  695.  
  696.         Assumes that the line does *not* end with \\r\\n.
  697.         '''
  698.         self._buffer.append(s)
  699.  
  700.     
  701.     def _send_output(self, message_body = None):
  702.         '''Send the currently buffered request and clear the buffer.
  703.  
  704.         Appends an extra \\r\\n to the buffer.
  705.         A message_body may be specified, to be appended to the request.
  706.         '''
  707.         self._buffer.extend(('', ''))
  708.         msg = '\r\n'.join(self._buffer)
  709.         del self._buffer[:]
  710.         if isinstance(message_body, str):
  711.             msg += message_body
  712.             message_body = None
  713.         self.send(msg)
  714.         if message_body is not None:
  715.             self.send(message_body)
  716.  
  717.     
  718.     def putrequest(self, method, url, skip_host = 0, skip_accept_encoding = 0):
  719.         """Send a request to the server.
  720.  
  721.         `method' specifies an HTTP request method, e.g. 'GET'.
  722.         `url' specifies the object being requested, e.g. '/index.html'.
  723.         `skip_host' if True does not add automatically a 'Host:' header
  724.         `skip_accept_encoding' if True does not add automatically an
  725.            'Accept-Encoding:' header
  726.         """
  727.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  728.             self._HTTPConnection__response = None
  729.         if self._HTTPConnection__state == _CS_IDLE:
  730.             self._HTTPConnection__state = _CS_REQ_STARTED
  731.         else:
  732.             raise CannotSendRequest()
  733.         self._method = None
  734.         if not url:
  735.             url = '/'
  736.         hdr = '%s %s %s' % (method, url, self._http_vsn_str)
  737.         self._output(hdr)
  738.         if self._http_vsn == 11:
  739.             if not skip_host:
  740.                 netloc = ''
  741.                 if url.startswith('http'):
  742.                     (nil, netloc, nil, nil, nil) = urlsplit(url)
  743.                 if netloc:
  744.                     
  745.                     try:
  746.                         netloc_enc = netloc.encode('ascii')
  747.                     except UnicodeEncodeError:
  748.                         netloc_enc = netloc.encode('idna')
  749.  
  750.                     self.putheader('Host', netloc_enc)
  751.                 else:
  752.                     
  753.                     try:
  754.                         host_enc = self.host.encode('ascii')
  755.                     except UnicodeEncodeError:
  756.                         host_enc = self.host.encode('idna')
  757.  
  758.                     if host_enc.find(':') >= 0:
  759.                         host_enc = '[' + host_enc + ']'
  760.                     if self.port == self.default_port:
  761.                         self.putheader('Host', host_enc)
  762.                     else:
  763.                         self.putheader('Host', '%s:%s' % (host_enc, self.port))
  764.             if not skip_accept_encoding:
  765.                 self.putheader('Accept-Encoding', 'identity')
  766.             
  767.  
  768.     
  769.     def putheader(self, header, *values):
  770.         """Send a request header line to the server.
  771.  
  772.         For example: h.putheader('Accept', 'text/html')
  773.         """
  774.         if self._HTTPConnection__state != _CS_REQ_STARTED:
  775.             raise CannotSendHeader()
  776.         hdr = '%s: %s' % (header, '\r\n\t'.join([ str(v) for v in values ]))
  777.         self._output(hdr)
  778.  
  779.     
  780.     def endheaders(self, message_body = None):
  781.         '''Indicate that the last header line has been sent to the server.
  782.  
  783.         This method sends the request to the server.  The optional
  784.         message_body argument can be used to pass message body
  785.         associated with the request.  The message body will be sent in
  786.         the same packet as the message headers if possible.  The
  787.         message_body should be a string.
  788.         '''
  789.         if self._HTTPConnection__state == _CS_REQ_STARTED:
  790.             self._HTTPConnection__state = _CS_REQ_SENT
  791.         else:
  792.             raise CannotSendHeader()
  793.         None._send_output(message_body)
  794.  
  795.     
  796.     def request(self, method, url, body = None, headers = { }):
  797.         '''Send a complete request to the server.'''
  798.         self._send_request(method, url, body, headers)
  799.  
  800.     
  801.     def _set_content_length(self, body):
  802.         thelen = None
  803.         
  804.         try:
  805.             thelen = str(len(body))
  806.         except TypeError:
  807.             te = None
  808.             
  809.             try:
  810.                 thelen = str(os.fstat(body.fileno()).st_size)
  811.             except (AttributeError, OSError):
  812.                 if self.debuglevel > 0:
  813.                     print 'Cannot stat!!'
  814.                 
  815.             
  816.  
  817.  
  818.         if thelen is not None:
  819.             self.putheader('Content-Length', thelen)
  820.  
  821.     
  822.     def _send_request(self, method, url, body, headers):
  823.         header_names = dict.fromkeys([ k.lower() for k in headers ])
  824.         skips = { }
  825.         if 'host' in header_names:
  826.             skips['skip_host'] = 1
  827.         if 'accept-encoding' in header_names:
  828.             skips['skip_accept_encoding'] = 1
  829.         self.putrequest(method, url, **skips)
  830.         if body and 'content-length' not in header_names:
  831.             self._set_content_length(body)
  832.         for hdr, value in headers.iteritems():
  833.             self.putheader(hdr, value)
  834.         
  835.         self.endheaders(body)
  836.  
  837.     
  838.     def getresponse(self, buffering = False):
  839.         '''Get the response from the server.'''
  840.         if self._HTTPConnection__response and self._HTTPConnection__response.isclosed():
  841.             self._HTTPConnection__response = None
  842.         if self._HTTPConnection__state != _CS_REQ_SENT or self._HTTPConnection__response:
  843.             raise ResponseNotReady()
  844.         args = (self.sock,)
  845.         kwds = {
  846.             'strict': self.strict,
  847.             'method': self._method }
  848.         if self.debuglevel > 0:
  849.             args += (self.debuglevel,)
  850.         if buffering:
  851.             kwds['buffering'] = True
  852.         response = self.response_class(*args, **kwds)
  853.         response.begin()
  854.         if not response.will_close != _UNKNOWN:
  855.             raise AssertionError
  856.         self._HTTPConnection__state = None
  857.         if response.will_close:
  858.             self.close()
  859.         else:
  860.             self._HTTPConnection__response = response
  861.         return response
  862.  
  863.  
  864.  
  865. class HTTP:
  866.     '''Compatibility class with httplib.py from 1.5.'''
  867.     _http_vsn = 10
  868.     _http_vsn_str = 'HTTP/1.0'
  869.     debuglevel = 0
  870.     _connection_class = HTTPConnection
  871.     
  872.     def __init__(self, host = '', port = None, strict = None):
  873.         '''Provide a default host, since the superclass requires one.'''
  874.         if port == 0:
  875.             port = None
  876.         self._setup(self._connection_class(host, port, strict))
  877.  
  878.     
  879.     def _setup(self, conn):
  880.         self._conn = conn
  881.         self.send = conn.send
  882.         self.putrequest = conn.putrequest
  883.         self.putheader = conn.putheader
  884.         self.endheaders = conn.endheaders
  885.         self.set_debuglevel = conn.set_debuglevel
  886.         conn._http_vsn = self._http_vsn
  887.         conn._http_vsn_str = self._http_vsn_str
  888.         self.file = None
  889.  
  890.     
  891.     def connect(self, host = None, port = None):
  892.         """Accept arguments to set the host/port, since the superclass doesn't."""
  893.         if host is not None:
  894.             self._conn._set_hostport(host, port)
  895.         self._conn.connect()
  896.  
  897.     
  898.     def getfile(self):
  899.         """Provide a getfile, since the superclass' does not use this concept."""
  900.         return self.file
  901.  
  902.     
  903.     def getreply(self, buffering = False):
  904.         '''Compat definition since superclass does not define it.
  905.  
  906.         Returns a tuple consisting of:
  907.         - server status code (e.g. \'200\' if all goes well)
  908.         - server "reason" corresponding to status code
  909.         - any RFC822 headers in the response from the server
  910.         '''
  911.         
  912.         try:
  913.             if not buffering:
  914.                 response = self._conn.getresponse()
  915.             else:
  916.                 response = self._conn.getresponse(buffering)
  917.         except BadStatusLine:
  918.             e = None
  919.             self.file = self._conn.sock.makefile('rb', 0)
  920.             self.close()
  921.             self.headers = None
  922.             return (-1, e.line, None)
  923.  
  924.         self.headers = response.msg
  925.         self.file = response.fp
  926.         return (response.status, response.reason, response.msg)
  927.  
  928.     
  929.     def close(self):
  930.         self._conn.close()
  931.         self.file = None
  932.  
  933.  
  934.  
  935. try:
  936.     import ssl
  937. except ImportError:
  938.     pass
  939.  
  940.  
  941. class HTTPSConnection(HTTPConnection):
  942.     '''This class allows communication via SSL.'''
  943.     default_port = HTTPS_PORT
  944.     
  945.     def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None, timeout = socket._GLOBAL_DEFAULT_TIMEOUT, source_address = None):
  946.         HTTPConnection.__init__(self, host, port, strict, timeout, source_address)
  947.         self.key_file = key_file
  948.         self.cert_file = cert_file
  949.  
  950.     
  951.     def connect(self):
  952.         '''Connect to a host on a given (SSL) port.'''
  953.         sock = socket.create_connection((self.host, self.port), self.timeout, self.source_address)
  954.         if self._tunnel_host:
  955.             self.sock = sock
  956.             self._tunnel()
  957.         self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
  958.  
  959.  
  960. __all__.append('HTTPSConnection')
  961.  
  962. class HTTPS(HTTP):
  963.     '''Compatibility with 1.5 httplib interface
  964.  
  965.         Python 1.5.2 did not have an HTTPS class, but it defined an
  966.         interface for sending http requests that is also useful for
  967.         https.
  968.         '''
  969.     _connection_class = HTTPSConnection
  970.     
  971.     def __init__(self, host = '', port = None, key_file = None, cert_file = None, strict = None):
  972.         if port == 0:
  973.             port = None
  974.         self._setup(self._connection_class(host, port, key_file, cert_file, strict))
  975.         self.key_file = key_file
  976.         self.cert_file = cert_file
  977.  
  978.  
  979.  
  980. def FakeSocket(sock, sslobj):
  981.     warnings.warn("FakeSocket is deprecated, and won't be in 3.x.  " + 'Use the result of ssl.wrap_socket() directly instead.', DeprecationWarning, stacklevel = 2)
  982.     return sslobj
  983.  
  984.  
  985. class HTTPException(Exception):
  986.     pass
  987.  
  988.  
  989. class NotConnected(HTTPException):
  990.     pass
  991.  
  992.  
  993. class InvalidURL(HTTPException):
  994.     pass
  995.  
  996.  
  997. class UnknownProtocol(HTTPException):
  998.     
  999.     def __init__(self, version):
  1000.         self.args = (version,)
  1001.         self.version = version
  1002.  
  1003.  
  1004.  
  1005. class UnknownTransferEncoding(HTTPException):
  1006.     pass
  1007.  
  1008.  
  1009. class UnimplementedFileMode(HTTPException):
  1010.     pass
  1011.  
  1012.  
  1013. class IncompleteRead(HTTPException):
  1014.     
  1015.     def __init__(self, partial, expected = None):
  1016.         self.args = (partial,)
  1017.         self.partial = partial
  1018.         self.expected = expected
  1019.  
  1020.     
  1021.     def __repr__(self):
  1022.         if self.expected is not None:
  1023.             e = ', %i more expected' % self.expected
  1024.         else:
  1025.             e = ''
  1026.         return 'IncompleteRead(%i bytes read%s)' % (len(self.partial), e)
  1027.  
  1028.     
  1029.     def __str__(self):
  1030.         return repr(self)
  1031.  
  1032.  
  1033.  
  1034. class ImproperConnectionState(HTTPException):
  1035.     pass
  1036.  
  1037.  
  1038. class CannotSendRequest(ImproperConnectionState):
  1039.     pass
  1040.  
  1041.  
  1042. class CannotSendHeader(ImproperConnectionState):
  1043.     pass
  1044.  
  1045.  
  1046. class ResponseNotReady(ImproperConnectionState):
  1047.     pass
  1048.  
  1049.  
  1050. class BadStatusLine(HTTPException):
  1051.     
  1052.     def __init__(self, line):
  1053.         if not line:
  1054.             line = repr(line)
  1055.         self.args = (line,)
  1056.         self.line = line
  1057.  
  1058.  
  1059. error = HTTPException
  1060.  
  1061. class LineAndFileWrapper:
  1062.     '''A limited file-like object for HTTP/0.9 responses.'''
  1063.     
  1064.     def __init__(self, line, file):
  1065.         self._line = line
  1066.         self._file = file
  1067.         self._line_consumed = 0
  1068.         self._line_offset = 0
  1069.         self._line_left = len(line)
  1070.  
  1071.     
  1072.     def __getattr__(self, attr):
  1073.         return getattr(self._file, attr)
  1074.  
  1075.     
  1076.     def _done(self):
  1077.         self._line_consumed = 1
  1078.         self.read = self._file.read
  1079.         self.readline = self._file.readline
  1080.         self.readlines = self._file.readlines
  1081.  
  1082.     
  1083.     def read(self, amt = None):
  1084.         if self._line_consumed:
  1085.             return self._file.read(amt)
  1086.         if not None._line_left:
  1087.             raise AssertionError
  1088.         if None is None or amt > self._line_left:
  1089.             s = self._line[self._line_offset:]
  1090.             self._done()
  1091.             if amt is None:
  1092.                 return s + self._file.read()
  1093.             return None + self._file.read(amt - len(s))
  1094.         if not amt <= self._line_left:
  1095.             raise AssertionError
  1096.         i = None._line_offset
  1097.         j = i + amt
  1098.         s = self._line[i:j]
  1099.         self._line_offset = j
  1100.         self._line_left -= amt
  1101.         if self._line_left == 0:
  1102.             self._done()
  1103.         return s
  1104.  
  1105.     
  1106.     def readline(self):
  1107.         if self._line_consumed:
  1108.             return self._file.readline()
  1109.         if not None._line_left:
  1110.             raise AssertionError
  1111.         s = None._line[self._line_offset:]
  1112.         self._done()
  1113.         return s
  1114.  
  1115.     
  1116.     def readlines(self, size = None):
  1117.         if self._line_consumed:
  1118.             return self._file.readlines(size)
  1119.         if not None._line_left:
  1120.             raise AssertionError
  1121.         L = [
  1122.             None._line[self._line_offset:]]
  1123.         self._done()
  1124.         if size is None:
  1125.             return L + self._file.readlines()
  1126.         return None + self._file.readlines(size)
  1127.  
  1128.  
  1129.  
  1130. def test():
  1131.     '''Test this module.
  1132.  
  1133.     A hodge podge of tests collected here, because they have too many
  1134.     external dependencies for the regular test suite.
  1135.     '''
  1136.     import sys as sys
  1137.     import getopt as getopt
  1138.     (opts, args) = getopt.getopt(sys.argv[1:], 'd')
  1139.     dl = 0
  1140.     for o, a in opts:
  1141.         if o == '-d':
  1142.             dl = dl + 1
  1143.             continue
  1144.     host = 'www.python.org'
  1145.     selector = '/'
  1146.     if args[0:]:
  1147.         host = args[0]
  1148.     if args[1:]:
  1149.         selector = args[1]
  1150.     h = HTTP()
  1151.     h.set_debuglevel(dl)
  1152.     h.connect(host)
  1153.     h.putrequest('GET', selector)
  1154.     h.endheaders()
  1155.     (status, reason, headers) = h.getreply()
  1156.     print 'status =', status
  1157.     print 'reason =', reason
  1158.     print 'read', len(h.getfile().read())
  1159.     print 
  1160.     if headers:
  1161.         for header in headers.headers:
  1162.             print header.strip()
  1163.         
  1164.     print 
  1165.     
  1166.     class HTTP11(HTTP):
  1167.         _http_vsn = 11
  1168.         _http_vsn_str = 'HTTP/1.1'
  1169.  
  1170.     h = HTTP11('www.python.org')
  1171.     h.putrequest('GET', 'http://www.python.org/~jeremy/')
  1172.     h.endheaders()
  1173.     h.getreply()
  1174.     h.close()
  1175.     
  1176.     try:
  1177.         import ssl
  1178.     except ImportError:
  1179.         pass
  1180.  
  1181.     for host, selector in (('sourceforge.net', '/projects/python'),):
  1182.         print 'https://%s%s' % (host, selector)
  1183.         hs = HTTPS()
  1184.         hs.set_debuglevel(dl)
  1185.         hs.connect(host)
  1186.         hs.putrequest('GET', selector)
  1187.         hs.endheaders()
  1188.         (status, reason, headers) = hs.getreply()
  1189.         print 'status =', status
  1190.         print 'reason =', reason
  1191.         print 'read', len(hs.getfile().read())
  1192.         print 
  1193.         if headers:
  1194.             for header in headers.headers:
  1195.                 print header.strip()
  1196.             
  1197.         print 
  1198.     
  1199.  
  1200. if __name__ == '__main__':
  1201.     test()
  1202.