home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2009 May / maximum-cd-2009-05.iso / DiscContents / XBMC_for_Windows-8.10.exe / system / python / spyce / spyceWWW.py < prev    next >
Encoding:
Python Source  |  2008-11-03  |  9.8 KB  |  270 lines

  1. ##################################################
  2. # SPYCE - Python-based HTML Scripting
  3. # Copyright (c) 2002 Rimon Barr.
  4. #
  5. # Refer to spyce.py
  6. # CVS: $Id: spyceWWW.py 5659 2006-04-27 16:15:15Z jwnmulder $
  7. ##################################################
  8.  
  9. import sys, os, string, socket, BaseHTTPServer, SocketServer, StringIO, cgi
  10. import spyce, spyceConfig, spyceException, spyceCmd, spyceUtil
  11.  
  12. __doc__ = '''Self-standing Spyce web server.'''
  13.  
  14. ##################################################
  15. # Request / response handlers
  16. #
  17.  
  18. class spyceHTTPRequest(spyce.spyceRequest):
  19.   'HTTP Spyce request object. (see spyce.spyceRequest)'
  20.   def __init__(self, httpdHandler, documentRoot):
  21.     spyce.spyceRequest.__init__(self)
  22.     self._in = httpdHandler.rfile
  23.     self._headers = httpdHandler.headers
  24.     self._env = {}
  25.     self._env['REMOTE_ADDR'], self._env['REMOTE_PORT'] = httpdHandler.client_address
  26.     self._env['GATEWAY_INTERFACE'] = 'CGI/1.1'
  27.     self._env['REQUEST_METHOD'] = httpdHandler.command
  28.     self._env['REQUEST_URI'] = httpdHandler.path
  29.     self._env['PATH_INFO'] = httpdHandler.path
  30.     self._env['SERVER_SOFTWARE'] = 'spyce/%s' % spyce.__version__
  31.     self._env['SERVER_PROTOCOL'] = httpdHandler.request_version
  32.     # self._env['SERVER_ADDR'] ... '127.0.0.1'
  33.     # self._env['SERVER_PORT'] ... '80'
  34.     # self._env['SERVER_NAME'] ... 'mymachine.mydomain.com'
  35.     # self._env['SERVER_SIGNATURE'] ... ' Apache/1.3.22 Server at mymachine.mydomain.com Port 80'
  36.     # self._env['SERVER_ADMIN'] ... 'rimon@acm.org'
  37.     self._env['DOCUMENT_ROOT'] = documentRoot
  38.     self._env['QUERY_STRING'] = ''
  39.     i=string.find(httpdHandler.path, '?')
  40.     if i!=-1: self._env['QUERY_STRING'] = httpdHandler.path[i+1:]
  41.     self._env['CONTENT_LENGTH'] = self.getHeader('Content-Length')
  42.     self._env['CONTENT_TYPE'] = self.getHeader('Content-type')
  43.     self._env['HTTP_USER_AGENT'] = self.getHeader('User-Agent')
  44.     self._env['HTTP_ACCEPT'] = self.getHeader('Accept')
  45.     self._env['HTTP_ACCEPT_ENCODING'] = self.getHeader('Accept-Encoding')
  46.     self._env['HTTP_ACCEPT_LANGUAGE'] = self.getHeader('Accept-Language')
  47.     self._env['HTTP_ACCEPT_CHARSET'] = self.getHeader('Accept-Charset')
  48.     self._env['HTTP_COOKIE'] = self.getHeader('Cookie')
  49.     self._env['HTTP_REFERER'] = self.getHeader('Referer')
  50.     self._env['HTTP_HOST'] = self.getHeader('Host')
  51.     self._env['HTTP_CONNECTION'] = self.getHeader('Connection')
  52.     self._env['HTTP_KEEP_ALIVE'] = self.getHeader('Keep-alive')
  53.     # From ASP
  54.     # AUTH_TYPE, 
  55.     # APPL_PHYSICAL_PATH, 
  56.     # REMOTE_HOST,
  57.     # SERVER_PROTOCOL, 
  58.     # SERVER_SOFWARE
  59.   def env(self, name=None):
  60.     return spyceUtil.extractValue(self._env, name)
  61.   def getHeader(self, type=None):
  62.     if type: type=string.lower(type)
  63.     return spyceUtil.extractValue(self._headers.dict, type)
  64.   def getServerID(self):
  65.     return os.getpid()
  66.  
  67. class spyceHTTPResponse(spyceCmd.spyceCmdlineResponse):
  68.   'HTTP Spyce response object. (see spyce.spyceResponse)'
  69.   def __init__(self, httpdHandler):
  70.     self._httpheader = httpdHandler.request_version!='HTTP/0.9'
  71.     spyceCmd.spyceCmdlineResponse.__init__(self, spyceUtil.NoCloseOut(httpdHandler.wfile), sys.stdout, self._httpheader)
  72.     self._httpdHandler = httpdHandler
  73.     httpdHandler.log_request()
  74.   def sendHeaders(self):
  75.     if self._httpheader and not self.headersSent:
  76.       resultText = spyceUtil.extractValue(self.RETURN_CODE, self.returncode)
  77.       self.origout.write('%s %s %s\n' % (self._httpdHandler.request_version, self.returncode, resultText))
  78.       spyceCmd.spyceCmdlineResponse.sendHeaders(self)
  79.  
  80.   def close(self):
  81.     spyceCmd.spyceCmdlineResponse.close(self)
  82.     self._httpdHandler.request.close()
  83.  
  84. ##################################################
  85. # Spyce web server
  86. #
  87.  
  88. class myHTTPhandler(BaseHTTPServer.BaseHTTPRequestHandler):
  89.   def do_GET(self):
  90.     try:
  91.       # parse path
  92.       path = self.path
  93.       i=string.find(path, '?')
  94.       if i!=-1: path = path[:i]
  95.       path = os.path.normpath(path)
  96.       while path and (path[0]==os.sep or path[0:2]==os.pardir):
  97.         if path[0]==os.sep: path=path[1:]
  98.         if path[0:2]==os.pardir: path=path[2:]
  99.       path = os.path.join(self.server.documentRoot, path)
  100.       # find handler and process
  101.       if os.path.isdir(path):
  102.         return self.handler_dir(path)
  103.       else:
  104.         _, ext = os.path.splitext(path)
  105.         if ext: ext = ext[1:]
  106.         try:
  107.           handler = self.server.handler[ext]
  108.         except:
  109.           handler = self.server.handler[None]
  110.         return handler(self, path)
  111.     except IOError: 
  112.       pass
  113.   do_POST=do_GET
  114.   def handler_spyce(self, path):
  115.     # process spyce
  116.     request = spyceHTTPRequest(self, self.server.documentRoot)
  117.     response = spyceHTTPResponse(self)
  118.     result = spyce.spyceFileHandler(request, response, path)
  119.     response.close()
  120.   def handler_dump(self, path):
  121.     # process content to dump (with correct mime type)
  122.     f = None
  123.     try:
  124.       try:
  125.         f = open(path, 'r')
  126.       except IOError:
  127.         self.send_error(404, "No permission to open file")
  128.         return None
  129.       try:
  130.         _, ext = os.path.splitext(path)
  131.         if ext: ext=ext[1:]
  132.         mimetype = self.server.mimeTable[ext]
  133.       except:
  134.         mimetype = "application/octet-stream"
  135.       self.send_response(200)
  136.       self.send_header("Content-type", mimetype)
  137.       self.end_headers()
  138.       self.wfile.write(f.read())
  139.       self.request.close()
  140.     finally:
  141.       try:
  142.         if f: f.close()
  143.       except: pass
  144.   def handler_dir(self, path):
  145.     # process directory
  146.     if(self.path[-1:]!='/'):
  147.       self.send_response(301)
  148.       self.send_header('Location', self.path+'/')
  149.       self.end_headers()
  150.       return
  151.     try:
  152.       list = os.listdir(path)
  153.     except os.error:
  154.       self.send_response(404)
  155.       self.end_headers()
  156.       self.request.close()
  157.       return
  158.     list.sort(lambda a, b: cmp(a.lower(), b.lower()))
  159.     f = StringIO.StringIO()
  160.     f.write("<title>Directory listing for %s</title>\n" % self.path)
  161.     f.write("<h2>Directory listing for %s</h2>\n" % self.path)
  162.     f.write("<hr>\n<ul>\n")
  163.     for name in list:
  164.       fullname = os.path.join(path, name)
  165.       displayname = linkname = name = cgi.escape(name)
  166.       # Append / for directories or @ for symbolic links
  167.       if os.path.isdir(fullname):
  168.         displayname = name + "/"
  169.         linkname = name + "/"
  170.       elif os.path.islink(fullname):
  171.         displayname = name + "@"
  172.         # Note: a link to a directory displays with @ and links with /
  173.       f.write('<li><a href="%s">%s</a>\n' % (linkname, displayname))
  174.     f.write("</ul>\n<hr>\n")
  175.     f.seek(0)
  176.     self.send_response(200)
  177.     self.send_header("Content-type", "text/html")
  178.     self.end_headers()
  179.     self.wfile.write(f.getvalue())
  180.  
  181. def buildMimeTable(files):
  182.   mimetable = {}
  183.   for file in files:
  184.     try:
  185.       f = None
  186.       try:
  187.         f = open(file, 'r')
  188.         print "#   MIME file: "+file
  189.         line = f.readline()
  190.         while line:
  191.           if line[0]=='#': 
  192.             line = f.readline(); continue
  193.           line = string.strip(line)
  194.           if not line:
  195.             line = f.readline(); continue
  196.           line = string.replace(line, '\t', ' ')
  197.           items = filter(None, map(string.strip, string.split(line, ' ')))
  198.           mimetype, extensions = items[0], items[1:]
  199.           for ext in extensions:
  200.             mimetable[ext] = mimetype
  201.           line = f.readline()
  202.       except IOError: pass
  203.     finally:
  204.       try:
  205.         if f: f.close()
  206.       except: pass
  207.   return mimetable
  208.  
  209. def buildHandlerTable(handler, server):
  210.   for ext in handler.keys():
  211.     handler[ext] = eval('server.handler_'+handler[ext])
  212.   return handler
  213.  
  214. def spyceHTTPserver(port, root, config_file=None, daemon=None):
  215.   os.environ[spyce.SPYCE_ENTRY] = 'www'
  216.   spyceCmd.showVersion()
  217.   print '# Starting web server'
  218.   # test for threading support, if needed
  219.   try:
  220.     server = spyce.getServer(
  221.       config_file=config_file, 
  222.       overide_www_port=port, 
  223.       overide_www_root=root)
  224.   except (spyceException.spyceForbidden, spyceException.spyceNotFound), e:
  225.     print e
  226.     return
  227.   if server.concurrency==spyceConfig.SPYCE_CONCURRENCY_THREAD:
  228.     spyceUtil.ThreadedWriter()  # will raise exception if 'import thread' fails
  229.   # determine type of server concurrency
  230.   serverSuperClass = {
  231.     spyceConfig.SPYCE_CONCURRENCY_SINGLE: SocketServer.TCPServer,
  232.     spyceConfig.SPYCE_CONCURRENCY_FORK:   SocketServer.ForkingTCPServer,
  233.     spyceConfig.SPYCE_CONCURRENCY_THREAD: SocketServer.ThreadingTCPServer,
  234.   } [server.concurrency]
  235.   class sharedSocketServer(serverSuperClass):
  236.     def server_bind(self):
  237.       self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  238.       SocketServer.TCPServer.server_bind(self)
  239.   try:
  240.     # initialize server
  241.     try:
  242.       httpd = sharedSocketServer(('',server.config.getSpyceWWWPort()), myHTTPhandler)
  243.       print '# Server Port: %d' % server.config.getSpyceWWWPort()
  244.       httpd.documentRoot = os.path.abspath(server.config.getSpyceWWWRoot())
  245.       print '# Server Root: '+httpd.documentRoot
  246.       httpd.mimeTable = buildMimeTable(server.config.getSpyceWWWMime())
  247.       httpd.handler = buildHandlerTable(server.config.getSpyceWWWHandler(), myHTTPhandler)
  248.     except:
  249.       print 'Unable to start server on port %s' % server.config.getSpyceWWWPort()
  250.       return -1
  251.     # daemonize
  252.     if daemon:
  253.       print '# Daemonizing process.'
  254.       try:
  255.         spyceCmd.daemonize(pidfile=daemon)
  256.       except SystemExit: # expected
  257.         return 0
  258.     # process requests
  259.     print '# Ready.'
  260.     while 1:
  261.       try:
  262.         httpd.handle_request()
  263.       except KeyboardInterrupt: raise
  264.       except:
  265.         print 'Error: %s' % spyceUtil.exceptionString()
  266.   except KeyboardInterrupt:
  267.     print 'Break!'
  268.   return 0
  269.  
  270.