fix Bug. now clears the streamplayerCB on Screen.close()
[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         if self.errorback is not None:
178             self.request.RequestError(reason.getErrorMessage())
179         ClientFactory.clientConnectionFailed(self, connector, reason)
180
181 def urlencode(dict):
182     return urllib.urlencode(dict)
183
184 def quote_plus(data):
185     return urllib.quote_plus(data)
186
187 def getURL(url,callback=None,errorback=None,headercallback=None,method="GET",headers={}):
188     """ 
189         this will is called with a url
190         url = http://www.hostna.me/somewhere/on/the/server <string>
191     """
192     req = Enigma2URLHTTPRequest(url,method=method,headerfields=headers)
193     req.onRequestError.append(errorback)
194     req.onHeaderLoaded.append(headercallback)
195     req.onRequestFinished.append(callback)
196     ipadress = req.getIPAdress()
197     if ipadress is not False:
198         reactor.connectTCP(ipadress,req.port, Enigma2HTTPClientFactory(req))
199         return req
200     else:
201         if errorback is not None:
202             errorback("Error while resolve Hostname")
203
204 def getPage(hostname,port,path,method="GET",callback=None,errorback=None,headercallback=None,headers={}):
205     """ 
206         this will is called with separte hostname,port,path
207         hostname = www.hostna.me <string>
208         port = 80 <int>
209         path= /somewhere/on/the/server <string>
210     """
211     req = Enigma2HTTPRequest(hostname,path,port,method=method,headerfields=headers)
212     req.onRequestError.append(errorback)
213     req.onRequestFinished.append(callback)
214     ipadress = req.getIPAdress()
215     if ipadress is not False:
216         reactor.connectTCP(ipadress,req.port, Enigma2HTTPClientFactory(req))
217         return req
218     else:
219         if errorback is not None:
220             errorback("Error while resolve Hostname")
221
222 def getFile(filename,url,method="GET",callback=None,errorback=None,headercallback=None,headers={}):
223     """ 
224         this will is called with a url and a target file
225         fimename = /tmp/target.jpg 
226         url = http://www.hostna.me/somewhere/on/the/server.jpg <string>
227     """
228     req = Enigma2FileHTTPRequest(filename,url,method=method,headerfields=headers)
229     req.onRequestError.append(errorback)
230     req.onHeaderLoaded.append(headercallback)
231     req.onRequestFinished.append(callback)
232     ipadress = req.getIPAdress()
233     if ipadress is not False:
234         reactor.connectTCP(ipadress,req.port, Enigma2HTTPClientFactory(req))
235         return req
236     else:
237         if errorback is not None:
238             errorback("Error while resolve Hostname")
239