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

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 ddtestgrepcutdc 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

目录
相关文章
|
11月前
|
监控 NoSQL 安全
如何在 Redis 中正确使用多线程?
【10月更文挑战第16天】正确使用 Redis 多线程需要综合考虑多个因素,并且需要在实践中不断摸索和总结经验。通过合理的配置和运用,多线程可以为 Redis 带来性能上的提升,同时也要注意避免可能出现的问题,以保障系统的稳定和可靠运行。
277 2
|
11月前
|
人工智能 开发框架 Java
总计 30 万奖金,Spring AI Alibaba 应用框架挑战赛开赛
Spring AI Alibaba 应用框架挑战赛邀请广大开发者参与开源项目的共建,助力项目快速发展,掌握 AI 应用开发模式。大赛分为《支持 Spring AI Alibaba 应用可视化调试与追踪本地工具》和《基于 Flow 的 AI 编排机制设计与实现》两个赛道,总计 30 万奖金。
292 93
|
7月前
|
开发工具 Android开发 iOS开发
零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
OpenIM 为开发者提供开源即时通讯 SDK,作为 Twilio、Sendbird 等云服务的替代方案。借助 OpenIM,开发者可以构建安全可靠的即时通讯应用,如 WeChat、Zoom、Slack 等。 本仓库基于开源版 OpenIM SDK 开发,提供了一款基于 Flutter 的即时通讯应用。您可以使用此应用程序作为 OpenIM SDK 的参考实现。 开发环境 在开始开发之前,请确保您的系统已安装以下软件: 操作系统:macOS 14.6 或更高版本 Flutter:版本 3.24.5(根据官网步骤进行安装) Git:用于代码版本控制 同时,您需要确保已经部署了最
396 10
|
8月前
|
DataWorks
【云产品评测】DataWorks获奖名单公布!
【云产品评测】DataWorks获奖名单公布!
146 0
|
11月前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【10月更文挑战第6天】本文比较了Python中三个最受欢迎的Web框架:Django、Flask和Pyramid。Django功能全面,适合快速开发;Flask灵活轻量,易于上手;Pyramid介于两者之间,兼顾灵活性和可扩展性。文章分析了各框架的优缺点,帮助开发者根据项目需求和个人偏好做出合适的选择。
236 4
|
机器学习/深度学习 算法 Serverless
【MATLAB】鲸鱼算法优化混合核极限学习机(WOA-HKELM)时序预测算法
【MATLAB】鲸鱼算法优化混合核极限学习机(WOA-HKELM)时序预测算法
266 1
|
12月前
|
机器学习/深度学习 数据采集
深度学习之脑电图信号解码
基于深度学习的脑电图(EEG)信号解码是一项重要的研究领域,旨在从脑电图信号中提取有用信息,用于脑-机接口、情绪识别、疾病诊断等应用。
325 5
|
12月前
|
人工智能 安全 开发者
由于安全风险,安全领导者考虑禁止用AI生成代码
由于安全风险,安全领导者考虑禁止用AI生成代码
|
12月前
|
KVM 虚拟化
计算虚拟化之CPU——qemu解析
【9月更文挑战10天】本文介绍了QEMU命令行参数的解析过程及其在KVM虚拟化中的应用。展示了QEMU通过多个`qemu_add_opts`函数调用处理不同类型设备和配置选项的方式,并附上了OpenStack生成的一个复杂KVM参数实例。
|
12月前
|
Linux iOS开发 MacOS
Python系统编程高手进阶:跨平台兼容性?小菜一碟💪
【9月更文挑战第6天】当我们探讨Python系统编程时,跨平台兼容性至关重要。Python凭借其解释型语言特性和多平台解释器,确保了代码能够在Windows、Linux、macOS等多种环境中顺畅运行。本文将介绍Python跨平台运行的基本原理,以及如何处理文件路径差异和系统调用等问题,助你轻松应对跨平台挑战。
305 1