#!/usr/bin/python

import os
import sys
from StringIO import StringIO
from email import message_from_file
import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler

import cgitb; cgitb.enable()

class CGIServer:

    '''
    This class exists to stuff data from the CGI environment into a
    child class of BaseHTTPRequestHandler. The idea is to not have to
    write different code depending on whether the program is a CGI or
    not -  *always* create a BaseHTTPRequestHandler child.
    
    Use it just like BaseHTTPServer:

    httpd = CGIServer(('', 8000), handler_class)
    httpd.serve_forever()

    '''

    def __init__(self, server_address, RequestHandlerClass):
        # nothing to do with server_address, we don't use it
	if not issubclass(RequestHandlerClass, SocketServer.StreamRequestHandler):
	    raise Error("class %s is not a SocketServer.StreamRequestHandler or BaseHTTPHandler")
        self.RequestHandlerClass = RequestHandlerClass
        self.connection = self

    def makefile(self, mode, bufsize):
        ''' so SocketServer doesn't puke '''
        if 'w' in mode:
	    return sys.stdout
	elif 'r' in mode:
            env = os.environ
            body = ''

            # Reconstruct the inputs from the CGI environment
            s  = env['REQUEST_METHOD']+' '+env['REQUEST_URI']+' '+env['SERVER_PROTOCOL']+'\r\n'
            if env.has_key('CONTENT_TYPE'):
                s += 'Content-type: ' + env['CONTENT_TYPE']+'\r\n'
            if env.has_key('CONTENT_LENGTH'):
                s += 'Content-length: ' + env['CONTENT_LENGTH']+'\r\n'
        	body = sys.stdin.read(int(env['CONTENT_LENGTH']))
            for k in env.keys():
                if k[:5] == 'HTTP_':
 	            s += k[5]+k[6:].lower() +': ' + env[k] + '\r\n'
            s += '\r\n'
            s += body
	    sys.stderr.write("makefile(r) returning:\n%s\n--end of makefile()--\n" % s)
            return StringIO(s) 

    def handle_request(self):
	# create a RequestHandlerClass object and set it up
	client_address = (os.environ['REMOTE_ADDR'], os.environ['REMOTE_PORT'])
        self.RequestHandlerClass(self, client_address, self)
    
    def serve_forever(self):
        """This is for compatability with SimpleHTTPServer"""
	sys.stderr.write("WARNING: %s called .serve_forever(), but it's a CGI! " % sys.argv[0])
	sys.stderr.write("To remove this warning, call .handle_request() instead.\n")
        self.handle_request()




class MyBaseHTTPRequestHandler(BaseHTTPRequestHandler):
    
    def emailMessageGlue(self, fh, seekable=1):
        '''
	    This glue function does several things:
	        * simulates a call to the class constructor of the 
		  old mimetools.Message class, so as not to break
		  existing BaseHTTP* code.
		* replaces BaseHTTP*'s use of mimetools.Message with
		  the newer email.Message
		* uses cgi.parse_qs() to parse all available CGI
		  vars (in the body of the POST if it's a POST, and
		  in the query string)
	'''
        import cgi  # needed for parse_qs b/c no one else does it!
        from email.Parser import Parser
        m = Parser().parse(fh)
	self.postvars = cgi.parse_qs(m.get_payload())
	self.getvars = cgi.parse_qs(os.environ['QUERY_STRING'])
        return m # it gets stored in self.headers, which is a bit of a misnomer, but oh well

    MessageClass = emailMessageGlue



class HelloWorldHandler(MyBaseHTTPRequestHandler):

    def do_GET(self):
        self.do_POST()

    def do_POST(self):
        content  =  "Content-type: text/html\n\n"
	content += '''
	<form method=POST>
	<input type=hidden name=foo value='bar'>
	<input type=submit name=button value='press'>
	</form>
	<hr>
	<form method=POST action='?baz=bal'>
	<input type=hidden name=foo value='bar'>
	<input type=submit name=button1 value='press1'>
	</form>
	<hr><code>
	'''
	content += "<p>client_address: %s\n" % repr(self.client_address)
	content += "<p>command: %s\n" % repr(self.command)
	content += "<p>path: %s\n" % repr(self.path)
	content += "<p>request_version: %s\n" % repr(self.request_version)
	for h in self.headers.keys():
	    content += "<p>header %s: %s\n" % (h, self.headers.get(h))
	content += "<p>as_string: %s\n" % repr(self.headers.as_string())
	content += "<p>type: %s\n" % repr(self.headers.get_content_type())
	content += "<p>POST data:\n<ul>\n"
	for k in self.postvars.keys():
	    content += "<li>%s: %s\n" % (k, repr(self.postvars[k]))
	content += "</ul>\n"
	content += "<p>GET data:\n<ul>\n"
	for k in self.getvars.keys():
	    content += "<li>%s: %s\n" % (k, repr(self.getvars[k]))
	content += "</ul>"
	content += "</code><hr>"

	self.wfile.write(content)


def test():

    s = CGIServer(('', 8080), HelloWorldHandler)
    #s.serve_forever()
    s.handle_request()

if __name__ == '__main__':
    test()

