#!/usr/bin/python # encoding: iso-8859-1 """ A simple CGI webserver with basic mod_rewrite support written in Python. Copyright (c) Phillip Berndt, 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. To view the whole GPL, go to http://www.gnu.org/licenses/gpl.txt """ import BaseHTTPServer, SimpleHTTPServer, CGIHTTPServer, signal, sys, os, re, urllib, shutil """ Settings """ "The htdocs directory." htdocs = "./" "File extensions associated with CGI executables" extensions = { "php": "\"C:\\Documents and Settings\\Amir\\Desktop\\network\\php server\\php-5\\php-cgi.exe\"", "pl": "/usr/bin/perl" } """ End of settings """ class RequestHandler(CGIHTTPServer.CGIHTTPRequestHandler): """ This is a customized CGIHTTPRequestHandler, which is able to execute CGI Scripts based upon file extensions. You'll have to set the class attributes "rewriteRules" and "extensions" before using this class. """ rewriteRules = [] extensions = {} def is_cgi(self): self.orginalPath = urllib.unquote(self.path) orginalURL = self.path url = self.path.split("?", 2) # Rewrite URL if a rule is matched for rewriteRule in self.rewriteRules: match = re.search(rewriteRule[0], url[0]) if match == None: continue url[0] = re.sub("(%s)" % rewriteRule[0], re.sub(r"\$([0-9])", lambda val: r"\%d" % (int(val.group(1)) + 1), rewriteRule[1]), url[0]) newUrl = url[0].split("?", 2) if len(newUrl) < 2 and len(url) == 2: newUrl.append(url[1]) elif len(newUrl) == 2 and len(url) == 2: newUrl[1] = "%s&%s" % (url[1], newUrl[1]) self.path = "?".join(newUrl) print "Rewrite from %s to %s" % (orginalURL, self.path) if len(rewriteRule) == 3 and rewriteRule[2].find("L"): break # Search for CGI executable if self.path.find("?") != -1: workPath = self.path[0:self.path.find("?")] else: workPath = self.path for extension in self.extensions: if workPath[-len(extension):].lower() == extension.lower(): self.cgiExecutable = self.extensions[extension] return True return False def run_cgi(self): try: # Set CGI environment variables env = { "GATEWAY_INTERFACE": "CGI/1.1", "SERVER_NAME": "Simple HTTP Server", "SERVER_SOFTWARE": "Simple HTTP Server", "SERVER_PROTOCOL": self.protocol_version, "REQUEST_METHOD": self.command, "PATH_INFO": self.path, "QUERY_STRING": self.path[self.path.find("?") + 1:], "REQUEST_URI": self.orginalPath, "REMOTE_ADDR": self.client_address[0] } if self.path.find("?") != -1: env["PATH_INFO"] = self.path[0:self.path.find("?")] else: env["QUERY_STRING"] = "" env["SCRIPT_NAME"] = env["PATH_INFO"] env["PATH_TRANSLATED"] = "./" + env["PATH_INFO"] if self.headers.typeheader is None: env['CONTENT_TYPE'] = self.headers.type else: env['CONTENT_TYPE'] = self.headers.typeheader length = self.headers.getheader('content-length') if length: env['CONTENT_LENGTH'] = length for header in self.headers: env['HTTP_' + header.upper()] = self.headers[header] os.environ.update(env) # Execute CGI print self.cgiExecutable + " " + env["PATH_TRANSLATED"].replace("/","\\") prog = os.popen3(self.cgiExecutable + " " + env["PATH_TRANSLATED"].replace("/","\\"), 'b') print prog[2].readline() if self.command.lower() == "post" and int(length) > 0: prog[0].write(self.rfile.read(int(length))) prog[0].close() firstLine = prog[1].readline() print firstLine if firstLine[0:6] == "Status": self.wfile.write(self.protocol_version + firstLine[7:-1] + "\r\n") elif firstLine[0:3] != "HTTP": self.wfile.write(self.protocol_version + " 200 Ok\r\n") self.wfile.write(firstLine) shutil.copyfileobj(prog[1], self.wfile) except: self.wfile.write("HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain\r\n\r\nCGI Error") if __name__ == "__main__": "Use default port 13000 or port given in cmd" if len(sys.argv) == 1: port = 13000 else: port = int(sys.argv[1]) "Change into the htdocs directory" os.chdir(htdocs) "Signal handler for save exit" def onSignal(sign, stack): sys.exit(0) signal.signal(signal.SIGINT, onSignal) "Load htaccess" if os.access(".htaccess", os.R_OK): print "Using htaccess" htaccessFile = open(".htaccess", "r").read() if re.search("RewriteEngine On", htaccessFile, re.IGNORECASE): rewriteRules = re.findall("^RewriteRule ([^ ]+) ([^ ]+)(?: (.*))?$", htaccessFile, re.MULTILINE) else: rewriteRules = [] else: rewriteRules = [] "Save settings" RequestHandler.rewriteRules = rewriteRules RequestHandler.extensions = extensions "Start httpd" httpd = BaseHTTPServer.HTTPServer(('', port), RequestHandler) httpd.serve_forever()