Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
36 kaklik 1
# Written by John Hoffman
2
# see LICENSE.txt for license information
3
 
4
from httplib import HTTPConnection, HTTPSConnection, HTTPException
5
from urlparse import urlparse
6
from bencode import bdecode
7
import socket
8
from gzip import GzipFile
9
from StringIO import StringIO
10
from urllib import quote, unquote
11
from __init__ import product_name, version_short
12
 
13
VERSION = product_name+'/'+version_short
14
MAX_REDIRECTS = 10
15
 
16
 
17
class btHTTPcon(HTTPConnection): # attempt to add automatic connection timeout
18
    def connect(self):
19
        HTTPConnection.connect(self)
20
        try:
21
            self.sock.settimeout(30)
22
        except:
23
            pass
24
 
25
class btHTTPScon(HTTPSConnection): # attempt to add automatic connection timeout
26
    def connect(self):
27
        HTTPSConnection.connect(self)
28
        try:
29
            self.sock.settimeout(30)
30
        except:
31
            pass 
32
 
33
class urlopen:
34
    def __init__(self, url):
35
        self.tries = 0
36
        self._open(url.strip())
37
        self.error_return = None
38
 
39
    def _open(self, url):
40
        self.tries += 1
41
        if self.tries > MAX_REDIRECTS:
42
            raise IOError, ('http error', 500,
43
                            "Internal Server Error: Redirect Recursion")
44
        (scheme, netloc, path, pars, query, fragment) = urlparse(url)
45
        if scheme != 'http' and scheme != 'https':
46
            raise IOError, ('url error', 'unknown url type', scheme, url)
47
        url = path
48
        if pars:
49
            url += ';'+pars
50
        if query:
51
            url += '?'+query
52
#        if fragment:
53
        try:
54
            if scheme == 'http':
55
                self.connection = btHTTPcon(netloc)
56
            else:
57
                self.connection = btHTTPScon(netloc)
58
            self.connection.request('GET', url, None,
59
                                { 'User-Agent': VERSION,
60
                                  'Accept-Encoding': 'gzip' } )
61
            self.response = self.connection.getresponse()
62
        except HTTPException, e:
63
            raise IOError, ('http error', str(e))
64
        status = self.response.status
65
        if status in (301,302):
66
            try:
67
                self.connection.close()
68
            except:
69
                pass
70
            self._open(self.response.getheader('Location'))
71
            return
72
        if status != 200:
73
            try:
74
                data = self._read()
75
                d = bdecode(data)
76
                if d.has_key('failure reason'):
77
                    self.error_return = data
78
                    return
79
            except:
80
                pass
81
            raise IOError, ('http error', status, self.response.reason)
82
 
83
    def read(self):
84
        if self.error_return:
85
            return self.error_return
86
        return self._read()
87
 
88
    def _read(self):
89
        data = self.response.read()
90
        if self.response.getheader('Content-Encoding','').find('gzip') >= 0:
91
            try:
92
                compressed = StringIO(data)
93
                f = GzipFile(fileobj = compressed)
94
                data = f.read()
95
            except:
96
                raise IOError, ('http error', 'got corrupt response')
97
        return data
98
 
99
    def close(self):
100
        self.connection.close()