#!/bin/rc rfork e url=() headers=() action=() method=() at=() # text fields af=() # file fields l=() fn usage { echo 'usage: hpost [ -l ] [ -[gpm] action ] [ -r header ] [ -u ] url [ field:value | field@file ... ]' >[1=2] exit usage } while(~ $1 -*){ switch($1){ case -l; l=($l $1) case -u; shift; url=$1 case -r; shift; headers=($headers -r $1) case -g; shift; action=$1; method=mget case -p; shift; action=$1; method=mpost case -m; shift; action=$1; method=multi case *; usage } shift } if(~ $#url 0){ url=$1 shift } if(~ $url '') usage while(! ~ $#* 0){ switch($1){ case *:*@*; at=($1 $at) case *@*; af=($1 $af) case *:*; at=($1 $at) case *; usage } shift } hpost=(hpost $l) fn uenc { f=$1 for(i in $at){ echo -n $"f`{urlencode /env/i | sed 's!%3A!=!; s!%00$!!'} f='&' } for(i in $af){ echo -n $"f`{urlencode /env/i | sed 's!@.*$!=!'} urlencode `{sed 's!^[^@]+@!!' /env/i} f='&' } } fn menc { f=$1 cr=`{echo x | tr x \015} for(i in $at){ k=`{sed 's!:.*$!!; q' /env/i} echo '--'$"f$"cr echo 'Content-Disposition: form-data; name="'$"k'"'$"cr echo $"cr i=$"i$"cr sed '1s!^[^:]+:!!' /env/i } for(i in $af){ k=`{sed 's!@.*$!!; q' /env/i} ifs=' ' v=`{sed 's!^[^@]+@!!' /env/i} t=`{file -m $v} n=`{basename $v} echo '--'$"f$"cr echo 'Content-Disposition: form-data; name="'$"k'"; filename="'$"n'"'$"cr echo 'Content-Type: '$"t$"cr echo $"cr cat $v echo $"cr } echo '--'$"f'--'$"cr } fn mget { a=`{uenc '?'} action=$"action$"a $hget -b $url $action } fn mpost { uenc | $hget -b $url -P $action } fn multi { f='HJBOUNDARY' menc $"f | $hget -r 'Content-Type: multipart/form-data; boundary='$"f -b $url -P $action } if(! ~ $action ''){ hget=(hget $headers $l) $method exit } # serialize $at and $af into a0=... a1=... for awk # to preserve newlines and other special characters n=() for(i in $at $af){ a$#n=$i n=(1 $n) } a$#n='' hget $url | uhtml | tr '>' ' ' | sed ' s!^(TAG|ATT)! \1!g; # escape our inline signaling s!<[ ]*!\nTAG !g; # find starttags, mark with TAG name ... s!>[^>"'']*$!!g; # remove garbage after the tag # find attributes, mark with ATT name value s!([a-zA-Z][a-zA-Z0-9:_]*)=("[^"]*"?|''[^'']*''?|[ ]*[^> ]+)!\nATT \1 \2!g; ' | awk -v 'hpost='$"hpost -v 'url='$"url ' BEGIN{ for(i=0; ENVIRON["a"i]!=""; i++){ s=ENVIRON["a"i] x=index(s, ":"); y=index(s, "@") if(y > 1 && (x < 1 || x > y)) x = y n=substr(s, 1, x-1) ainput[n]=substr(s, x+1, length(s)) atypes[n]=substr(s, x, 1); } } function qw(s){ if(s !~ /[\n\\#;\|\^$=`''{}\(\)<> ]/) return s gsub(/''/, "''''", s) return "''"s"''" } function uq(s){ q=substr(s, 1, 1) if(q=="\"" || q=="''"){ s=substr(s, 2, length(s)) x=index(s, q) if(x > 0) s=substr(s,1,x-1) } return s } function emitform(){ if(action!=""){ printf hpost if(url!="") printf " -u %s", qw(url) if(method=="post"){ if(enctype=="multipart/form-data") printf " -m %s", qw(action) else printf " -p %s", qw(action) } else printf " -g %s", qw(action) for(n in ainput) printf " %s%s%s", n, atypes[n], qw(ainput[n]) for(n in input) if(!(n in ainput)) printf " %s%s%s", n, types[n], qw(input[n]) printf "\n" } delete input delete types action="" method="" enctype="" } function endtag(){ if(tag=="form"){ action=attr["action"] method=tolower(attr["method"]) enctype=tolower(attr["enctype"]) } if(tag=="select") selectname=attr["name"] if(tag=="option" && selectname!=""){ if(attr["selected"]!=""){ input[selectname]=attr["value"] selectname="" } } if(tag=="input" || tag=="textarea" || tag=="submit"){ n=attr["name"] if(n!=""){ if(tolower(attr["type"])=="file"){ input[n]="/dev/null" types[n]="@" } else { input[n]=attr["value"] types[n]=":" } } } delete attr tag="" } /^TAG \//{ etag=tolower(substr($2, 2, length(etag)-1)) endtag() if(etag=="form") emitform() } /^TAG [^\/]/{ endtag() tag=tolower($2) if(tag=="form") emitform() } /^ATT/{ for(i=4; i<=NF; i++) $3=$3" "$i attr[tolower(uq($2))]=uq($3) } END{ endtag() emitform() } '