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