| # |
| # script.ws3 -- the commands of websh3 that are implemented as Tcl scripts |
| # nca-073-9 |
| # |
| # Copyright (C) 1996-2000 by Netcetera AG. |
| # Copyright (C) 2001 by Apache Software Foundation. |
| # All rights reserved. |
| # |
| # See the file "license.terms" for information on usage and |
| # redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
| # |
| # @(#) $Id$ |
| # |
| |
| #----------------------------------------------------------------------------- |
| # namespace init (make sure web:: exists) |
| #----------------------------------------------------------------------------- |
| namespace eval web {} |
| |
| #----------------------------------------------------------------------------- |
| # web::putxfile |
| #----------------------------------------------------------------------------- |
| proc web::putxfile {file {channel ""} {vmsg ""}} { |
| |
| if {[string length $vmsg]} { |
| upvar $vmsg msg |
| } |
| if {[string length $channel]} { |
| # file is actually the channel and channel is the file |
| if {[web::readfile $channel content msg]} { |
| return 1 |
| } |
| return [catch {uplevel [list web::putx $file $content]} msg] |
| } else { |
| if {[web::readfile $file content msg]} { |
| return 1 |
| } |
| return [catch {uplevel [list web::putx $content]} msg] |
| } |
| } |
| |
| #----------------------------------------------------------------------------- |
| # web::readfile |
| #----------------------------------------------------------------------------- |
| proc web::readfile {name vtarget {vmsg ""}} { |
| |
| upvar $vtarget target |
| if {[string length $vmsg]} { |
| upvar $vmsg msg |
| } |
| return [catch { |
| set fh [open $name r] |
| set target [read $fh] |
| close $fh |
| } msg] |
| } |
| |
| #----------------------------------------------------------------------------- |
| # web_include |
| #----------------------------------------------------------------------------- |
| proc web::include {name {vmsg ""}} { |
| |
| if {[string length $vmsg]} { |
| upvar $vmsg msg |
| } |
| if {![file exists $name]} { |
| set so "$name[info sharedlibextension]" |
| if {[file exists $so]} { |
| return [catch {uplevel [list load $so]} msg] |
| } |
| } |
| return [catch {uplevel [list source $name]} msg] |
| } |
| |
| #----------------------------------------------------------------------------- |
| # web::match |
| # 1: string to be returned if $val exists in $list |
| # 2: list to be searched for $val |
| # 3: string to search |
| #----------------------------------------------------------------------------- |
| proc web::match {res list val} { |
| |
| if {[lsearch -exact $list $val] >= 0} { |
| return $res |
| } |
| return "" |
| } |
| |
| #----------------------------------------------------------------------------- |
| # web::list2uri |
| #----------------------------------------------------------------------------- |
| proc web::list2uri {list} { |
| |
| if {[llength $list] % 2} { |
| error "list must have even number of elems" |
| } |
| |
| set pairs {} |
| foreach {k v} $list { |
| lappend pairs [join [list [uriencode $k] [uriencode $v] ] = ] |
| } |
| return [join $pairs &] |
| } |
| |
| #----------------------------------------------------------------------------- |
| # web::uri2list |
| #----------------------------------------------------------------------------- |
| proc web::uri2list {string} { |
| |
| # special case: must return a list with an even # of elements |
| set res "" |
| foreach item [split $string &] { |
| set kv [split $item =] |
| if [llength $kv] { |
| lappend res [uridecode [lindex $kv 0]] [uridecode [lindex $kv 1]] |
| } |
| } |
| return $res |
| } |
| |
| #----------------------------------------------------------------------------- |
| # mod_websh and CGI stuff |
| #----------------------------------------------------------------------------- |
| |
| #----------------------------------------------------------------------------- |
| # per request init and cleanup for mod_websh |
| |
| namespace eval web::ap {} |
| |
| proc web::ap::perReqInit {} { |
| } |
| |
| proc web::ap::perReqCleanup {} { |
| # reset logging (except stuff from web::initializer) |
| web::loglevel delete -requests |
| web::logdest delete -requests |
| # reset request data |
| web::request -reset |
| # reset response channels |
| web::response -resetall |
| # reset url data |
| web::cmdurlcfg -reset |
| } |
| |
| #----------------------------------------------------------------------------- |
| # setup environment for cgi mode |
| |
| namespace eval web::cgi {} |
| |
| proc web::cgi::copyenv {} { |
| |
| set cgienv { |
| SERVER_SOFTWARE |
| SERVER_NAME |
| GATEWAY_INTERFACE |
| SERVER_PROTOCOL |
| SERVER_PORT |
| REQUEST_METHOD |
| PATH_INFO |
| PATH_TRANSLATED |
| SCRIPT_NAME |
| QUERY_STRING |
| REMOTE_HOST |
| REMOTE_ADDR |
| AUTH_TYPE |
| REMOTE_USER |
| REMOTE_IDENT |
| CONTENT_TYPE |
| CONTENT_LENGTH |
| HTTPS |
| } |
| |
| # set request headers from environment |
| foreach e [array names ::env] { |
| if {![string match HTTP_* $e]} { |
| if {[lsearch -exact $cgienv $e] == -1} continue |
| } |
| web::request -set $e $::env($e) |
| } |
| |
| # check for Authorization |
| if {![info exists ::env(REMOTE_USER)] && [info exists ::env(AUTH_BASIC)]} { |
| # AUTH_BASIC contains the Authorization header |
| # sent by the browser (e.g. created using Apache >= 2.0.51: |
| # SetEnvIf Authorization "^(Basic .+)$" AUTH_BASIC=$1 |
| # check the quick reference for security considerations |
| if {[regexp "^Basic (.*)" $::env(AUTH_BASIC) dummy authstring]} { |
| # base64 decode it |
| set i 0 |
| foreach char {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \ |
| a b c d e f g h i j k l m n o p q r s t u v w x y z \ |
| 0 1 2 3 4 5 6 7 8 9 + / =} { |
| set b64($char) $i |
| incr i |
| } |
| set decoded {} |
| set group 0; set j 18; set eq 0 |
| foreach char [split $authstring {}] { |
| |
| # ignore all characters not in base64 character set |
| # should be only newlines, but who knows ;-) |
| if {![info exists b64($char)]} {continue} |
| |
| if {[string compare $char "="]} { |
| set bits $b64($char) |
| set group [expr {$group | ($bits << $j)}] |
| } else { |
| incr eq |
| } |
| |
| if {[incr j -6] < 0} { |
| scan [format %06x $group] %2x%2x%2x a b c |
| switch $eq { |
| 0 {append decoded [format %c%c%c $a $b $c]} |
| 1 {append decoded [format %c%c $a $b]} |
| 2 {append decoded [format %c $a]} |
| } |
| set group 0; set j 18; set eq 0 |
| } |
| } |
| # set request params |
| web::request -set AUTH_USER [lindex [split $decoded :] 0] |
| web::request -set AUTH_PW [join [lrange [split $decoded :] 1 end] :] |
| } |
| } |
| if {[info exists ::env(AUTH_BASIC)]} { |
| unset ::env(AUTH_BASIC) |
| } |
| } |