summaryrefslogtreecommitdiff
path: root/Lib/httplib.py
diff options
context:
space:
mode:
authorBill Janssen <janssen@parc.com>2007-08-29 22:35:05 +0000
committerBill Janssen <janssen@parc.com>2007-08-29 22:35:05 +0000
commit426ea0a8640b2905ba0c0833ff797241dd5b819d (patch)
tree884d69dd7a747da0a144dba46d8dfa8fd1a90fa7 /Lib/httplib.py
parent492e5920bc8a6d07be7f9b251bdc2482f043e48d (diff)
downloadcpython-git-426ea0a8640b2905ba0c0833ff797241dd5b819d.tar.gz
This contains a number of things:
1) Improve the documentation of the SSL module, with a fuller explanation of certificate usage, another reference, proper formatting of this and that. 2) Fix Windows bug in ssl.py, and general bug in sslsocket.close(). Remove some unused code from ssl.py. Allow accept() to be called on sslsocket sockets. 3) Use try-except-else in import of ssl in socket.py. Deprecate use of socket.ssl(). 4) Remove use of socket.ssl() in every library module, except for test_socket_ssl.py and test_ssl.py.
Diffstat (limited to 'Lib/httplib.py')
-rw-r--r--Lib/httplib.py233
1 files changed, 32 insertions, 201 deletions
diff --git a/Lib/httplib.py b/Lib/httplib.py
index aee9b0dc03..599a3314c9 100644
--- a/Lib/httplib.py
+++ b/Lib/httplib.py
@@ -940,205 +940,6 @@ class HTTPConnection:
return response
-# The next several classes are used to define FakeSocket, a socket-like
-# interface to an SSL connection.
-
-# The primary complexity comes from faking a makefile() method. The
-# standard socket makefile() implementation calls dup() on the socket
-# file descriptor. As a consequence, clients can call close() on the
-# parent socket and its makefile children in any order. The underlying
-# socket isn't closed until they are all closed.
-
-# The implementation uses reference counting to keep the socket open
-# until the last client calls close(). SharedSocket keeps track of
-# the reference counting and SharedSocketClient provides an constructor
-# and close() method that call incref() and decref() correctly.
-
-class SharedSocket:
-
- def __init__(self, sock):
- self.sock = sock
- self._refcnt = 0
-
- def incref(self):
- self._refcnt += 1
-
- def decref(self):
- self._refcnt -= 1
- assert self._refcnt >= 0
- if self._refcnt == 0:
- self.sock.close()
-
- def __del__(self):
- self.sock.close()
-
-class SharedSocketClient:
-
- def __init__(self, shared):
- self._closed = 0
- self._shared = shared
- self._shared.incref()
- self._sock = shared.sock
-
- def close(self):
- if not self._closed:
- self._shared.decref()
- self._closed = 1
- self._shared = None
-
-class SSLFile(SharedSocketClient):
- """File-like object wrapping an SSL socket."""
-
- BUFSIZE = 8192
-
- def __init__(self, sock, ssl, bufsize=None):
- SharedSocketClient.__init__(self, sock)
- self._ssl = ssl
- self._buf = ''
- self._bufsize = bufsize or self.__class__.BUFSIZE
-
- def _read(self):
- buf = ''
- # put in a loop so that we retry on transient errors
- while True:
- try:
- buf = self._ssl.read(self._bufsize)
- except socket.sslerror, err:
- if (err[0] == socket.SSL_ERROR_WANT_READ
- or err[0] == socket.SSL_ERROR_WANT_WRITE):
- continue
- if (err[0] == socket.SSL_ERROR_ZERO_RETURN
- or err[0] == socket.SSL_ERROR_EOF):
- break
- raise
- except socket.error, err:
- if err[0] == errno.EINTR:
- continue
- if err[0] == errno.EBADF:
- # XXX socket was closed?
- break
- raise
- else:
- break
- return buf
-
- def read(self, size=None):
- L = [self._buf]
- avail = len(self._buf)
- while size is None or avail < size:
- s = self._read()
- if s == '':
- break
- L.append(s)
- avail += len(s)
- all = "".join(L)
- if size is None:
- self._buf = ''
- return all
- else:
- self._buf = all[size:]
- return all[:size]
-
- def readline(self):
- L = [self._buf]
- self._buf = ''
- while 1:
- i = L[-1].find("\n")
- if i >= 0:
- break
- s = self._read()
- if s == '':
- break
- L.append(s)
- if i == -1:
- # loop exited because there is no more data
- return "".join(L)
- else:
- all = "".join(L)
- # XXX could do enough bookkeeping not to do a 2nd search
- i = all.find("\n") + 1
- line = all[:i]
- self._buf = all[i:]
- return line
-
- def readlines(self, sizehint=0):
- total = 0
- list = []
- while True:
- line = self.readline()
- if not line:
- break
- list.append(line)
- total += len(line)
- if sizehint and total >= sizehint:
- break
- return list
-
- def fileno(self):
- return self._sock.fileno()
-
- def __iter__(self):
- return self
-
- def next(self):
- line = self.readline()
- if not line:
- raise StopIteration
- return line
-
-class FakeSocket(SharedSocketClient):
-
- class _closedsocket:
- def __getattr__(self, name):
- raise error(9, 'Bad file descriptor')
-
- def __init__(self, sock, ssl):
- sock = SharedSocket(sock)
- SharedSocketClient.__init__(self, sock)
- self._ssl = ssl
-
- def close(self):
- SharedSocketClient.close(self)
- self._sock = self.__class__._closedsocket()
-
- def makefile(self, mode, bufsize=None):
- if mode != 'r' and mode != 'rb':
- raise UnimplementedFileMode()
- return SSLFile(self._shared, self._ssl, bufsize)
-
- def send(self, stuff, flags = 0):
- return self._ssl.write(stuff)
-
- sendall = send
-
- def recv(self, len = 1024, flags = 0):
- return self._ssl.read(len)
-
- def __getattr__(self, attr):
- return getattr(self._sock, attr)
-
- def close(self):
- SharedSocketClient.close(self)
- self._ssl = None
-
-class HTTPSConnection(HTTPConnection):
- "This class allows communication via SSL."
-
- default_port = HTTPS_PORT
-
- def __init__(self, host, port=None, key_file=None, cert_file=None,
- strict=None, timeout=None):
- HTTPConnection.__init__(self, host, port, strict, timeout)
- self.key_file = key_file
- self.cert_file = cert_file
-
- def connect(self):
- "Connect to a host on a given (SSL) port."
-
- sock = socket.create_connection((self.host, self.port), self.timeout)
- ssl = socket.ssl(sock, self.key_file, self.cert_file)
- self.sock = FakeSocket(sock, ssl)
-
class HTTP:
"Compatibility class with httplib.py from 1.5."
@@ -1229,7 +1030,29 @@ class HTTP:
### do it
self.file = None
-if hasattr(socket, 'ssl'):
+try:
+ import ssl
+except ImportError:
+ pass
+else:
+ class HTTPSConnection(HTTPConnection):
+ "This class allows communication via SSL."
+
+ default_port = HTTPS_PORT
+
+ def __init__(self, host, port=None, key_file=None, cert_file=None,
+ strict=None, timeout=None):
+ HTTPConnection.__init__(self, host, port, strict, timeout)
+ self.key_file = key_file
+ self.cert_file = cert_file
+
+ def connect(self):
+ "Connect to a host on a given (SSL) port."
+
+ sock = socket.create_connection((self.host, self.port), self.timeout)
+ self.sock = ssl.sslsocket(sock, self.key_file, self.cert_file)
+
+
class HTTPS(HTTP):
"""Compatibility with 1.5 httplib interface
@@ -1256,6 +1079,10 @@ if hasattr(socket, 'ssl'):
self.cert_file = cert_file
+ def FakeSocket (sock, sslobj):
+ return sslobj
+
+
class HTTPException(Exception):
# Subclasses that define an __init__ must call Exception.__init__
# or define self.args. Otherwise, str() will fail.
@@ -1413,7 +1240,11 @@ def test():
h.getreply()
h.close()
- if hasattr(socket, 'ssl'):
+ try:
+ import ssl
+ except ImportError:
+ pass
+ else:
for host, selector in (('sourceforge.net', '/projects/python'),
):