home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / xbmc-9.11.exe / system / python / spyce / spyceCmd.py < prev    next >
Encoding:
Python Source  |  2009-12-23  |  11.4 KB  |  337 lines

  1. #!/usr/bin/env python
  2.  
  3. ##################################################
  4. # SPYCE - Python-based HTML Scripting
  5. # Copyright (c) 2002 Rimon Barr.
  6. #
  7. # Refer to spyce.py
  8. # CVS: $Id: spyceCmd.py 16779 2008-12-31 04:41:27Z monkeyman_67156 $
  9. ##################################################
  10.  
  11. import getopt, sys, traceback, os, string, glob, copy
  12. import spyce, spyceException, spyceUtil
  13.  
  14. __doc__ = '''Command-line and CGI-based Spyce entry point.'''
  15.  
  16. ##################################################
  17. # Output
  18. #
  19.  
  20. # output version
  21. def showVersion(out=sys.stdout):
  22.   "Emit version information."
  23.   out.write('spyce v'+spyce.__version__+', by Rimon Barr: ')
  24.   out.write('Python Server Pages\n')
  25.  
  26. # output syntax
  27. def showUsage(out=sys.stdout):
  28.   "Emit command-line usage information."
  29.   showVersion(out)
  30.   out.write('Command-line usage:\n')
  31.   out.write('  spyce [-c] [-o filename.html] <filename.spy>\n')
  32.   out.write('  spyce [-w] <filename.spy>              <-- CGI\n')
  33.   out.write('  spyce -O filename(s).spy               <-- batch process\n')
  34.   out.write('  spyce -l [-p port] [-d file ] [<root>] <-- proxy server\n')
  35.   out.write('  spyce -h | -v\n')
  36.   out.write('    -h, -?, --help       display this help information\n')
  37.   out.write('    -v, --version        display version\n')
  38.   out.write('    -o, --output         send output to given file\n')
  39.   out.write('    -O                   send outputs of multiple files to *.html\n')
  40.   out.write('    -c, --compile        compile only; do not execute\n')
  41.   out.write('    -w, --web            cgi mode: emit headers (or use run_spyceCGI.py)\n')
  42.   out.write('    -q, --query          set QUERY_STRING environment variable\n')
  43.   out.write('    -l, --listen         run in HTTP server mode\n')
  44.   out.write('    -d, --daemon         run as a daemon process with given pidfile\n')
  45.   out.write('    -p, --port           listen on given port, default 80\n')
  46.   out.write('    --conf [file]        Spyce configuration file\n')
  47.   out.write('To configure Apache, please refer to: spyceApache.conf\n')
  48.   out.write('For more details, refer to the documentation.\n')
  49.   out.write('  http://spyce.sourceforge.net\n')
  50.   out.write('Send comments, suggestions and bug reports to <rimon-AT-acm.org>.\n')
  51.  
  52. ##################################################
  53. # Request / Response handlers
  54. #
  55.  
  56. class spyceCmdlineRequest(spyce.spyceRequest):
  57.   'CGI/Command-line Spyce request object. (see spyce.spyceRequest)'
  58.   def __init__(self, input, env, filename):
  59.     spyce.spyceRequest.__init__(self)
  60.     self._in = input
  61.     self._env = copy.copy(env)
  62.     if not self._env.has_key('SERVER_SOFTWARE'):
  63.       self._env['SERVER_SOFTWARE'] = 'spyce %s Command-line' % spyce.__version__
  64.     if not self._env.has_key('REQUEST_URI'): 
  65.       self._env['REQUEST_URI']=filename
  66.     if not self._env.has_key('REQUEST_METHOD'): 
  67.       self._env['REQUEST_METHOD']='spyce'
  68.     if not self._env.has_key('QUERY_STRING'): 
  69.       self._env['QUERY_STRING']=''
  70.     self._headers = {
  71.       'Content-Length': self.env('CONTENT_LENGTH'),
  72.       'Content-Type': self.env('CONTENT_TYPE'),
  73.       'User-Agent': self.env('HTTP_USER_AGENT'),
  74.       'Accept': self.env('HTTP_ACCEPT'),
  75.       'Accept-Encoding': self.env('HTTP_ACCEPT_ENCODING'),
  76.       'Accept-Language': self.env('HTTP_ACCEPT_LANGUAGE'),
  77.       'Accept-Charset': self.env('HTTP_ACCEPT_CHARSET'),
  78.       'Cookie': self.env('HTTP_COOKIE'),
  79.       'Referer': self.env('HTTP_REFERER'),
  80.       'Host': self.env('HTTP_HOST'),
  81.       'Connection': self.env('HTTP_CONNECTION'),
  82.       'Keep-Alive': self.env('HTTP_KEEP_ALIVE'),
  83.     }
  84.   def env(self, name=None):
  85.     return spyceUtil.extractValue(self._env, name)
  86.   def getHeader(self, type=None):
  87.     return spyceUtil.extractValue(self._headers, type)
  88.   def getServerID(self):
  89.     return os.getpid()
  90.  
  91. class spyceCmdlineResponse(spyce.spyceResponse):
  92.   'CGI/Command-line Spyce response object. (see spyce.spyceResponse)'
  93.   def __init__(self, out, err, cgimode=0):
  94.     spyce.spyceResponse.__init__(self)
  95.     if not cgimode:
  96.       self.RETURN_OK = 0
  97.       self.RETURN_CODE[self.RETURN_OK] = 'OK'
  98.     self.origout = out
  99.     self.out = spyceUtil.BufferedOutput(out)
  100.     self.err = err
  101.     self.cgimode = cgimode
  102.     self.headers = []
  103.     self.headersSent = 0
  104.     self.CT = None
  105.     self.returncode = self.RETURN_OK
  106.     # functions (for performance)
  107.     self.write = self.out.write
  108.     self.writeErr = self.err.write
  109.     self.clear = self.out.clear
  110.   def close(self):
  111.     self.flush()
  112.     self.out.close()
  113.   def sendHeaders(self):
  114.     if self.cgimode and not self.headersSent:
  115.       resultText = spyceUtil.extractValue(self.RETURN_CODE, self.returncode)
  116.       self.origout.write('Status: %3d "%s"\n' % (self.returncode, resultText))
  117.       if not self.CT:
  118.         self.setContentType('text/html')
  119.       self.origout.write('Content-Type: %s\n' % self.CT)
  120.       for h in self.headers:
  121.         self.origout.write('%s: %s\n'%h)
  122.       self.origout.write('\n')
  123.       self.headersSent = 1
  124.   def clearHeaders(self):
  125.     if self.headersSent:
  126.       raise 'headers already sent'
  127.     self.headers = []
  128.   def setContentType(self, content_type):
  129.     if self.headersSent:
  130.       raise 'headers already sent'
  131.     self.CT = content_type
  132.   def setReturnCode(self, code):
  133.     if self.headersSent:
  134.       raise 'headers already sent'
  135.     self.returncode = code
  136.   def addHeader(self, type, data, replace=0):
  137.     if self.headersSent:
  138.       raise 'headers already sent'
  139.     if type=='Content-Type':
  140.       self.setContentType(data)
  141.     else:
  142.       if replace:
  143.         self.headers = filter(lambda (type, _), t2=type: type!=t2, self.headers)
  144.       self.headers.append((type, data))
  145.   def flush(self, stopFlag=0):
  146.     if stopFlag: return
  147.     self.sendHeaders()
  148.     self.out.flush()
  149.   def unbuffer(self):
  150.     self.sendHeaders()
  151.     self.out.unbuffer()
  152.  
  153. ##################################################
  154. # Daemonizing
  155. #
  156.  
  157. def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null', pidfile=None):
  158.   '''Forks current process into a daemon. stdin, stdout, and stderr arguments 
  159.   are file names that are opened and used in place of the standard file descriptors
  160.   in sys.stdin, sys.stdout, and sys.stderr, which default to /dev/null.
  161.   Note that stderr is unbuffered, so output may interleave with unexpected order
  162.   if shares destination with stdout.'''
  163.   def forkToChild():
  164.     try: 
  165.       if os.fork()>0: sys.exit(0) # exit parent.
  166.     except OSError, e: 
  167.       sys.stderr.write("fork failed: (%d) %s\n" % (e.errno, e.strerror))
  168.       sys.exit(1)
  169.   # First fork; decouple
  170.   forkToChild()
  171.   os.chdir("/") 
  172.   os.umask(0) 
  173.   os.setsid() 
  174.   # Second fork; create pidfile; redirect descriptors
  175.   forkToChild()
  176.   pid = str(os.getpid())
  177.   if pidfile: 
  178.     f = open(pidfile,'w+')
  179.     f.write("%s\n" % pid)
  180.     f.close()
  181.   si = open(stdin, 'r')
  182.   so = open(stdout, 'a+')
  183.   se = open(stderr, 'a+', 0)
  184.   os.dup2(si.fileno(), sys.stdin.fileno())
  185.   os.dup2(so.fileno(), sys.stdout.fileno())
  186.   os.dup2(se.fileno(), sys.stderr.fileno())
  187.   # I am a daemon!
  188.  
  189. ##################################################
  190. # Command-line entry point
  191. #
  192.  
  193. #for debugging/profiling only
  194. #sys.stdout = spyceUtil.NoCloseOut(sys.stdout)
  195.  
  196. def spyceMain(cgimode=0, cgiscript=None, 
  197.     stdout=sys.stdout, stdin=sys.stdin, stderr=sys.stderr, environ=os.environ):
  198.   "Command-line and CGI entry point."
  199.   # defaults
  200.   compileonlyMode = 0
  201.   outputFilename = None
  202.   defaultOutputFilename = 0
  203.   httpmode = 0
  204.   httpport = None
  205.   httproot = None
  206.   daemon = None
  207.   configFile = None
  208.   # parse options
  209.   if cgimode and cgiscript:
  210.     args = [cgiscript]
  211.   else:
  212.     try:
  213.       opts, args = getopt.getopt(sys.argv[1:], 'h?vco:Owq:ld:p:',
  214.         ['help', 'version', 'compile', 'output=', 'web', 
  215.          'query=', 'listen', 'daemon=', 'port=', 'conf=',])
  216.     except getopt.error: 
  217.       if cgimode:
  218.         stdout.write('Content-Type: text/plain\n\n')
  219.       stdout.write('syntax: unknown switch used\n')
  220.       stdout.write('Use -h option for help.\n')
  221.       return -1
  222.     for o, a in opts:
  223.       if o in ("-v", "--version"):
  224.         showVersion(); return
  225.       if o in ("-h", "--help", "-?"):
  226.         showUsage(); return
  227.       if o in ("-c", "--compileonly"):
  228.         compileonlyMode = 1
  229.       if o in ("-o", "--output"):
  230.         outputFilename = a
  231.       if o in ("-O", ):
  232.         defaultOutputFilename = 1
  233.       if o in ("-w", "--web"):
  234.         cgimode = 1
  235.       if o in ("-q", "--query"):
  236.         environ['QUERY_STRING'] = a
  237.       if o in ("-l", "--listen"):
  238.         httpmode = 1
  239.       if o in ("-d", "--daemon"):
  240.         daemon = a
  241.       if o in ("-p", "--port"):
  242.         try: httpport = int(a)
  243.         except:
  244.           stdout.write('syntax: port must be integer\n')
  245.           stdout.write('Use -h option for help.\n')
  246.           return -1
  247.       if o in ("--conf", ):
  248.         configFile = a
  249.  
  250.   # web server mode
  251.   if httpmode:
  252.     if len(args):
  253.       httproot = args[0]
  254.     import spyceWWW
  255.     return spyceWWW.spyceHTTPserver(httpport, httproot, config_file=configFile, daemon=daemon)
  256.   # some checks
  257.   if not cgimode and not defaultOutputFilename and len(args)>1:
  258.     stdout.write('syntax: too many files to process\n')
  259.     stdout.write('Use -h option for help.\n')
  260.     return -1
  261.   # file globbing
  262.   if defaultOutputFilename:
  263.     globbed = map(glob.glob, args)
  264.     args = []
  265.     for g in globbed:
  266.       for f in g:
  267.         args.append(f)
  268.   if not len(args):
  269.     if cgimode:
  270.       stdout.write('Content-Type: text/plain\n\n')
  271.     stdout.write('syntax: please specify a spyce file to process\n')
  272.     stdout.write('Use -h option for help.\n')
  273.     return -1
  274.   # run spyce
  275.   result=0
  276.   try:
  277.     while len(args):
  278.       result=0
  279.       script = args[0]
  280.       del args[0]
  281.       if cgimode:
  282.         dir = os.path.dirname(script)
  283.         if dir: 
  284.           script = os.path.basename(script)
  285.           os.chdir(dir)
  286.       try:
  287.         output = stdout
  288.         if defaultOutputFilename:
  289.           outputFilename = os.path.splitext(script)[0]+'.html'
  290.           stdout.write('Processing: %s\n'%script)
  291.           stdout.flush()
  292.         if outputFilename:
  293.           output = None
  294.           output = open(outputFilename, 'w')
  295.         if compileonlyMode:
  296.           s = spyce.getServer().spyce_cache['file', script]
  297.           output.write(s.getCode())
  298.           output.write('\n')
  299.         else:
  300.           request = spyceCmdlineRequest(stdin, environ, script)
  301.           response = spyceCmdlineResponse(output, stderr, cgimode)
  302.           result = spyce.spyceFileHandler(request, response, script)
  303.           response.close()
  304.       except KeyboardInterrupt: raise
  305.       except SystemExit: pass
  306.       except (spyceException.spyceForbidden, spyceException.spyceNotFound), e:
  307.         if cgimode:
  308.           stdout.write('Content-Type: text/plain\n\n')
  309.         stdout.write(str(e)+'\n')
  310.       except:
  311.         if cgimode:
  312.           stdout.write('Content-Type: text/plain\n\n')
  313.         stdout.write(spyceUtil.exceptionString()+'\n')
  314.       if output:
  315.         output.close()
  316.   except KeyboardInterrupt:
  317.     stdout.write('Break!\n')
  318.   return result
  319.  
  320. ABSPATH = 1
  321. if ABSPATH:
  322.   for i in range(len(sys.path)):
  323.     sys.path[i] = os.path.abspath(sys.path[i])
  324.   ABSPATH = 0
  325.  
  326. # Command-line entry point
  327. if __name__=='__main__': 
  328.   os.environ[spyce.SPYCE_ENTRY] = 'cmd'
  329.   try:
  330.     exitcode=0
  331.     exitcode=spyceMain(cgimode=0)
  332.   except: 
  333.     exitcode=1
  334.     traceback.print_exc()
  335.   sys.exit(exitcode)
  336.  
  337.