Processing Form Data in Shell CGI Scripts[转]

Processing Form Data in Shell CGI Scripts

This page presents a little /bin/sh shell script that will help you processing form data in a CGI shell script, without needing C or perl.
You receive the form values straight into your shell environment, where you can then access them just like other shell variables. About no special requirements are needed, it just uses the standard Unix utilities dd, test, grep, cut, dc and echo.
The latter must be able to print arbitrary octal codes.

Note: Writing this script was interesting, but the program is also kind of a joke. I wanted to prove that it is indeed possible to pick apart CGI data with a shell
script, and I succeeded. Yet the script has some deficiencies.

Don't get me wrong. Programming CGI shell scripts isn't a bad idea in general, it indeed works quite well for small jobs. But evaluating the form datashouldn't be done in a script.

One problem is that this script is slow. For biting its way through the data string, it must continuously invoke the afore-mentioned utilities. Hundreds of times. Second, there are a few tiny differences
in the tools' implementations on various platforms, so in rare cases, obscure problems may occur.

I never expected the overwhelming feedback on my script. Unfortunately, it didn't always work out perfectly. It is much better having an integrated piece of C code that does the job than a shell script. I have decided
to write such a tool, proccgi, to help all folks that were having problems getting the script to work. Unless you know what you're doing, or are looking for fascinating
shell scripts, please use that program to evaluate form data in your shell CGI scripts instead, it's much easier to use.

If you are currently using the script on your site, you can simply switch over to proccgi. It works the same, and
you only need to change a single line of code in your CGI scripts.

A big thank you to all who have used this shell script in the past, present, and future, and to those who commented on it.

Yet another option is to switch to the Tcl language for CGI scripting. It's powerful and easy to use; I use it for most of my scripting these days. Of course I also have a Tcl script for CGI data evaluation: proccgi.tcl.

Now back to the shell script ...

Features

  • Handles both GET and POST methods transparently.
  • Also accepts assignments on the command line (great for testing).
  • If the extra pathname features assignments (like /A=trash), it is processed as well.
  • Handles '+' (replaced by space) and '%XX' sequences.
  • Exports all found variables to the shell environment.
  • Can also handle multiline "Textarea" input fields.

Bugs

Most of them are shell limitations, and there isn't much I can do to fix them. Should you find a solution, tell me!

  • All exported variables are case sensitive.
  • Cannot properly handle newlines (%0A); they are replaced by spaces.
  • Hex escapes must be uppercase. This should be guaranteed by the remote browser.
  • Slow.

Usage

