git: 9front

Download patch

ref: 07dedc5cf4936895b5899e765477e13a8ab5324b
parent: c140ce8a715cf77335fcd9a94f309e404613797a
author: stanley lieber <stanley.lieber@gmail.com>
date: Thu Oct 11 12:37:48 EDT 2012

add /rc/bin/formpost; add formpost to hget(1) man page

--- /dev/null
+++ b/rc/bin/formpost
@@ -1,0 +1,191 @@
+#!/bin/rc
+rfork e
+argv0=$0
+fn usage {
+	echo usage: $argv0 '[-d] [-M] [ -u url ] [ -g action | -p action | -m action ] [ name:value | name:@value ]' ... >[1=2]
+	exit usage
+}
+d=()
+g=()
+M=()
+m=()
+p=()
+u=()
+while(~ $1 -*){
+	switch($1){
+	case -d
+		d=1
+	case -g
+		g=1
+		a=$2
+		shift
+	case -M
+		M=1
+	case -m
+		m=1
+		a=$2
+		shift
+	case -p
+		p=1
+		a=$2
+		shift
+	case -u
+		u=$2
+		shift
+	case *
+		usage
+	}
+	shift
+}
+if(~ $#M 0 && ~ $#u 0)
+	usage
+fn geth{
+	hget $u |
+	sed 's/ACTION\=/action\=/g;
+		s/ENCTYPE\=/enctype\=/g;
+		s/FORM/form/g;
+		s/INPUT/input/g;
+		s/METHOD\=/method\=/g;
+		s/NAME\=/name\=/g;
+		s/OPTION/option/g;
+		s/SELECT/select/g;
+		s/TEXTAREA/textarea/g;
+		s/TYPE\=/type\=/g' |
+	awk '/<([ ]|[	])*form/,/<\/form>/ {print}' |
+	sed 's/<\/form>/&\nHJFORMEND\n/g;
+		s/<([ ]|[	])*/HJBOUNDARY/g;
+		s/>(\n)*([ ]|[	])*HJBOUNDARY/\n/g;
+		s/([ ]|[	])*HJBOUNDARY//g;
+		s/^form/HJFORMSTART\n&/g' |
+	grep -e '(^HJFORM|^form|^input|^option|^select|^textarea)' >$1
+}
+fn getf{
+	a=`{grep -e '^form' $1 | sed 's/^.*action\=//g; s/^(\''|\"|[ ]*)//g; s/(\''|\"|[ ]|>).*$//g'}
+	e=`{grep -e '^form' $1 | sed 's/^.*enctype\=//g; s/^(\''|\"|[ ]*)//g; s/(\''|\"|[ ]|>).*$//g'}
+	m=`{grep -e '^form' $1 | sed 's/^.*method\=//g; s/^(\''|\"|[ ]*)//g; s/(\''|\"|[ ]|>).*$//g'}
+	f=$a
+	if(~ $#f 0)
+		f=/
+	if(~ $e multipart/form-data)
+		f=($f m)
+	if not if(~ $m post)
+		f=($f p)
+	if not
+		f=($f g)
+	ifs='
+' {
+	for(j in `{grep -e '(^input|^select|^textarea)' $1}){
+		if(~ $d 1)
+			echo $"j >>formpost.log #debug
+		if(~ $j *name'='*)
+			jname=`{echo $"j |
+				sed 's/^.*name\=//g;
+					s/^(\''|\"|[ ]*)//g;
+					s/(\''|\"|[ ]|>).*$//g;
+					s/^.*\=.*$//g'}
+		if(~ $j *value'='*)
+			jvalue=`{echo $"j |
+				sed 's/^.*value\=//g;
+					s/^(\''|\"|[ ]*)//g;
+					s/(\''|\"|[ ]|>).*$//g;
+					s/^.*\=.*$//g;
+					s/[ ]/HJSPACE/g'}
+		ff=`{echo $"jname':'$"jvalue |
+			sed 's/^.*\=.*:/:/g;
+				s/:.*\=.*$/:/g'}
+		if(! ~ $ff :*)
+			f=($"f $"ff)
+		jname=()
+		jvalue=()
+	}
+}
+	echo $"f
+}
+fn mencode{
+	f=()
+	cr=`{echo x | tr x \015}
+	while(! ~ $#1 0){
+		switch($1){
+		case *:*
+			f=($f $1)
+		case *
+			usage
+		}
+		shift
+	}
+	for(i in $f){
+		echo '--HJBOUNDARY'^$"cr
+		fname=`{echo $"i | awk -F ':' '{print $1}'}
+		fvalue=`{echo $"i | awk -F ':' '{print $2}'}
+		if(~ $fvalue @*){
+			fvalue=`{echo $"fvalue | sed 's/@//g'}
+			echo 'Content-Disposition: form-data; name="'$"fname'"; filename="'^`{basename $fvalue}^'"'$"cr
+			echo Content-Type: `{file -m $fvalue}^$"cr
+			echo $cr
+			cat $fvalue
+			echo $cr
+		}
+		if not{
+			echo 'Content-Disposition: form-data; name="'$"fname'"'$"cr
+			echo $"cr
+			echo $"fvalue^$"cr
+		}
+	}
+	echo '--HJBOUNDARY--'$"cr
+}
+fn uencode{
+	f=()
+	for(i){
+		fname=`{echo $"i | awk -F ':' '{print $1}'}
+		fvalue=`{echo $"i | awk -F ':' '{$1=""; print substr($0, 2)}' |
+			sed 's/HJSPACE/ /g' |
+			urlencode |
+			sed 's/%0A$//g'}
+		f=$"f^$"fname'='$"fvalue
+		if(! ~ $"i $*($#*))
+			f=$"f^'&'
+	}
+	echo $"f
+}
+fn print{
+	if(~ $d 1)
+		echo $"f >>formpost.log #debug
+	a=`{echo $"a | sed 's/^\///g'}
+	if(~ $a http*)
+		u=$a
+	if not
+		u=$"u/$"a
+	if(~ $M 1)
+		mencode `{for(i in $f){echo $"i}}
+	if not if(~ $m 1)
+		echo formpost -M `{for(i in $f){echo ''''$"i''''}} '| hget -P -r ''Content-Type: multipart/form-data, boundary=HJBOUNDARY''' $"u
+	if not if(~ $p 1)
+		echo 'hget -p '''^`{uencode $f}^''' '^$"u
+	if not
+		echo hget ''''$"u^'?'^`{uencode $f}^''''
+}
+if(~ $#M 0 && ~ $#g 0 && ~ $#m 0 && ~ $#p 0){
+	file=/tmp/formpost.$pid
+	geth $file
+	while(grep -s -e '^HJFORMSTART$' $file){
+		f=`{getf $file}
+		a=$f(1)
+		if(~ $f(2) g)
+			g=1
+		if not if(~ $f(2) m)
+			m=1
+		if not if(~ $f(2) p)
+			p=1
+		f=$f(3-)
+		print
+		{ echo /HJFORMSTART/,/HJFORMEND/d
+			echo w
+			echo q
+		} | sam -d $file >[2]/dev/null
+	}
+	rm -f $file
+}
+if not{
+	f=$*
+	print
+}
--- a/sys/man/1/hget
+++ b/sys/man/1/hget
@@ -1,6 +1,6 @@
 .TH HGET 1
 .SH NAME
-hget \- retrieve a web page corresponding to a url
+hget, formpost \- retrieve, post to a web page corresponding to a url
 .SH SYNOPSIS
 .B hget
 [
@@ -22,6 +22,30 @@
 .I baseurl
 ]
 .I url
+.PP
+.B formpost
+[
+.B -d
+] [
+.B -M
+] [
+.B -u
+.I url
+] [
+.B -g
+.I action
+] [
+.B -p
+.I action
+] [
+.B -m
+.I action
+] [
+.I name:value
+|
+.I name:@value
+]
+.I ...
 .SH DESCRIPTION
 .I Hget
 retrieves the web page specified by the URL
@@ -72,10 +96,84 @@
 Option
 .B -m
 overrides the HTTP method used for the request.
+.PP
+.I Formpost
+retrieves the web page specified by the URL
+.I url,
+parses its HTML for form data, then prints
+.I hget
+commands to submit forms to the
+.I url.
+If the
+.B -M, -g, -p
+or
+.B -m
+flags are set, the
+.I hget
+commands are assembled without first retrieving and interpreting the
+target HTML.
+.PP
+If the
+.B -d
+flag is specified, debugging information is written
+to the file
+.B formpost.log
+in the current directory.
+.PP
+The
+.B -M
+flag applies multipart/form-data encoding to the
+remaining arguments and prints the result on
+the standard output.
+.PP
+The
+.B -u
+flag sets the target URL to
+.I url.
+.PP
+The
+.B -g
+and
+.B -p
+flags set the the form method to GET and POST, respectively. The
+.B -m
+flag sets the form method to POST and its enctype to multipart/form-data.
+In all cases, the form action is set to
+.I action.
+.PP
+The remaining arguments of the form
+.B name:value
+are interpreted as form field names and values to be submitted along
+with the form. An argument of the form
+.B name:@value
+is interpreted as a file upload, with the information following the
+.B @
+symbol treated as the full path to the location of the file.
+.SH EXAMPLES
+Retrieve the
+.I hget
+command needed to submit a form, which may then be
+edited and sent.
+.IP
+.EX
+% formpost -u http://p.intma.in
+hget -p 'text=' http://p.intma.in/paste.cgi
+.EE
+.PP
+Manually specify options to be sent to a given
+.I url.
+Note: The target HTML is not fetched and interpreted.
+.IP
+.EX
+% formpost -u http://p.intma.in -p paste.cgi 'text:test post'
+hget -p 'text=test+post' http://p.intma.in/paste.cgi
+.EE
 .SH SOURCE
 .B /rc/bin/hget
+.br
+.B /rc/bin/formpost
 .SH "SEE ALSO"
-.IR webfs (4),
+.IR webfs (4) ,
 .IR ftpfs (4)
 .SH DIAGNOSTICS
 .I Hget
@@ -84,3 +182,8 @@
 service mounted on
 .B /mnt/web
 to work.
+.SH BUGS
+.I Formpost
+does not attempt to insert default values for
+.B <select>
+tags.
--