fix scrolling SignalPanel
[enigma2-plugins.git] / lastfm / src / httpclient.py
1 from twisted.internet import reactor
2 from twisted.internet.protocol import ClientFactory,connectionDone
3 from twisted.web2.client.http import HTTPClientProtocol
4 from twisted.internet import error 
5 import urlparse, urllib
6
7 import socket
8
9 global HTTPCLIENT_requestCount
10 HTTPCLIENT_requestCount = 0 # counts requests
11     
12 class Enigma2HTTPRequest:
13         
14     def __init__(self,hostname,path,port,method="GET",headerfields={}):
15         self.hostname=hostname
16         self.port=port
17         self.path=path
18         self.method=method
19         self.headerfields = headerfields
20         self.onRequestFinished = []
21         self.onRequestError = []
22         self.onHeaderLoaded = []
23         
24         self.data=""
25         self.readsize = 0
26         self.headers= {}
27         
28     def _DataRecived(self,data):
29         self.readsize += len(data)
30         self.data += data
31             
32     def getIPAdress(self):
33         """    
34             socket.gethostbyname() is syncron
35             Enigma2 is blocked while process is running    
36         """
37         try:
38             return socket.gethostbyname(self.hostname)
39         except:
40             return False
41         
42     def HeaderLoaded(self,headers):
43         self.headers = headers
44         for i in self.onHeaderLoaded:
45             if i is not None:
46                 i(headers)
47         self.onHeaderLoaded=[]
48         
49     def RequestError(self,error):
50         for i in self.onRequestError:
51             if i is not None:
52                 i(error)
53         self.onRequestError = []
54         
55     def RequestFinished(self,data):
56         for i in self.onRequestFinished:
57             if i is not None:
58                 i(data)
59        
60 class Enigma2URLHTTPRequest(Enigma2HTTPRequest):
61     def __init__(self,url,method="GET",headerfields={}):
62         x= urlparse.urlsplit(url)
63         if x[1].rfind(":")>0:
64             y = x[1].split(":")
65             hostname = y[0]
66             port = int(y[1])
67         else:
68             hostname = x[1]
69             port = 80
70         path=x[2]
71         Enigma2HTTPRequest.__init__(self,hostname,path,port,method=method,headerfields=headerfields)
72
73 class Enigma2FileHTTPRequest(Enigma2URLHTTPRequest):
74     def __init__(self,targetfile,url,method="GET",headerfields={}):
75         Enigma2URLHTTPRequest.__init__(self,url,method=method,headerfields=headerfields)
76         self.filehandle = open(targetfile,"w")
77         self.onRequestFinished.append(self.close)
78         self.onRequestError.append(self.close)
79     def close(self,dummy):
80         self.filehandle.close()
81     
82     def _DataRecived(self,data):
83         self.readsize += len(data)
84         self.filehandle.write(data)
85         
86             
87         
88         
89 class Enigma2HTTPProtocol(HTTPClientProtocol):
90     DEBUG = False
91     
92     def __init__(self,request,requestCount):
93         self.request = request
94         self.requestCount = requestCount
95         self.headers={}
96         self.headerread=False
97         self.responseFirstLine = True # to indikate, that first line of responseheader was read
98         HTTPClientProtocol.__init__(self)
99         self.setRawMode()
100         
101     def rawDataReceived(self,line):
102         for l in line.split(self.delimiter): 
103             if self.headerread:
104                 self.request._DataRecived(l)
105             else:
106                 if self.DEBUG:
107                     print "HTTP "+self.requestCount+" <<==",l
108                 if l == "":
109                     self.headerread = True
110                     self.request.HeaderLoaded(self.headers)
111                 else:
112                     self.parseHeaderLine(l)
113     
114     def parseHeaderLine(self,line):
115         if self.responseFirstLine is  True:
116             #print "parseHeaderLine",line.split(" ")
117             fields = line.split(" ")
118             protocoll = fields[0]
119             responsecode  = fields[1]
120             statuscode = " ".join(fields[2:])
121             self.headers["protocoll"] = protocoll
122             self.headers["responsecode"] = responsecode
123             self.headers["statuscode"] = statuscode
124             self.responseFirstLine = False
125         elif line.rfind(":"):
126             x = line.split(":")
127             key = x[0].lstrip().rstrip().lower()
128             var = ":".join(x[1:]).lstrip()
129             self.headers[key] = var        
130         else:
131             print "unknown headerline",line
132
133     def connectionMade(self):
134         if self.request.method == "POST":
135             (path,params ) = self.request.path.split("?")
136         elif self.request.method == "GET":
137             path = self.request.path
138         self.sendLine("%s %s HTTP/1.0"%(self.request.method,path))
139         self.sendLine("Host: %s"%self.request.hostname)
140         for i in self.request.headerfields:
141             self.sendLine(i+": "+self.request.headerfields[i])
142         if self.request.method == "POST":
143             self.sendLine("Content-Type: application/x-www-form-urlencoded")
144             self.sendLine("Content-Length: "+str(len(params)))
145         
146         self.sendLine("")
147         if self.request.method == "POST":
148             self.sendLine(params)
149     
150     def sendLine(self,data):
151         if self.DEBUG:
152             print "HTTP "+self.requestCount+" ==>>",data
153         HTTPClientProtocol.sendLine(self,data)
154         
155 class Enigma2HTTPClientFactory(ClientFactory):
156
157     initialDelay = 20
158     maxDelay = 500
159     def __init__(self,request):
160         self.hangup_ok = False
161         self.request = request
162        
163     def startedConnecting(self, connector):
164         pass
165     
166     def buildProtocol(self, addr):
167         global HTTPCLIENT_requestCount
168         HTTPCLIENT_requestCount = HTTPCLIENT_requestCount + 1
169         return Enigma2HTTPProtocol(self.request,str(HTTPCLIENT_requestCount))
170
171     def clientConnectionLost(self, connector, reason):
172         if not self.hangup_ok:
173             self.request.RequestFinished(self.request.data)
174         ClientFactory.clientConnectionLost(self, connector, reason)
175         
176     def clientConnectionFailed(self, connector, reason):
177         self.request.RequestError(reason.getErrorMessage())
178         ClientFactory.clientConnectionFailed(self, connector, reason)
179
180 def urlencode(dict):
181     return urllib.urlencode(dict)
182
183 def quote_plus(data):
184     return urllib.quote_plus(data)
185
186 def getURL(url,callback=None,errorback=None,headercallback=None,method="GET",headers={}):
187     """ 
188         this will is called with a url
189         url = http://www.hostna.me/somewhere/on/the/server <string>
190     """
191     req = Enigma2URLHTTPRequest(url,method=method,headerfields=headers)
192     req.onRequestError.append(errorback)
193     req.onHeaderLoaded.append(headercallback)
194     req.onRequestFinished.append(callback)
195     ipadress = req.getIPAdress()
196     if ipadress is not False:
197         reactor.connectTCP(ipadress,req.port, Enigma2HTTPClientFactory(req))
198         return req
199     else:
200         if errorback is not None:
201             errorback("Error while resolve Hostname")
202
203 def getPage(hostname,port,path,method="GET",callback=None,errorback=None,headercallback=None,headers={}):
204     """ 
205         this will is called with separte hostname,port,path
206         hostname = www.hostna.me <string>
207         port = 80 <int>
208         path= /somewhere/on/the/server <string>
209     """
210     req = Enigma2HTTPRequest(hostname,path,port,method=method,headerfields=headers)
211     req.onRequestError.append(errorback)
212     req.onRequestFinished.append(callback)
213     ipadress = req.getIPAdress()
214     if ipadress is not False:
215         reactor.connectTCP(ipadress,req.port, Enigma2HTTPClientFactory(req))
216         return req
217     else:
218         if errorback is not None:
219             errorback("Error while resolve Hostname")
220
221 def getFile(filename,url,method="GET",callback=None,errorback=None,headercallback=None,headers={}):
222     """ 
223         this will is called with a url and a target file
224         fimename = /tmp/target.jpg 
225         url = http://www.hostna.me/somewhere/on/the/server.jpg <string>
226     """
227     req = Enigma2FileHTTPRequest(filename,url,method=method,headerfields=headers)
228     req.onRequestError.append(errorback)
229     req.onHeaderLoaded.append(headercallback)
230     req.onRequestFinished.append(callback)
231     ipadress = req.getIPAdress()
232     if ipadress is not False:
233         reactor.connectTCP(ipadress,req.port, Enigma2HTTPClientFactory(req))
234         return req
235     else:
236         if errorback is not None:
237             errorback("Error while resolve Hostname")
238