[Python-checkins] CVS: python/dist/src/Lib httplib.py,1.12,1.13

Guido van Rossum guido@cnri.reston.va.us
Tue, 7 Dec 1999 16:35:22 -0500 (EST)


Update of /projects/cvsroot/python/dist/src/Lib
In directory eric:/projects/python/develop/guido/src/Lib

Modified Files:
	httplib.py 
Log Message:
OpenSSL support.  This is based on patches for a version of SSLeay by
Brian E Gallew, which were improved and adapted to OpenSSL 0.9.4 by
Laszlo Kovacs of HP.  Both have kindly given permission to include
the patches in the Python distribution.  Final formatting by GvR.


Index: httplib.py
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Lib/httplib.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -r1.12 -r1.13
*** httplib.py	1998/01/19 22:25:24	1.12
--- httplib.py	1999/12/07 21:35:20	1.13
***************
*** 29,43 ****
  """
  
  import socket
  import string
  import mimetools
  
  HTTP_VERSION = 'HTTP/1.0'
  HTTP_PORT = 80
  
  class HTTP:
      """This class manages a connection to an HTTP server."""
!     
!     def __init__(self, host = '', port = 0):
          """Initialize a new instance.
  
--- 29,74 ----
  """
  
+ import os
  import socket
  import string
  import mimetools
  
+ try:
+     from cStringIO import StringIO
+ except:
+     from StringIO import StringIO
+ 
  HTTP_VERSION = 'HTTP/1.0'
  HTTP_PORT = 80
+ HTTPS_PORT = 443
+ 
+ class FakeSocket:
+     def __init__(self, sock, ssl):
+ 	self.__sock = sock
+ 	self.__ssl = ssl
+ 	return
+ 
+     def makefile(self, mode):		# hopefully, never have to write
+ 	msgbuf = ""
+ 	while 1:
+ 	    try:
+ 		msgbuf = msgbuf + self.__ssl.read()
+ 	    except socket.sslerror, msg:
+ 		break
+ 	return StringIO(msgbuf)
+ 
+     def send(self, stuff, flags = 0):
+ 	return self.__ssl.write(stuff)
+ 
+     def recv(self, len = 1024, flags = 0):
+ 	return self.__ssl.read(len)
+ 
+     def __getattr__(self, attr):
+ 	return getattr(self.__sock, attr)
  
  class HTTP:
      """This class manages a connection to an HTTP server."""
! 
!     def __init__(self, host = '', port = 0, **x509):
          """Initialize a new instance.
  
***************
*** 47,54 ****
  
          """
          self.debuglevel = 0
          self.file = None
          if host: self.connect(host, port)
!     
      def set_debuglevel(self, debuglevel):
          """Set the debug output level.
--- 78,87 ----
  
          """
+         self.key_file = x509.get('key_file')
+         self.cert_file = x509.get('cert_file')
          self.debuglevel = 0
          self.file = None
          if host: self.connect(host, port)
! 
      def set_debuglevel(self, debuglevel):
          """Set the debug output level.
***************
*** 59,66 ****
          """
          self.debuglevel = debuglevel
!     
      def connect(self, host, port = 0):
          """Connect to a host on a given port.
!         
          Note:  This method is automatically invoked by __init__,
          if a host is specified during instantiation.
--- 92,99 ----
          """
          self.debuglevel = debuglevel
! 
      def connect(self, host, port = 0):
          """Connect to a host on a given port.
! 
          Note:  This method is automatically invoked by __init__,
          if a host is specified during instantiation.
***************
*** 78,87 ****
          if self.debuglevel > 0: print 'connect:', (host, port)
          self.sock.connect(host, port)
!     
      def send(self, str):
          """Send `str' to the server."""
          if self.debuglevel > 0: print 'send:', `str`
          self.sock.send(str)
