#!/bin/sh
# The next line is executed by /bin/sh, but not tcl \
exec tclsh "$0" ${1+"$@"}
##
## httppost.tcl
##
## Post to a web page and return data
##
if {0} {
##
## EXAMPLES
##
# Uploading a PTS file: (only the file as a Data elem is needed)
httppost.tcl http://pop/~hobbs/wis/cgi-bin/pq.cgi
-user <valid-user> -passwd <users-passwd> \
-file Data <PTS_data.txt> var value var value
}
package require Tcl 8.2
package require http 2.2
#package require base64; # from tcllib - only needed for user/passwd
# it gets called below when necessary
proc Usage {} {
puts stderr "[file tail $::argv0] URL \\
?-proxyhost domain? \\
?-proxyport port? \\
?-user user? \\
?-passwd passwd? \\
?-output outputFile? \\
?-file formElemName fileName? \\
formElemName value formElemName value ...
-proxyhost and -proxyport set the proxy to use, if necessary
-user and -passwd are required if the URL requires authentication
files are handled specially with -file as the file has to
be read in and then that is used as the value."
exit
}
proc process {} {
global argv
if {[llength $argv] < 4} {
Usage
}
set opts(URL) [lindex $argv 0]
set argv [lrange $argv 1 end]
set opts(FILE) [list]
while {[string match -* [lindex $argv 0]]} {
switch -exact -- [lindex $argv 0] {
-proxyhost {
set opts(PROXYHOST) [lindex $argv 1]
if {![info exists opts(PROXYPORT)]} {
set opts(PROXYPORT) 80
}
set argv [lrange $argv 2 end]
}
-proxyport {
set opts(PROXYPORT) [lindex $argv 1]
set argv [lrange $argv 2 end]
}
-user {
set opts(USER) [lindex $argv 1]
set argv [lrange $argv 2 end]
}
-passwd {
set opts(PASSWD) [lindex $argv 1]
set argv [lrange $argv 2 end]
}
-file {
lappend opts(FILE) [lindex $argv 1] [lindex $argv 2]
set argv [lrange $argv 3 end]
}
-output {
set opts(OUTFILE) [lindex $argv 1]
set argv [lrange $argv 2 end]
}
default {
Usage
}
}
}
if {[info exists opts(PROXYHOST)]} {
::http::config -proxyhost $opts(PROXYHOST) \
-proxyport $opts(PROXYPORT)
}
## Configure the output channel
set outfd stdout
set type "multipart/form-data"
if {[info exists opts(OUTFILE)]} {
set outfd [open $opts(OUTFILE) w]
}
fconfigure $outfd -translation binary
set outputData {}
set bound "-----NEXT_PART_[clock seconds].[pid]"
foreach {elem file} $opts(FILE) {
set fid [open $file r]
fconfigure $fid -translation binary
if {[catch {read $fid [file size $file]} data]} {
return -code error $data
}
close $fid
append outputData "--$bound\nContent-Disposition: form-data;\
name=\"$elem\"; filename=\"[file tail $file]\"\n\n$data\n"
}
foreach {elem data} $argv {
append outputData "$bound\nContent-Disposition: form-data;\
name=\"$elem\"\n\n$data\n"
}
if {![string length $outputData]} {
return -code error "No data given to post"
}
append outputData "${bound}--"
set request [list ::http::geturl $opts(URL) \
-channel $outfd \
-type "multipart/form-data; boundary=$bound" \
-query $outputData]
if {[info exists opts(USER)] && [info exists opts(PASSWD)]} {
package require base64
lappend request -headers [list Authorization \
"Basic [base64::encode $opts(USER):$opts(PASSWD)]"]
}
set token [eval $request]
::http::wait $token
if {[string compare stdout $outfd]} {
close $outfd
}
}
process