# kw_cgi.py - Enhanced CGI functionality
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# 01-27-97 ct7 Original Version
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

import sys
import traceback
import os
import cgi

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
# The IOtrap class is designed to emulate enough of a file class to act
# like stdout or stderr for print statements.  It stores everything that
# is written to it and then dumps it all later, on demand. The current
# implementation is very simplistic, slow, and probably won't work for
# binary data, but that can be fixed at a later date.
#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

class IOtrap:

	def __init__( self ):

		self.data = []

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def write( self, line ):

		self.data.append( line )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def writelines( self, list ):

		self.data = self.data + list

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def dump( self, file ):

		file.writelines( self.data )
		self.data = []

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

class CGI:

	def __init__( self ):

		# Trap stdout/stderr for later use

		iotrap = IOtrap()

		stdout = sys.stdout
		stderr = sys.stderr
		sys.stdout = iotrap
		sys.stderr = iotrap

		# set defaults

		self.environ = os.environ
		self._content_ = "text/html"
		self._headers_ = []

		# process the CGI, trapping exceptions

		try:
			errors = 0
			self.initialize()
			self.action()

		except:
			errors = 1

		# revert output to normal

		sys.stdout = stdout
		sys.stderr = stdout

		# print errors, if any

		if errors:
			print 'Content-type: text/plain'
			print
			print 'CGI error:'
			print
			traceback.print_exc()
			print
			print "-" * 60
			print
			print 'CGI instance variables:'
			print
			for key in dir(self):
				print "%-30s %s" % (key, self.__dict__[ key ])
			print
			print "-" * 60
			print

		# print HTTP headers

		print "Content-type: %s" % self._content_
		for line in self._headers_:
			print line
		print

		# print stored output

		iotrap.dump( stdout )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def initialize( self ):

		self._form_ = cgi.SvFormContentDict()
		self._args_ = {}
		for key in self._form_.keys():
			self._args_[ key ] = self._form_[ key ]
			# self._args_[ key ] = self._form_[ key ].value

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def debug( self ):

		cgi.print_form( self._form_ )
		cgi.print_environ()

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def get_arg( self, key, default=None ):

		if self._args_.has_key( key ):
			return self._args_[ key ]
		else:
			return default

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def set_content( self, content ):

		self._content_ = content

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def set_header( self, header, value ):

		self._headers_.append( "%s: %s" % ( header, value ) )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def redirect( self, location ):

		self.set_header( "Location", location )

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
	# The following methods are intended to be overridden
	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def action( self ):

		self.header()
		self.footer()

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def header( self ):

		print '<html>'
		print '<head><title>%s</title></head>' % self.environ[ 'SCRIPT_NAME' ]
		print '<body bgcolor="#ffffff">'

	#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

	def footer( self ):

		print '</body>'
		print '</html>'

#---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

if __name__ == "__main__":

	CGI()
