cgistarter.py
Go to the documentation of this file.
00001 #! /usr/bin/env python
00002 
00003 import os, sys, string, time, string
00004 import subprocess
00005 
00006 import roslib; roslib.load_manifest('webui')
00007 
00008 from pyclearsilver import httpResponses
00009 from pyclearsilver.log import *
00010 
00011 #debugfull()
00012 debugoff()
00013 
00014 
00015 try:
00016   import warnings
00017   warnings.resetwarnings()
00018   warnings.filterwarnings("ignore")
00019 except ImportError:
00020   pass
00021 
00022 import neo_cgi, neo_cs, neo_util
00023 
00024 from pyclearsilver import CSPage
00025 
00026 import mimetypes
00027 mimetypes.init(["/etc/mime.types"])
00028 
00029 
00030 gConfig = None
00031 def setConfig(config):
00032   global gConfig
00033   gConfig = config
00034 
00035   if not hasattr(gConfig, "gRequireUsername"): gConfig.gRequireUsername = 0
00036   if not hasattr(gConfig, "gDataFilePaths"): gConfig.gDataFilePaths = []
00037 
00038 
00039 def split_path(path):
00040   # strip off leading slash, it's no fun!
00041   return string.split(path, '/')[1:]
00042 
00043 def getPackagePath(pkg):
00044   cmd = ["rospack", "find", pkg]
00045   pkgpath = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].strip()
00046   return pkgpath
00047 
00048 
00049 class Page:
00050   def __init__(self, context):
00051     self.context = context
00052     self.cwd = None
00053 
00054   def setupvars(self):
00055 
00056     self.path = self.context.environ.get("PATH_INFO", '')
00057 
00058     script_name = self.context.environ.get("SCRIPT_NAME",'')
00059 
00060     ## handle the case where the site is located at '/'
00061     if not self.path:  
00062       self.path = script_name
00063       script_name = '/'
00064 
00065 
00066   def start(self):
00067     self.setupvars()
00068 
00069     self._path = self.path
00070 
00071     rpath = self._path
00072     if not rpath: rpath = '/'
00073 
00074     if rpath == "/": rpath = gConfig.gDefaultPage
00075 
00076     self.path = split_path(rpath)
00077 
00078     username = None
00079 
00080     if len(self.path) == 0:
00081       warn("no such path", self.path)
00082       self.error(404)
00083       return 404
00084 
00085     ## the url form should be:
00086     ##    /baseuri/username/module/script.py
00087 
00088     #cwd = os.getcwd()
00089     #cwd = self.cwd
00090     #warn("CWD", cwd)
00091 
00092     module = gConfig.gDefaultModule
00093 
00094     if hasattr(gConfig, "gDataFilePaths"):
00095       if self.path[0] in gConfig.gDataFilePaths:
00096         fn = apply(os.path.join, [self.cwd,] + self.path)
00097         return outputFile(self.context, fn)
00098 
00099     if gConfig.gRequireUsername:
00100       username = self.path[0]
00101       n = 1
00102     else:
00103       n = 0
00104 
00105     #warn("self.path", self.path)
00106 
00107     if len(self.path) > 1:
00108       module = self.path[n]
00109       n = n + 1
00110 
00111     modpath = None
00112     app_id = None
00113     taskid = None
00114     if module == "app":
00115       module, app_id = self.path[n:n+2]
00116       taskid = string.join([module, app_id], "/")
00117       n = n + 2
00118       
00119       modpath = os.path.join(getPackagePath(module), "src")
00120 
00121       fn = apply(os.path.join, [modpath] + [module] + self.path[n:])
00122       moduleRootPath = modpath
00123       handlerRoot = apply(os.path.join, [modpath, module, "cgibin"])
00124       moduleTemplatePath = apply(os.path.join, [modpath, module, "templates"])
00125     else:
00126       app_id = module
00127       moduleRootPath = apply(os.path.join, [self.cwd, "mod", module])
00128       handlerRoot = apply(os.path.join, [self.cwd, "mod", module, "cgibin"])
00129       moduleTemplatePath = apply(os.path.join, [self.cwd, "mod", module, "templates"])
00130 
00131       fn = apply(os.path.join, [self.cwd, moduleRootPath,] + self.path[n:])
00132 
00133     systemTemplatePath = apply(os.path.join, [self.cwd, "mod", "webui", "templates"])
00134     systemJLIBPath = apply(os.path.join, [self.cwd, "mod", "webui", "jslib"])
00135 
00136     #warn("fn", fn)
00137 
00138     ## if requesting a file, then just output it to the browser.
00139     if os.path.isfile(fn):
00140       return outputFile(self.context, fn)
00141 
00142     ## manage the Python module Path
00143     sys.path.insert(0, os.path.abspath(self.cwd))
00144     if modpath: sys.path.insert(0, os.path.abspath(modpath))
00145     sys.path.insert(0, os.path.abspath(moduleRootPath))
00146 
00147     #debug("sys.path", sys.path)
00148 
00149     handlerPath = ''
00150 
00151     ## find the first *real* file in the path
00152     ## the rest of the path becomes the pathinfo.
00153     m = n
00154     for m in range(len(self.path)-1, n-2, -1):
00155       handlerPath = apply(os.path.join, [handlerRoot, ] + self.path[n:m+1])
00156 
00157       if os.path.isdir(handlerPath):
00158         sys.path.insert(0, handlerPath)
00159       if os.path.isfile(handlerPath): break
00160       if os.path.isdir(handlerPath): break
00161 
00162     if m+1 == len(self.path):
00163       pathinfo = ''
00164     else:
00165       pathinfo = apply(os.path.join, self.path[m+1:])
00166 
00167     if os.path.isdir(handlerPath): 
00168       modulePath = handlerPath
00169       moduleFilename = app_id + "_index.py"
00170       handlerPath = os.path.join(self.cwd, modulePath, moduleFilename)
00171     else:
00172       modulePath, moduleFilename = os.path.split(handlerPath)
00173 
00174     if not os.path.isfile(handlerPath):
00175       self.error(404, handlerPath + " doesn't exist2")
00176       return 404
00177 
00178     import imp
00179 
00180     moduleName, ext = os.path.splitext(moduleFilename)
00181 
00182     #module = __import__(moduleName)
00183     if taskid:
00184       module = __import__("%s.cgibin.%s" % (module, moduleName, ), {}, {}, (None,))
00185     else:
00186       module = __import__("mod.%s.cgibin.%s" % (module, moduleName), {}, {}, (None,))
00187 
00188     page = module.run(self.context)
00189     
00190     proxy_path = page.ncgi.hdf.getValue("HTTP.Soap.Action", "")
00191     if proxy_path and not gConfig.gBaseURL.startswith(proxy_path):
00192       gConfig.gBaseURL = proxy_path + gConfig.gBaseURL
00193       gConfig.gROSURL = proxy_path + gConfig.gROSURL
00194 
00195     page.ncgi.hdf.setValue("CGI.BaseURI", gConfig.gBaseURL)
00196     if taskid:
00197       page.ncgi.hdf.setValue("CGI.taskid", taskid)
00198 
00199     if gConfig.gRequireUsername:
00200       page.ncgi.hdf.setValue("CGI.Username", username)
00201       page.username = username
00202 
00203     if hasattr(page, "checkLoginCookie"):
00204       nologin = page._pageparms.get("nologin", False)
00205 
00206       if not nologin:
00207         try:
00208           page.checkLoginCookie()
00209 
00210         except CSPage.Redirected:
00211           return
00212 
00213     page.ncgi.hdf.setValue("CGI.PathInfo", pathinfo)
00214     page.clearPaths()
00215     page.setPaths([moduleTemplatePath, systemTemplatePath, systemJLIBPath])
00216 
00217 
00218     ret = page.start()
00219 
00220 
00221     try: 
00222       page.db.close()
00223     except AttributeError: pass
00224 
00225     page = None
00226 
00227     return ret
00228 
00229   def error(self, ecode, reason=None):
00230     message = httpResponses.gHTTPResponses[ecode]
00231 
00232     template = httpResponses.errorMessage_Default
00233     if ecode == 404:
00234       template = httpResponses.errorMessage_404
00235 
00236     hdf = neo_util.HDF()
00237     hdf.setValue("code", str(ecode))
00238     if message: hdf.setValue("message", message)
00239     if reason: hdf.setValue("reason", reason)
00240 
00241     for key,val in self.context.environ.items():
00242       hdf.setValue("environ." + key, str(val))
00243 
00244     self.context.stdout.write("Content-Type: text/html\r\n")
00245     self.context.setStatus(None, ecode)
00246     self.context.stdout.write("Status: %s\r\n" % ecode)
00247     self.context.stdout.write("\r\n")
00248     
00249     cs = neo_cs.CS(hdf)
00250     cs.parseStr(template)
00251     page = cs.render()
00252 
00253     self.context.stdout.write(page)
00254 
00255     warn("Error", message, reason)
00256 
00257 
00258 def outputFile(context, fn):
00259   fp = open(fn, "rb")
00260   data = fp.read()
00261   fp.close()
00262 
00263   context.setStatus(None, 200)
00264 
00265   imagetype, encoding = mimetypes.guess_type(fn)
00266   debug("imagetype = %s  fn = %s" % (imagetype,fn))
00267 
00268   lines = []
00269 
00270   if imagetype:
00271     lines.append("Content-Type: %s" % imagetype)
00272 
00273   lines.append("Content-Length: %d" % len(data))
00274   
00275   stat = os.stat(fn)
00276   mtime = stat.st_mtime
00277   mod_str = time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime(mtime))
00278   
00279   lines.append('Last-Modified: %s GMT' % mod_str)
00280 
00281   expire_time = time.gmtime(time.time() + (360*24*3600))
00282   expire_str = time.strftime("%a, %d %b %Y %H:%M:%S", expire_time)
00283   lines.append('Expires: %s GMT' % expire_str)
00284 
00285   lines.append("\r\n")
00286   
00287   headers = string.join(lines, "\r\n")
00288   context.stdout.write(headers)
00289   
00290   context.stdout.write(data)
00291 
00292   return 200
00293 
00294 
00295 class FakeError:
00296   def __init__(self, req):
00297     self.req = req
00298   def write(self, s):
00299     from mod_python import apache
00300     self.req.log_error(s, apache.APLOG_WARNING)
00301 
00302 class ModPythonContext:
00303   def __init__ (self, req):
00304 
00305     from mod_python import apache
00306 
00307     self.stdout = apache.CGIStdout(req)
00308     self.stdin = apache.CGIStdin(req)
00309 
00310     self.stderr = FakeError(req)
00311     sys.stderr = self.stderr
00312     env = apache.build_cgi_env(req)
00313 
00314     self.environ = env
00315 
00316     scriptFilename = self.environ.get("SCRIPT_FILENAME", "")
00317     if scriptFilename:
00318       path, fn = os.path.split(scriptFilename)
00319       os.chdir(path)
00320 
00321   def setStatus(self, request, status):
00322     if request:
00323       request['status'] = str(status)
00324 
00325   
00326 def handler(req, cwd):
00327   start = time.time()
00328 
00329   from mod_python import apache
00330 
00331   if 1:
00332     context = ModPythonContext(req)
00333     page = Page(context)
00334     page.cwd = cwd
00335     page.mod_python_req = req 
00336     ret = page.start()
00337 
00338   ret = apache.OK
00339 
00340   end = time.time()
00341   #sys.stderr.write("handler time %s\n" % int((end-start)*1000))
00342 
00343   return ret
00344 
00345 
00346 def main(argv, stdout, environ):
00347   context = CSPage.Context()
00348   page = Page(context)
00349   page.start()
00350 
00351 
00352 if __name__ == "__main__":
00353   main(sys.argv, sys.stdout, os.environ)


webui
Author(s): Scott Hassan/hassan@willowgarage.com
autogenerated on Wed Apr 23 2014 10:36:00