Blame | Last modification | View Log | Download
# Written by John Hoffman
# see LICENSE.txt for license information
from httplib import HTTPConnection, HTTPSConnection, HTTPException
from urlparse import urlparse
from bencode import bdecode
import socket
from gzip import GzipFile
from StringIO import StringIO
from urllib import quote, unquote
from __init__ import product_name, version_short
VERSION = product_name+'/'+version_short
MAX_REDIRECTS = 10
class btHTTPcon(HTTPConnection): # attempt to add automatic connection timeout
def connect(self):
HTTPConnection.connect(self)
try:
self.sock.settimeout(30)
except:
pass
class btHTTPScon(HTTPSConnection): # attempt to add automatic connection timeout
def connect(self):
HTTPSConnection.connect(self)
try:
self.sock.settimeout(30)
except:
pass
class urlopen:
def __init__(self, url):
self.tries = 0
self._open(url.strip())
self.error_return = None
def _open(self, url):
self.tries += 1
if self.tries > MAX_REDIRECTS:
raise IOError, ('http error', 500,
"Internal Server Error: Redirect Recursion")
(scheme, netloc, path, pars, query, fragment) = urlparse(url)
if scheme != 'http' and scheme != 'https':
raise IOError, ('url error', 'unknown url type', scheme, url)
url = path
if pars:
url += ';'+pars
if query:
url += '?'+query
# if fragment:
try:
if scheme == 'http':
self.connection = btHTTPcon(netloc)
else:
self.connection = btHTTPScon(netloc)
self.connection.request('GET', url, None,
{ 'User-Agent': VERSION,
'Accept-Encoding': 'gzip' } )
self.response = self.connection.getresponse()
except HTTPException, e:
raise IOError, ('http error', str(e))
status = self.response.status
if status in (301,302):
try:
self.connection.close()
except:
pass
self._open(self.response.getheader('Location'))
return
if status != 200:
try:
data = self._read()
d = bdecode(data)
if d.has_key('failure reason'):
self.error_return = data
return
except:
pass
raise IOError, ('http error', status, self.response.reason)
def read(self):
if self.error_return:
return self.error_return
return self._read()
def _read(self):
data = self.response.read()
if self.response.getheader('Content-Encoding','').find('gzip') >= 0:
try:
compressed = StringIO(data)
f = GzipFile(fileobj = compressed)
data = f.read()
except:
raise IOError, ('http error', 'got corrupt response')
return data
def close(self):
self.connection.close()