home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / httplib.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-29  |  37.7 KB  |  1,380 lines

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