After downloading the script (with a name of 'proccgi.sh' or whatever) and installing it (don't forget to grant exec permission), all left to do in your own scripts is to call

eval `proccgi.sh $*`

In some cases, you might need to give the full pathname if it's not found automatically. After this call, you have everything in your shell.

If something goes wrong, you can also enable some debugging output by setting the variable DEBUG to 1, causing a log to be printed to standard error. To get a debugging logfile, you would call

DEBUG=1
export DEBUG
eval `proccgi.sh $* 2> logfile`

Example

This is a very simple example of an automatic software-by-email program. You can fill in your email address and a file name which is then automatically mailed to you.Do
not, I repeat, do not install this piece of code. It would be a major security leak.

The Form

<form action="http://our-server/cgi-stuff/mailer" method="post">
<dl>
  <dt> Your Email <dd> <input name="email" size="50">
  <dt> Filename   <dd> <input name="file"  size="50">
</dl>
<input type="submit" value="Submit">
</form>

The Script

#!/bin/sh
eval `proccgi.sh $*`
mail $FORM_email < $FORM_file
cat - << \END
echo Content-type: text/plain
echo
echo done.
END

As you can see, after the call to proccgi.sh, the email address from the form is stored in the shell variable $FORM_email, and the file name
is in $FORM_file.

Note

This was just an experiment for me to experience myself what's possible with shell scripts. I know it's not perfect, but I'm missing the time to put much more efforts into it. If you desperately
need a feature, read man sh and fix it yourself.

The script may be freely used and distributed at no charge provided that the copyright notice remains at its top.

Script & Code

Don't forget to download the code, proccgi.sh.

http://www.fpx.de/fp/Software/ProcCGIsh.html

#!/bin/sh
#
# Process input to a CGI script. Written and Copyright 1995 Frank Pilhofer
# You may freely use and distribute this code free of charge provided that
# this copyright notice remains.            fp@informatik.uni-frankfurt.de
#
# All variables in here are prefixed by _F_, so you shouldn't have
# any conflicts with your own var names
#
# get query string. if $REQUEST_METHOD is "POST", then it must be read
# from stdin, else it's in $QUERY_STRING
#
if [ ${DEBUG:-0} -eq 1 ] ; then
	echo --Program Starts-- 1>&2
fi
#
if [ "$REQUEST_METHOD" = "POST" ] ; then
	_F_QUERY_STRING=`dd count=$CONTENT_LENGTH bs=1 2> /dev/null`"&"
	if [ "$QUERY_STRING" != "" ] ; then
		_F_QUERY_STRING="$_F_QUERY_STRING""$QUERY_STRING""&"
	fi
	if [ ${DEBUG:-0} -eq 1 ] ; then
		echo --Posted String-- 1>&2
	fi
else
	_F_QUERY_STRING="$QUERY_STRING""&"
	if [ ${DEBUG:-0} -eq 1 ] ; then
		echo --Query String-- 1>&2
	fi
fi
if [ ${DEBUG:-0} -eq 1 ] ; then
	( echo "  " $_F_QUERY_STRING
	  echo --Adding Arguments-- ) 1>&2
fi
#
# if there are arguments, use them as well.
#
for _F_PAR in $* ; do
	_F_QUERY_STRING="$_F_QUERY_STRING""$_F_PAR""&"
	if [ ${DEBUG:-0} -eq 1 ] ; then
		echo "  " arg $_F_PAR 1>&2
	fi
done
if [ ${DEBUG:-0} -eq 1 ] ; then
	( echo --With Added Arguments--
	  echo "  " $_F_QUERY_STRING ) 1>&2
fi
#
# if $PATH_INFO is not empty and contains definitions '=', append it as well.
# but replace slashes by ampersands
#
if echo $PATH_INFO | grep = > /dev/null ; then
	_F_PATH_INFO="$PATH_INFO""//"
	if [ ${DEBUG:-0} -eq 1 ] ; then
		( echo --Adding Path Info--
		  echo "  " $_F_PATH_INFO ) 1>&2
	fi

	while [ "$_F_PATH_INFO" != "" -a "$_F_PATH_INFO" != "/" ] ; do
		_F_QUERY_STRING="$_F_QUERY_STRING""`echo $_F_PATH_INFO | cut -d / -f 1`""&"
		_F_PATH_INFO=`echo $_F_PATH_INFO | cut -s -d / -f 2-`
	done
fi
#
# append another '&' to fool some braindead cut implementations. Test yours:
# echo 'i am braindead!' | cut -d '!' -f 2
#
_F_QUERY_STRING="$_F_QUERY_STRING""&"
#
if [ ${DEBUG:-0} -eq 1 ] ; then
	( echo --Final Query String--
	  echo "  " $_F_QUERY_STRING ) 1>&2
fi
#
while [ "$_F_QUERY_STRING" != "" -a "$_F_QUERY_STRING" != "&" ] ; do
	_F_VARDEF=`echo $_F_QUERY_STRING | cut -d \& -f 1`
#	_F_QUERY_STRING=`echo $_F_QUERY_STRING | cut -d \& -f 2-`
	_F_VAR=`echo $_F_VARDEF | cut -d = -f 1`
	_F_VAL=`echo "$_F_VARDEF""=" | cut -d = -f 2`

#
# Workaround for more braindead cut implementations that strip delimiters
# at the end of the line (i.e. HP-UX 10)
#

	if echo $_F_QUERY_STRING | grep -c \& > /dev/null ; then
		_F_QUERY_STRING=`echo $_F_QUERY_STRING | cut -d \& -f 2-`
	else
		_F_QUERY_STRING=""
	fi

	if [ ${DEBUG:-0} -eq 1 ] ; then
		( echo --Got Variable--
		  echo "  " var=$_F_VAR
		  echo "  " val=$_F_VAL
		  echo "  " rem=$_F_QUERY_STRING ) 1>&2
	fi
	if [ "$_F_VAR" = "" ] ; then
		continue
	fi

#
# replace '+' by spaces
#

	_F_VAL="$_F_VAL""++"
	_F_TMP=

	while [ "$_F_VAL" != "" -a "$_F_VAL" != "+" -a "$_F_VAL" != "++" ] ; do
		_F_TMP="$_F_TMP""`echo $_F_VAL | cut -d + -f 1`"
		_F_VAL=`echo $_F_VAL | cut -s -d + -f 2-`

		if [ "$_F_VAL" != "" -a "$_F_VAL" != "+" ] ; then
			_F_TMP="$_F_TMP"" "
		fi
	done

	if [ ${DEBUG:-0} -eq 1 ] ; then
		echo "  " vrs=$_F_TMP 1>&2
	fi

#
# replace '%XX' by ascii character. the hex sequence MUST BE uppercase
#

	_F_TMP="$_F_TMP""%%"
	_F_VAL=

	while [ "$_F_TMP" != "" -a "$_F_TMP" != "%" ] ; do
		_F_VAL="$_F_VAL""`echo $_F_TMP | cut -d % -f 1`"
		_F_TMP=`echo $_F_TMP | cut -s -d % -f 2-`

		if [ "$_F_TMP" != "" -a "$_F_TMP" != "%" ] ; then
			if [ ${DEBUG:-0} -eq 1 ] ; then
				echo "  " got hex "%" $_F_TMP 1>&2
			fi
			_F_HEX=`echo $_F_TMP | cut -c 1-2 | tr "abcdef" "ABCDEF"`
			_F_TMP=`echo $_F_TMP | cut -c 3-`
#
# can't handle newlines anyway. replace by space
#
#			if [ "$_F_HEX" = "0A" ] ; then
#				_F_HEX="20"
#			fi

			_F_VAL="$_F_VAL""`/bin/echo '\0'\`echo "16i8o"$_F_HEX"p" | dc\``"
		fi
	done

#
# replace forward quotes to backward quotes, since we have trouble handling
# the former ones.
#

	_F_VAL=`echo $_F_VAL | tr "'" '\`'`

#
# if debug, send variables to stderr
#

	if [ ${DEBUG:-0} -eq 1 ] ; then
		( echo --Final Assignment--
		  echo "FORM_$_F_VAR"=\'$_F_VAL\' ) 1>&2
	fi

#	/bin/echo "FORM_$_F_VAR"=\'$_F_VAL\'
	/bin/echo "FORM_$_F_VAR"="'"$_F_VAL"'"
done
#
if [ ${DEBUG:-0} -eq 1 ] ; then
	echo done. 1>&2
fi
#
# done.
#
exit 0

http://cyent.blog.51cto.com/905592/829034

时间: 2024-11-03 07:51:26

Processing Form Data in Shell CGI Scripts[转]的相关文章

Posting form data from ASP.NET page to another URL

asp.net source: http://www.c-sharpcorner.com/Code/2004/Sept/ASP.NetPostURL.asp begin: AuthorDate Of SubmissionUser LevelJigar Desai09/27/2004IntermediateDownload: Remote Post 2Kb IntroductionSometime you need to post a form to an different url from a

Web前沿—HTML5 Form Data 对象的使用

XMLHttpRequest Level 2 添加了一个新的接口--FormData.利用 FormData 对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件,我们还可以使用 XMLHttpRequest 的 send() 方法来异步的提交表单.与普通的 Ajax 相比,使用 FormData 的最大优点就是我们可以异步上传二进制文件. 创建一个FormData对象 你可以先创建一个空的 FormData 对象,然后使用 append() 方法向该对象里添加字段,如下:

Xajax手册(第一版)

ajax 原文:http://xajax.sourceforge.net/英文原版:Copyright 2005 J. Max Wilson简体中文翻译:HonestQiao(乔楚)/2005-12-7 17:23/(第一版)什么是xajax? xajax如何工作? 为什么我要使用xajax代替其他PHP的Ajax库? 如何在我的PHP脚本之中使用xajax? 如何异步更新内容? 如何异步处理表单数据? 如何给xajax增加定制功能? 我能在私有或者收费产品之中使用xajax吗?  What i

Incremental Data Processing based on MapReduce

Incremental Data Processing based on MapReduce Cairong Yan  Xin Yang  Ze Yu  Min Li  Xiaolin Li IncMR framework is proposed in this paper for incrementally processing new data of a large data set Keywords:MapReduce,Incrementaldataprocessing,State,Dat

CGI漏洞集锦_网络冲浪

一.phf漏洞这个phf漏洞好象是最经典了,几乎所有的文章都会介绍,可以执行服务器的命令,如显示/etc/passwd:lynx http://www.victim.com/cgi-bin/phf?Qalias=x%0a/bin/cat%20/etc/passwd但是我们还能找到它吗?二.php.cgi 2.0beta10或更早版本的漏洞 可以读nobody权限的所有文件.lynx http://www.victim.com/cgi-bin/php.cgi?/etc/passwdphp.cgi

MaxCompute 2.0: Evolution of Alibaba&#039;s Big Data Service

The speech mainly covers three aspects: • Overview of Alibaba Cloud MaxCompute • Evolution of Alibaba's Data Platform • MaxCompute 2.0 Moving Forward I. Overview of Alibaba Cloud MaxCompute Alibaba Cloud MaxCompute is formerly known as ODPS, which is

Working with Big Data on Alibaba Cloud

You know Alibaba Cloud can be used to deploy applications. You may be less familiar with its Big Data storage and management options. In fact, Alibaba offers a range of Big Data solutions. This article outlines them and explains which types of Big Da

Shell逐行读取文件的4种方法_linux shell

在Linux中有很多方法逐行读取一个文件的方法,其中最常用的就是下面的脚本里的方法,而且是效率最高,使用最多的方法.为了给大家一个直观的感受,我们将通过生成一个大的文件的方式来检验各种方法的执行效率. 方法1:while循环中执行效率最高,最常用的方法. 复制代码 代码如下: function while_read_LINE_bottm(){ While read LINE do echo $LINE done  < $FILENAME } 注释:我习惯把这种方式叫做read釜底抽薪,因为这种方

Mining of Massive Datasets – Mining Data Streams

Most of the algorithms described in this book assume that we are mining a database. That is, all our data is available when and if we want it. In this chapter, we shall make another assumption: data arrives in a stream or streams, and if it is not pr