!     
      def putrequest(self, request, selector):
          """Send a request to the server.
--- 111,120 ----
          if self.debuglevel > 0: print 'connect:', (host, port)
          self.sock.connect(host, port)
! 
      def send(self, str):
          """Send `str' to the server."""
          if self.debuglevel > 0: print 'send:', `str`
          self.sock.send(str)
! 
      def putrequest(self, request, selector):
          """Send a request to the server.
***************
*** 95,99 ****
          str = '%s %s %s\r\n' % (request, selector, HTTP_VERSION)
          self.send(str)
!     
      def putheader(self, header, *args):
          """Send a request header line to the server.
--- 128,132 ----
          str = '%s %s %s\r\n' % (request, selector, HTTP_VERSION)
          self.send(str)
! 
      def putheader(self, header, *args):
          """Send a request header line to the server.
***************
*** 104,115 ****
          str = '%s: %s\r\n' % (header, string.joinfields(args,'\r\n\t'))
          self.send(str)
!     
      def endheaders(self):
          """Indicate that the last header line has been sent to the server."""
          self.send('\r\n')
!     
      def getreply(self):
          """Get a reply from the server.
!         
          Returns a tuple consisting of:
          - server response code (e.g. '200' if all goes well)
--- 137,148 ----
          str = '%s: %s\r\n' % (header, string.joinfields(args,'\r\n\t'))
          self.send(str)
! 
      def endheaders(self):
          """Indicate that the last header line has been sent to the server."""
          self.send('\r\n')
! 
      def getreply(self):
          """Get a reply from the server.
! 
          Returns a tuple consisting of:
          - server response code (e.g. '200' if all goes well)
***************
*** 137,141 ****
          self.headers = mimetools.Message(self.file, 0)
          return errcode, errmsg, self.headers
!     
      def getfile(self):
          """Get a file object from which to receive data from the HTTP server.
--- 170,174 ----
          self.headers = mimetools.Message(self.file, 0)
          return errcode, errmsg, self.headers
! 
      def getfile(self):
          """Get a file object from which to receive data from the HTTP server.
***************
*** 146,150 ****
          """
          return self.file
!     
      def close(self):
          """Close the connection to the HTTP server."""
--- 179,183 ----
          """
          return self.file
! 
      def close(self):
          """Close the connection to the HTTP server."""
***************
*** 156,159 ****
--- 189,217 ----
          self.sock = None
  
+ if hasattr(socket, "ssl"):
+     class HTTPS(HTTP):
+         """This class allows communication via SSL."""
+ 
+         def connect(self, host, port = 0):
+             """Connect to a host on a given port.
+ 
+             Note:  This method is automatically invoked by __init__,
+             if a host is specified during instantiation.
+ 
+             """
+             if not port:
+                 i = string.find(host, ':')
+                 if i >= 0:
+                     host, port = host[:i], host[i+1:]
+                     try: port = string.atoi(port)
+                     except string.atoi_error:
+                         raise socket.error, "nonnumeric port"
+             if not port: port = HTTPS_PORT
+             sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+             if self.debuglevel > 0: print 'connect:', (host, port)
+             sock.connect(host, port)
+             ssl = socket.ssl(sock, self.key_file, self.cert_file)
+             self.sock = FakeSocket(sock, ssl)
+ 
  
  def test():
***************
*** 171,174 ****
--- 229,233 ----
      for o, a in opts:
          if o == '-d': dl = dl + 1
+     print "testing HTTP..."
      host = 'www.python.org'
      selector = '/'
***************
*** 188,191 ****
--- 247,270 ----
      print
      print h.getfile().read()
+     if hasattr(socket, "ssl"):
+         print "-"*40
+         print "testing HTTPS..."
+         host = 'synergy.as.cmu.edu'
+         selector = '/~geek/'
+         if args[0:]: host = args[0]
+         if args[1:]: selector = args[1]
+         h = HTTPS()
+         h.set_debuglevel(dl)
+         h.connect(host)
+         h.putrequest('GET', selector)
+         h.endheaders()
+         errcode, errmsg, headers = h.getreply()
+         print 'errcode =', errcode
+         print 'errmsg  =', errmsg
+         print
+         if headers:
+             for header in headers.headers: print string.strip(header)
+         print
+         print h.getfile().read()