[ Previous ] [ Contents ] [ Index ] [ Next ]

Example 7: wincgi

The following example script is a simple emulation of the WebSite WinCGI interface.

This example can be found in the examples/tcl/wincgi.tcl file.

    
    #
    # Example 7: simple emulation of the WebSite WinCGI interface
    #
    # This Tcl script emulates the WinCGI interface of the WebSite server.
    # To use, move this file to your Tcl library directory (normally the
    # modules/tcl directory of the AOLserver directory), set the
    # following nsd.ini variables in the [ns\server\<server-name>\wincgi]
    # section, and restart the server.
    #
    # key     default    description
    # ---     -------    -----------
    # prefix  /cgi-win   URL prefix for WinCGI.
    # debug   off        Set to on to keep temp files for debugging.
    # gmtoff  0          Minutes West of GMT for the "GMT Offset" variable.
    # dir     c:\wincgi  Directory of WinCGI programs.
    #
    #
    # Note:  This script is unsupported and not a complete emulation of the
    # WebSite WinCGI interface.  In particular, not all the WinCGI variables
    # are set.  Full support for WinCGI will be incorporated into the nscgi
    # module in a future AOLserver release. 
    #
    
    #
    # Fetch the variables from the configuration file.
    #
    global WinCGI
    set WinCGI(section) "ns\\server\\[ns_info server]\\wincgi"
    if {[set WinCGI(prefix) [ns_config $WinCGI(section) prefix]] == ""} {
    	set WinCGI(prefix) /cgi-win
    }
    if {[set WinCGI(dir) [ns_config $WinCGI(section) dir]] == ""} {
    	set WinCGI(dir) [ns_info home]/$WinCGI(prefix)
    }
    if {[set WinCGI(gmtoff) [ns_config $WinCGI(section) gmtoff]] == ""} {
    	set WinCGI(gmtoff) 0
    }
    if {[set WinCGI(debug) [ns_config -bool $WinCGI(section) debug]] == ""} {
    	set WinCGI(debug) 0
    }
    
    
    
    
    
    #
    # Register the win-cgi procedure to handle requests for WinCGI executables.
    #
    ns_register_proc POST $WinCGI(prefix)/*.exe win-cgi
    ns_register_proc GET $WinCGI(prefix)/*.exe win-cgi
    
    
    #
    # win-cgi - The Tcl request procedure which emulates WinCGI.
    #
    proc win-cgi {conn ignored} {
    	global WinCGI
    
    	# The program is the second part of the WinCGI URL.
    	set args [join [split [ns_conn query $conn] &]]
    	set pgm [lindex [ns_conn urlv $conn] 1]
    	regsub -all {\+} $args " " args
    	foreach e [split $WinCGI(dir)/$pgm /] {
    		if {$e != ""} {lappend exec $e}
    	}
    	set exec [join $exec \\]
    	if ![file executable $exec] {
    		return [ns_returnnotfound $conn]
    	}
    
    	# WinCGI requires a few temporary files.
    	set ini [ns_tmpnam]
    	set inp [ns_tmpnam]
    	set out [ns_tmpnam]
    
    	# Copy the request content to the input file.
    	set fp [open $inp w]
    	ns_writecontent $conn $fp
    	set len [tell $fp]
    	close $fp
    
    	# Create the WinCGI variables .ini file.
    	set fp [open $ini w]
    	puts $fp {[CGI]}
    	puts $fp \
    "Request Protocol=HTTP/1.0
    Request Method=[ns_conn method $conn]
    Executable Path=$WinCGI(prefix)/$pgm
    Server Software=[ns_info name]/[ns_info version]
    Server Name=[ns_info name]
    Server Port=[ns_info version]
    Server Admin=[ns_config AOLserver WebMaster]
    CGI Version=CGI/1.2 (Win)
    Remote Address=[ns_conn peeraddr $conn]
    Authentication Method=Basic
    Authentication Realm=[ns_conn location $conn]
    Content Type=application/x-www-form-urlencoded
    Content Length=$len"
    	puts $fp ""
    	puts $fp {[System]}
    	puts $fp \
    "GMT Offset=$WinCGI(gmtoff)
    Debug Mode=Yes
    Output File=$out
    Content File=$inp"
    
    	# Set any POST or query form variables. 
    	puts $fp ""
    	puts $fp {[Form Literal]}
    	set form [ns_conn form $conn]
    	if {$form != ""} {
    		for {set i 0} {$i < [ns_set size $form]} {incr i} {
    			set key [ns_set key $form $i]
    			set value [ns_set value $form $i]
    			puts $fp "$key=$value"
    		}
    	}
    
    	# Set the accept headers and accumulate the extra headers.
    	puts $fp ""
    	puts $fp {[Accept]}
    	set headers [ns_conn headers $conn]
    	set extras ""
    	for {set i 0} {$i < [ns_set size $headers]} {incr i} {
    		set key [ns_set key $headers $i]
    		set ukey [string toupper $key]
    		set value [ns_set value $headers $i]
    		if {$ukey == "ACCEPT"} {
    			puts $fp "$value=Yes"
    		} elseif {$key != "CONTENT-LENGTH" && $key != "CONTENT-TYPE"} {
    			append extras "$key=$value\n"
    		}
    	}
    	puts $fp ""
    	puts $fp {[Extra Headers]}
    	puts $fp $extras
    	close $fp
    
    	# Execute the WinCGI program.
    	# NB:  "catch" the exec and open because a WinCGI
    	# program can be misbehaved, returning a non-zero
    	# exit status or not creating the output file.
    	catch {exec "$exec $ini $inp $out $args"}
    	if [catch {set fp [open $out]}] {
    		ns_returnerror $conn 500 "WinCGI exec failed"
    	} else {
    		set type text/html
    		set status 200
    		while {[gets $fp line] > 0} {
    			set line [string trim $line]
    			if {$line == ""} break
    			set head [split $line :]
    			set key [string tolower [string trim [lindex $head 0]]]
    			set value [string trim [lindex $head 1]]
    			if {$key == "content-type"} {
    				set type $value
    			} elseif {$key == "location"} {
    				set location $value
    			} elseif {$key == "status"} {
    				set status $status
    			}
    		}
    		set page [read $fp]
    		close $fp
    
    		if [info exists location] {
    			ns_returnredirect $conn $location
    		} else {
    			ns_return $conn $status $type $page
    		}
    	}
    
    	if $WinCGI(debug) {
    		ns_log Notice "CGI $pgm: ini: $ini, inp: $inp, out: $out"
    	} else {
    		ns_unlink -nocomplain $ini
    		ns_unlink -nocomplain $inp
    		ns_unlink -nocomplain $out
    	}
    }
    
    

Top of Page

[ Previous ] [ Contents ] [ Index ] [ Next ]
Copyright © 1998-99 America Online, Inc.