1
2 import traceback
3 import SocketServer
4 import SimpleHTTPServer
5 import BaseHTTPServer
6 import pyratemp
7 import os
8 import sys
9 import traceback
10 import urllib
11 import time
12 import random
13 import socket
14 import Cookie
15 import string
16
17 from threading import Thread
18
19 chars = string.ascii_letters + string.digits
20 sessionDict = {}
21
24
27 Thread.__init__(self)
28 self.owner = owner
29 self.httpd = None
30 self.port = 8009
31 self.template_path = ""
32
33 tpath = os.path.realpath(pyratemp.__file__)
34 tpath = tpath.rsplit(os.sep,1)
35 self.spade_path = tpath[0]
36
37
38 self.controllers = {}
39
40 self.is_running = False
41
43
44 while not self.httpd:
45 try:
46 self.httpd = SocketServer.ThreadingTCPServer(('', self.port), WUIHandler)
47 self.httpd.owner = self
48 self.httpd.timeout = 1
49
50 self.notifyAMS()
51 except:
52 self.port = random.randint(1024,65536)
53
54 self.owner.DEBUG("WebUserInterface serving at port "+str(self.port))
55 self.registerController("error404", self.error404)
56 self.registerController("error501", self.error501)
57 self.registerController("error503", self.error503)
58
59 self.is_running = True
60 while self.isRunning():
61 self.httpd.handle_request()
62
64 return self.is_running
65
67 self.is_running = False
68
71
73 self.template_path = os.path.realpath(path)
74
76 self.controllers[name] = controller
77
79 del self.controllers[name]
80
90
91
92
94 return "404.pyra", {"template":"404.pyra"}
96 return "501.pyra", {"template":"501.pyra", "error":""}
98 return "503.pyra", {"page":"503.pyra"}
99
100
102 """Arbitrary objects, referenced by the session id"""
103 pass
104
106 """Return a random string of specified length (used for session id's)"""
107 return ''.join([random.choice(chars) for i in range(length)])
108
109 -class WUIHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
110
112 """Session management
113 If the client has sent a cookie named sessionId, take its value and
114 return the corresponding SessionElement objet, stored in
115 sessionDict
116 Otherwise create a new SessionElement objet and generate a random
117 8-letters value sent back to the client as the value for a cookie
118 called sessionId"""
119 if self.cookie.has_key("sessionId"):
120 sessionId=self.cookie["sessionId"].value
121 else:
122 sessionId=generateRandom(8)
123 self.cookie["sessionId"]=sessionId
124 try:
125 sessionObject = sessionDict[sessionId]
126 except KeyError:
127 sessionObject = SessionElement()
128 sessionDict[sessionId] = sessionObject
129 return sessionObject
130
131 - def getPage(self, req):
132 """
133 Return the page name from a raw GET line
134 """
135 return req.split("?")[0]
136
138 """
139 Return the variables and values from a raw GET or POST request line
140 """
141 d = dict()
142 try:
143 raw_vars = req.split("?")[1]
144 for raw in raw_vars.split("&"):
145
146 var = raw.split("=")
147 if len(var) > 1:
148
149 if var[0] in d.keys():
150 try:
151
152 d[var[0]].append(urllib.unquote_plus(var[1]))
153 except:
154
155 d[var[0]] = [d[var[0]]]
156 d[var[0]].append(urllib.unquote_plus(var[1]))
157 else:
158 d[urllib.unquote_plus(var[0])] = urllib.unquote_plus(var[1])
159 else:
160 d[urllib.unquote_plus(var[0])] = ""
161 except:
162 pass
163
164 return d
165
167
168 self._POST_REQ = ""
169 try:
170 length = int(self.headers.getheader('content-length'))
171 self._POST_REQ = self.rfile.read(length)
172 except:
173 pass
174
175 self.do_GET()
176
177
179 """
180 GET petitions handler
181 """
182 ret = None
183 request = self.raw_requestline.split()
184 page = self.getPage(request[1])
185
186
187 if page == "/": page = "/index"
188
189 if page.startswith("/"): page = page [1:]
190
191 try:
192 req_vars = self.getVars("?"+self._POST_REQ)
193 except:
194 req_vars = self.getVars(request[1])
195
196 s_vars=""
197 for k,v in req_vars.items():
198 if k:
199 v = str(v)
200 if not v.startswith('"') and not v.startswith("'") and not v.startswith("["):
201 v = '"'+ v +'"'
202 s_vars+= str(k) + "=" + v +","
203 if s_vars.endswith(","): s_vars = s_vars[:-1]
204
205
206 if self.headers.has_key('cookie'):
207 self.cookie=Cookie.SimpleCookie(self.headers.getheader("cookie"))
208 else:
209 self.cookie=Cookie.SimpleCookie()
210
211
212
213 if page.endswith(".css") or page.endswith(".png") or page.endswith(".html") or page.endswith(".js"):
214
215 try:
216 if os.path.exists(self.server.owner.template_path + os.sep + page):
217 page = self.server.owner.template_path + os.sep + page
218 elif os.path.exists(self.server.owner.spade_path + os.sep + "templates" + os.sep + page):
219 page = self.server.owner.spade_path + os.sep + "templates" + os.sep + page
220 elif page.startswith("doc") and os.path.exists(self.server.owner.spade_path + os.sep + page):
221
222 page = self.server.owner.spade_path + os.sep + page
223 else:
224 raise Exception
225
226 except:
227 self.server.owner.owner.DEBUG("Could not open file: "+ page, "err")
228
229 try:
230 self.send_response(200)
231 for morsel in self.cookie.values():
232 self.send_header('Set-Cookie', morsel.output(header='').lstrip())
233 self.end_headers()
234 f = open(page, "r")
235 self.copyfile(f, self.wfile)
236 f.close()
237 except:
238 self.server.owner.owner.DEBUG(str(sys.exc_info()), "err")
239
240 else:
241 sess = self.Session()
242 try:
243
244
245 eval("self.server.owner.controllers['"+str(page)+"']")
246 except:
247
248 _exception = sys.exc_info()
249 if _exception[0]:
250 _err = ''.join(traceback.format_exception(_exception[0], _exception[1], _exception[2])).rstrip()
251 template = "404.pyra"
252 ret = {"template":page, "error":str(_err),"name":self.server.owner.owner.getName()}
253 code=404
254 try:
255 if not ret:
256 func = self.server.owner.controllers[str(page)]
257
258 sess.url = page
259 func.__self__.session = sess
260 template, ret = eval("func"+"("+s_vars+")")
261 code=200
262 except HTTP_REDIRECTION,url:
263 self.send_response(302)
264 for morsel in self.cookie.values():
265 self.send_header('Set-Cookie', morsel.output(header='').lstrip())
266 self.send_header('Location', url)
267 self.end_headers()
268 self.wfile.write("")
269 return
270
271 except Exception, e:
272
273 _exception = sys.exc_info()
274 if _exception[0]:
275 _err = ''.join(traceback.format_exception(_exception[0], _exception[1], _exception[2])).rstrip()
276 template = "501.pyra"
277 ret = {"template":page, "error":str(_err),"name":self.server.owner.owner.getName()}
278 code=501
279
280 try:
281 if os.path.exists(self.server.owner.template_path+os.sep+template):
282 t = pyratemp.Template(filename=self.server.owner.template_path+os.sep+template, data=ret)
283 else:
284
285
286 authenticated = False
287 if hasattr(sess,"user_authenticated"):
288 if sess.user_authenticated==True: authenticated=True
289 ret['authenticated'] = authenticated
290 t = pyratemp.Template(filename=self.server.owner.spade_path+os.sep+"templates"+os.sep+template, data=ret)
291
292
293 except pyratemp.TemplateSyntaxError, e:
294 _exception = sys.exc_info()
295 if _exception[0]:
296 _err = ''.join(traceback.format_exception(_exception[0], _exception[1], _exception[2])).rstrip()
297 t = pyratemp.Template(filename=self.server.owner.spade_path+os.sep+"templates"+os.sep+"501.pyra", data={"template":template, "error":str(_err),"name":self.server.owner.owner.getName()})
298 code=501
299 except Exception, e:
300
301 _exception = sys.exc_info()
302 if _exception[0]:
303 _err = ''.join(traceback.format_exception(_exception[0], _exception[1], _exception[2])).rstrip()
304
305 t = pyratemp.Template(filename=self.server.owner.spade_path+os.sep+"templates"+os.sep+"503.pyra", data={"page":template,"name":self.server.owner.owner.getName()})
306 code=503
307 try:
308 result = t()
309 except Exception, e:
310
311 _exception = sys.exc_info()
312 if _exception[0]:
313 _err = ''.join(traceback.format_exception(_exception[0], _exception[1], _exception[2])).rstrip()
314 t = pyratemp.Template(filename=self.server.owner.spade_path+os.sep+"templates"+os.sep+"501.pyra", data={"template":template, "error":str(_err),"name":self.server.owner.owner.getName()})
315 result = t()
316 code=501
317
318 r = result.encode("ascii", 'xmlcharrefreplace')
319
320 self.send_response(code)
321 for morsel in self.cookie.values():
322 self.send_header('Set-Cookie', morsel.output(header='').lstrip())
323 self.end_headers()
324 self.wfile.write(r)
325