$search
00001 #!/usr/bin/env python 00002 00003 import neo_cgi, neo_cs 00004 import sys, os, string 00005 import time 00006 from log import * 00007 00008 # errors thrown... 00009 class NoPageName(Exception): 00010 pass 00011 class NoDisplayMethod(Exception): 00012 pass 00013 00014 # errors signaled back to here 00015 class Redirected(Exception): 00016 pass 00017 class DisplayDone(Exception): 00018 pass 00019 class DisplayError(Exception): 00020 pass 00021 class MultipleActionsError(Exception): 00022 pass 00023 00024 class Context: 00025 def __init__ (self): 00026 self.argv = sys.argv 00027 self.stdin = sys.stdin 00028 self.stdout = sys.stdout 00029 self.stderr = sys.stderr 00030 self.environ = os.environ 00031 00032 def setStatus(self, request, status): 00033 if request: 00034 request['status'] = str(status) 00035 00036 00037 class CSPage: 00038 _pagename = None 00039 00040 def __init__(self, context, pagename=None,readDefaultHDF=1,israwpage=0, 00041 parseCGI=1, makePUT=0, **parms): 00042 if pagename is None: pagename = self._pagename 00043 if not pagename: raise NoPageName("missing pagename") 00044 self.pagename = pagename 00045 self.readDefaultHDF = readDefaultHDF 00046 self._israwpage = israwpage 00047 self.context = context 00048 self._pageparms = parms 00049 00050 self._error_template = None 00051 00052 self.page_start_time = time.time() 00053 00054 if makePUT: 00055 context.environ['REQUEST_METHOD'] = 'PUT' 00056 00057 neo_cgi.cgiWrap(context.stdin, context.stdout, context.environ) 00058 neo_cgi.IgnoreEmptyFormVars(1) 00059 self.ncgi = neo_cgi.CGI() 00060 00061 if parseCGI: 00062 self.ncgi.parse() 00063 00064 self._path_num = 0 00065 domain = self.ncgi.hdf.getValue("CGI.ServerName","") 00066 domain = self.ncgi.hdf.getValue("HTTP.Host", domain) 00067 self.domain = domain 00068 00069 self.setPaths([self.ncgi.hdf.getValue("CGI.DocumentRoot","")]) 00070 00071 self._sent_headers = 0 00072 self._reply_headers = {} 00073 self._reply_code = 200 00074 00075 if self.ncgi.hdf.getValue("CGI.HTTPS", ""): 00076 self.http = "https://" 00077 else: 00078 self.http = "http://" 00079 00080 try: 00081 self.subclassinit() 00082 except: 00083 SHOULD_DISPLAY = 0 00084 DISPLAY_ERROR = 1 00085 00086 import handle_error 00087 handle_error.handleException("Display Failed!") 00088 ERROR_MESSAGE = handle_error.exceptionString() 00089 return 00090 00091 def __setitem__(self, key, value): 00092 self._reply_headers[string.lower(key)] = value 00093 self.ncgi.hdf.setValue("cgiout.other.%s" % key, "%s: %s" % (key, value)) 00094 00095 def __getitem__(self, key): 00096 return self._reply_headers[string.lower(key)] 00097 00098 def has_key(self, key): 00099 return self._reply_headers.has_key(string.lower(key)) 00100 00101 def subclassinit(self): 00102 pass 00103 00104 def clearPaths(self): 00105 self.ncgi.hdf.removeTree("hdf.loadpaths") 00106 00107 def setPaths(self, paths): 00108 for path in paths: 00109 self.ncgi.hdf.setValue("hdf.loadpaths.%d" % self._path_num, path) 00110 self._path_num = self._path_num + 1 00111 00112 def redirectUri(self,redirectTo): 00113 ncgi = self.ncgi 00114 if ncgi.hdf.getIntValue("Cookie.debug",0) == 1: 00115 ncgi.hdf.setValue("CGI.REDIRECT_TO",redirectTo) 00116 # ncgi.display("dbg/redirect.cs") 00117 00118 cs = neo_cs.CS(ncgi.hdf) 00119 self['Content-Type'] = "text/html" 00120 template = """ 00121 Redirect 00122 <br><br> 00123 <a href="<?cs var:CGI.REDIRECT_TO ?>"><?cs var:CGI.REDIRECT_TO ?></a> 00124 """ 00125 cs.parseStr(template) 00126 page = cs.render() 00127 00128 self.push(page) 00129 00130 self.push("<PRE>\n") 00131 self.push(neo_cgi.htmlEscape(ncgi.hdf.dump()) + "\n") 00132 self.push("</PRE>\n") 00133 raise DisplayDone() 00134 00135 self.context.setStatus(self, 302) 00136 self.ncgi.redirectUri(redirectTo) 00137 raise Redirected("redirected To: %s" % redirectTo) 00138 00139 ## ---------------------------------- 00140 ## methods to be overridden in subclass when necessary: 00141 00142 def setup(self): 00143 pass 00144 00145 def display(self): 00146 raise NoDisplayMethod("no display method present in %s" % repr(self)) 00147 00148 def main(self): 00149 hdf = self.ncgi.hdf 00150 00151 def __call(method): 00152 if method.im_func.func_code.co_argcount == 2: 00153 method(hdf) 00154 else: 00155 method() 00156 00157 __call(self.setup) 00158 00159 self.handle_actions() 00160 00161 __call(self.display) 00162 00163 ## ---------------------------------- 00164 00165 def handle_actions(self): 00166 hdf = self.ncgi.hdf 00167 #warn(hdf.writeString()) 00168 hdfobj = hdf.getObj("Query.Action") 00169 if hdfobj: 00170 firstchild = hdfobj.child() 00171 if firstchild: 00172 action = firstchild.name() 00173 if firstchild.next(): 00174 raise MultipleActionsError("multiple actions present!!!") 00175 00176 method_name = "Action_%s" % action 00177 method = getattr(self,method_name) 00178 if method.im_func.func_code.co_argcount == 2: 00179 apply(method,[hdf]) 00180 else: 00181 apply(method,[]) 00182 00183 def start(self): 00184 SHOULD_DISPLAY = 1 00185 if self._israwpage: 00186 SHOULD_DISPLAY = 0 00187 00188 ncgi = self.ncgi 00189 00190 if self.readDefaultHDF: 00191 try: 00192 if not self.pagename is None: 00193 ncgi.hdf.readFile("%s.hdf" % self.pagename) 00194 except: 00195 debug("Error reading HDF file: %s.hdf" % (self.pagename)) 00196 00197 DISPLAY_ERROR = 0 00198 ERROR_MESSAGE = "" 00199 # call page main function! 00200 try: 00201 self.main() 00202 except DisplayDone: 00203 SHOULD_DISPLAY = 0 00204 except Redirected: 00205 # catch redirect exceptions 00206 SHOULD_DISPLAY = 0 00207 except DisplayError, num: 00208 ncgi.hdf.setValue("Query.error", str(num)) 00209 if self._error_template: 00210 ncgi.hdf.setValue("Content", self._error_template) 00211 else: 00212 DISPLAY_ERROR = 1 00213 except: 00214 SHOULD_DISPLAY = 0 00215 DISPLAY_ERROR = 1 00216 00217 import handle_error 00218 handle_error.handleException("Display Failed!") 00219 ERROR_MESSAGE = handle_error.exceptionString() 00220 00221 if DISPLAY_ERROR: 00222 #print "Content-Type: text/html\n\n" 00223 00224 # print the page 00225 00226 self['Content-Type'] = "text/html" 00227 00228 # print the page 00229 self.push("<head>") 00230 self.push(''' 00231 <script type="text/javascript"> 00232 function toggleDebugInfo() { 00233 var tb = document.getElementById('%s'); 00234 if (tb == null) return; 00235 tb.style.display = tb.style.display ? '' : 'none'; 00236 } 00237 </script> 00238 <style type="text/css"> 00239 .cgitb {background: #E6EAF0; border: 1px solid #4D6180; direction: ltr;} 00240 .cgitb p {margin: 0.5em 0; padding: 5px 10px; text-align: left;} 00241 .cgitb ol {margin: 0} 00242 .cgitb li {margin: 0.25em 0;} 00243 .cgitb h1, .cgitb h2, .cgitb h3 {padding: 5px 10px; margin: 0; background: #4D6180; color: white;} 00244 .cgitb h1 {font-size: 1.3em;} 00245 .cgitb h2 {font-size: 1em; margin-top: 1em;} 00246 .cgitb h3 {font-size: 1em;} 00247 .cgitb .frames {margin: 0; padding: 0; color: #606060} 00248 .cgitb .frames li {display: block;} 00249 .cgitb .call {padding: 5px 10px; background: #A3B4CC; color: black} 00250 .cgitb .context {padding: 0; font-family: monospace; } 00251 .cgitb .context li {display: block; white-space: pre;} 00252 .cgitb .context li.highlight {background: #C0D3F0; color: black} 00253 .cgitb .variables {padding: 5px 10px; font-family: monospace;} 00254 .cgitb .variables li {display: inline;} 00255 .cgitb .variables li:after {content: ", ";} 00256 .cgitb .variables li:last-child:after {content: "";} 00257 .cgitb .exception {border: 1px solid #4D6180; margin: 10px} 00258 .cgitb .exception h3 {background: #4D6180; color: white;} 00259 .cgitb .exception p {color: black;} 00260 .cgitb .exception ul {padding: 0 10px; font-family: monospace;} 00261 .cgitb .exception li {display: block;} 00262 00263 .cgitb .buttons {margin: 0.5em 0; padding: 5px 10px;} 00264 .cgitb .buttons li {display: inline; margin: 0; padding: 0 0.25em;} 00265 </style> 00266 ''') 00267 00268 self.push("</head>") 00269 00270 self.push("<H1> Error in Page </H1>\n") 00271 self.push("A copy of this error report has been submitted to the developers. ") 00272 self.push("The details of the error report are below.") 00273 00274 self.push(handle_error.exceptionString()) 00275 00276 # print debug info always on page error... 00277 self.push("<HR>\n") 00278 self.push("<PRE>") 00279 self.push(neo_cgi.htmlEscape(ncgi.hdf.dump())) 00280 self.push("</PRE>") 00281 00282 00283 etime = time.time() - self.page_start_time 00284 ncgi.hdf.setValue("CGI.debug.execute_time","%f" % (etime)) 00285 #warn("excute_time", etime) 00286 00287 if SHOULD_DISPLAY and self.pagename: 00288 debug_output = ncgi.hdf.getIntValue("page.debug",ncgi.hdf.getIntValue("Cookie.debug",0)) 00289 00290 # hijack the built-in debug output method... 00291 if ncgi.hdf.getValue("Query.debug","") == ncgi.hdf.getValue("Config.DebugPassword","1"): 00292 ncgi.hdf.setValue("Config.DebugPassword","CSPage.py DEBUG hijack (%s)" % 00293 ncgi.hdf.getValue("Config.DebugPassword","")) 00294 debug_output = 1 00295 00296 if not debug_output: 00297 ncgi.hdf.setValue("Config.CompressionEnabled","1") 00298 else: 00299 ncgi.hdf.setValue("Config.CompressionEnabled","0") 00300 00301 # default display 00302 template_name = ncgi.hdf.getValue("Content","%s.cs" % self.pagename) 00303 # ncgi.hdf.setValue ("cgiout.charset", "utf-8"); 00304 00305 try: 00306 self.context.setStatus(self, 200) 00307 ncgi.display(template_name) 00308 self._sent_headers = 1 00309 except: 00310 self['Content-Type'] = 'text/html' 00311 self.push("CSPage: Error occured\n") 00312 import handle_error 00313 self.push("<pre>" + handle_error.exceptionString() + "</pre>") 00314 debug_output = 1 00315 00316 00317 # debug output 00318 if debug_output: 00319 self.push("<HR>\n") 00320 self.push("Execution Time: %5.3f<BR><HR>" % (etime)) 00321 self.push("<PRE>") 00322 self.push(neo_cgi.htmlEscape(ncgi.hdf.dump())) 00323 self.push("</PRE>") 00324 # ncgi.hdf.setValue("hdf.DEBUG",ncgi.hdf.dump()) 00325 # ncgi.display("debug.cs") 00326 00327 script_name = ncgi.hdf.getValue("CGI.ScriptName","") 00328 if script_name: 00329 script_name = string.split(script_name,"/")[-1] 00330 00331 log ("[%s] etime/dtime: %5.3f/%5.3f %s (%s)" % (self.domain, etime, time.time() - etime - self.page_start_time, script_name, self.pagename)) 00332 return self._reply_code 00333 00334 # a protected output function to catch the output errors that occur when 00335 # the server is either restarted or the user pushes the stop button on the 00336 # browser 00337 def output(self, str): 00338 try: 00339 if len(str) > 8196: 00340 import cStringIO 00341 fp = cStringIO.StringIO(str) 00342 while 1: 00343 data = fp.read(8196*8) 00344 if not data: break 00345 self.context.stdout.write(data) 00346 else: 00347 self.context.stdout.write(str) 00348 except IOError, reason: 00349 log("IOError: %s" % (repr(reason))) 00350 raise DisplayDone() 00351 00352 def done(self): 00353 if not self._sent_headers: self.error(500) 00354 self._sent_headers = 0 00355 00356 raise DisplayDone() 00357 00358 def push(self, data): 00359 if not self._sent_headers: 00360 headerdata = self.send_headers(dont_send=1) 00361 self.output(headerdata + data) 00362 else: 00363 self.output(data) 00364 00365 00366 def send_headers(self, dont_send=0): 00367 self._sent_headers = 1 00368 00369 message = gHTTPResponses[self._reply_code] 00370 00371 if self._reply_code != 200: 00372 #self['status'] = "%s %s" % (self._reply_code, message) 00373 #self.context.setStatus(self, self._reply_code) 00374 pass 00375 self.context.setStatus(self, self._reply_code) 00376 self['connection'] = 'close' 00377 00378 headers = [] 00379 #headers.append(self.response(self._reply_code)) 00380 for (key, value) in self._reply_headers.items(): 00381 headers.append('%s: %s' % (key, value)) 00382 headers.append('\r\n') 00383 00384 if dont_send == 0: 00385 self.push(string.join(headers, '\r\n')) 00386 else: 00387 return string.join(headers, '\r\n') 00388 00389 00390 def allQuery (self, s): 00391 l = [] 00392 if self.ncgi.hdf.getValue ("Query.%s.0" % s, ""): 00393 obj = self.ncgi.hdf.getChild ("Query.%s" % s) 00394 while obj: 00395 l.append(obj.value()) 00396 obj = obj.next() 00397 else: 00398 t = self.ncgi.hdf.getValue ("Query.%s" % s, "") 00399 if t: l.append(t) 00400 return l 00401 00402 00403 def error(self, code, reason=None): 00404 self._reply_code = code 00405 message = gHTTPResponses[code] 00406 s = DEFAULT_ERROR_MESSAGE % { 00407 'code': code, 'message': message, 'reason': reason 00408 } 00409 00410 # self['Content-Length'] = len(s) 00411 # self['Content-Type'] = 'text/html' 00412 00413 # self.push(s) 00414 self.context.stdout.write("Content-Type: text/html\n") 00415 self.context.setStatus(self, code) 00416 self.context.stdout.write("Status: %s\n" % code) 00417 self.context.stdout.write(s) 00418 # self.done() 00419 00420 raise DisplayDone() 00421 00422 00423 00424 gHTTPResponses = { 00425 100: "Continue", 00426 101: "Switching Protocols", 00427 200: "OK", 00428 201: "Created", 00429 202: "Accepted", 00430 203: "Non-Authoritative Information", 00431 204: "No Content", 00432 205: "Reset Content", 00433 206: "Partial Content", 00434 300: "Multiple Choices", 00435 301: "Moved Permanently", 00436 302: "Moved Temporarily", 00437 303: "See Other", 00438 304: "Not Modified", 00439 305: "Use Proxy", 00440 400: "Bad Request", 00441 401: "Unauthorized", 00442 402: "Payment Required", 00443 403: "Forbidden", 00444 404: "Not Found", 00445 405: "Method Not Allowed", 00446 406: "Not Acceptable", 00447 407: "Proxy Authentication Required", 00448 408: "Request Time-out", 00449 409: "Conflict", 00450 410: "Gone", 00451 411: "Length Required", 00452 412: "Precondition Failed", 00453 413: "Request Entity Too Large", 00454 414: "Request-URI Too Large", 00455 415: "Unsupported Media Type", 00456 500: "Internal Server Error", 00457 501: "Not Implemented", 00458 502: "Bad Gateway", 00459 503: "Service Unavailable", 00460 504: "Gateway Time-out", 00461 505: "HTTP Version not supported" 00462 } 00463 00464 # Default error message 00465 DEFAULT_ERROR_MESSAGE = string.join( 00466 ['', 00467 '<head>', 00468 '<title>%(code)d %(message)s</title>', 00469 '</head>', 00470 '<body>', 00471 '<h1>%(message)s</h1>', 00472 '<p>Error code %(code)d.', 00473 '<p>Message: %(message)s.', 00474 '<p>Reason:\n <pre>%(reason)s</pre>', 00475 '</body>', 00476 '' 00477 ], 00478 '\r\n' 00479 )