]> git.ipfire.org Git - ipfire.org.git/blame - www/pages/torrent/client/HTTPHandler.py
Change Color of Menuitem CeBIT.
[ipfire.org.git] / www / pages / torrent / client / HTTPHandler.py
CommitLineData
879aa787
MT
1# Written by Bram Cohen
2# see LICENSE.txt for license information
3
4from cStringIO import StringIO
5from sys import stdout
6import time
7from clock import clock
8from gzip import GzipFile
9try:
10 True
11except:
12 True = 1
13 False = 0
14
15DEBUG = False
16
17weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
18
19months = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
20 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
21
22class HTTPConnection:
23 def __init__(self, handler, connection):
24 self.handler = handler
25 self.connection = connection
26 self.buf = ''
27 self.closed = False
28 self.done = False
29 self.donereading = False
30 self.next_func = self.read_type
31
32 def get_ip(self):
33 return self.connection.get_ip()
34
35 def data_came_in(self, data):
36 if self.donereading or self.next_func is None:
37 return True
38 self.buf += data
39 while True:
40 try:
41 i = self.buf.index('\n')
42 except ValueError:
43 return True
44 val = self.buf[:i]
45 self.buf = self.buf[i+1:]
46 self.next_func = self.next_func(val)
47 if self.donereading:
48 return True
49 if self.next_func is None or self.closed:
50 return False
51
52 def read_type(self, data):
53 self.header = data.strip()
54 words = data.split()
55 if len(words) == 3:
56 self.command, self.path, garbage = words
57 self.pre1 = False
58 elif len(words) == 2:
59 self.command, self.path = words
60 self.pre1 = True
61 if self.command != 'GET':
62 return None
63 else:
64 return None
65 if self.command not in ('HEAD', 'GET'):
66 return None
67 self.headers = {}
68 return self.read_header
69
70 def read_header(self, data):
71 data = data.strip()
72 if data == '':
73 self.donereading = True
74 if self.headers.get('accept-encoding','').find('gzip') > -1:
75 self.encoding = 'gzip'
76 else:
77 self.encoding = 'identity'
78 r = self.handler.getfunc(self, self.path, self.headers)
79 if r is not None:
80 self.answer(r)
81 return None
82 try:
83 i = data.index(':')
84 except ValueError:
85 return None
86 self.headers[data[:i].strip().lower()] = data[i+1:].strip()
87 if DEBUG:
88 print data[:i].strip() + ": " + data[i+1:].strip()
89 return self.read_header
90
91 def answer(self, (responsecode, responsestring, headers, data)):
92 if self.closed:
93 return
94 if self.encoding == 'gzip':
95 compressed = StringIO()
96 gz = GzipFile(fileobj = compressed, mode = 'wb', compresslevel = 9)
97 gz.write(data)
98 gz.close()
99 cdata = compressed.getvalue()
100 if len(cdata) >= len(data):
101 self.encoding = 'identity'
102 else:
103 if DEBUG:
104 print "Compressed: %i Uncompressed: %i\n" % (len(cdata),len(data))
105 data = cdata
106 headers['Content-Encoding'] = 'gzip'
107
108 # i'm abusing the identd field here, but this should be ok
109 if self.encoding == 'identity':
110 ident = '-'
111 else:
112 ident = self.encoding
113 self.handler.log( self.connection.get_ip(), ident, '-',
114 self.header, responsecode, len(data),
115 self.headers.get('referer','-'),
116 self.headers.get('user-agent','-') )
117 self.done = True
118 r = StringIO()
119 r.write('HTTP/1.0 ' + str(responsecode) + ' ' +
120 responsestring + '\r\n')
121 if not self.pre1:
122 headers['Content-Length'] = len(data)
123 for key, value in headers.items():
124 r.write(key + ': ' + str(value) + '\r\n')
125 r.write('\r\n')
126 if self.command != 'HEAD':
127 r.write(data)
128 self.connection.write(r.getvalue())
129 if self.connection.is_flushed():
130 self.connection.shutdown(1)
131
132class HTTPHandler:
133 def __init__(self, getfunc, minflush):
134 self.connections = {}
135 self.getfunc = getfunc
136 self.minflush = minflush
137 self.lastflush = clock()
138
139 def external_connection_made(self, connection):
140 self.connections[connection] = HTTPConnection(self, connection)
141
142 def connection_flushed(self, connection):
143 if self.connections[connection].done:
144 connection.shutdown(1)
145
146 def connection_lost(self, connection):
147 ec = self.connections[connection]
148 ec.closed = True
149 del ec.connection
150 del ec.next_func
151 del self.connections[connection]
152
153 def data_came_in(self, connection, data):
154 c = self.connections[connection]
155 if not c.data_came_in(data) and not c.closed:
156 c.connection.shutdown(1)
157
158 def log(self, ip, ident, username, header,
159 responsecode, length, referrer, useragent):
160 year, month, day, hour, minute, second, a, b, c = time.localtime(time.time())
161 print '%s %s %s [%02d/%3s/%04d:%02d:%02d:%02d] "%s" %i %i "%s" "%s"' % (
162 ip, ident, username, day, months[month], year, hour,
163 minute, second, header, responsecode, length, referrer, useragent)
164 t = clock()
165 if t - self.lastflush > self.minflush:
166 self.lastflush = t
167 stdout.flush()