在IPCam上搭建WEB服务并通过CGI交互的相关问题

本文涉及到目前遇到的几个方面的问题,也是分享,也做个记号备忘。

1,thttpd服务器搭建

   1)下载:  http://www.acme.com/software/thttpd/


   2)  交叉编译

        命令:CC=arm-linux-gcc ./configure --host=arm-linux
  这里有几个问题需要注意,比较令人郁闷的事情
  1,config.cache会记录上次的配置,所以一定要先删除,再配置
  2,配置语句:CC=arm-linux-gcc ./configure --host=arm-linux
  3,不能建立build目录,使用../configure 配置
  4,编译完成后,用如下命令可启动之:
    sudo ./thttpd -d /home/lfx/html/ -c /cgi-bin/\*
    也可使用配置文件启动:sudo ./thttpd -C thttpd.conf
    thttpd.conf中需要添加cgipat=/cgi-bin/* 以便支持cgi
    cgi的路径,实际上是从配置文件的dir路径开始算的。
    chroot要删除。
  5,配置完成后,要得到CGI的运行结果,可以输入这样的地址:
 http://192.168.12.44/cgi-bin/getdate.sh
把配置文件thttpd.conf的内容贴在这里

# This section overrides defaults
dir=/home/lfx/html
#chroot
user=lfx# default = nobody
logfile=/var/log/thttpd.log
pidfile=/var/run/thttpd.pid
cgipat=/cgi-bin/*
charset=UTF-8
max_age=0
# This section _documents_ defaults in effect
# port=80
# nosymlink# default = !chroot
# novhost
# nocgipat
# nothrottles
# host=0.0.0.0
# charset=iso-8859-1

 

2,CGI参数传递

CGI的参数传递有两种方法,一个比较简单,就是在URL后面直接跟参数,

就像这样http://192.168.12.44/cgi-bin/myscript.sh?lfx+123456

这种做法的好处是不需要解析,在服务端,会直接调用myscript.sh lfx 123

还有一种比较通用,但是稍微麻烦的格式:

http://192.168.12.44/cgi-bin/myscript.sh?username=lfx&password=123456

这种的好处是通用,几乎都是这么弄的。坏处是字符串没直接传递过来,而是放在环境变量:QUERY_STRING中。

而QUERY_STRING的值为username=lfx&password=123456

下面两个脚本,一个是工具脚本,负责解析,另一个是演示脚本

工具脚本proccgi.sh

 

#!/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.            [email protected]
#
# 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


测试脚本:myscript.sh

#!/bin/sh

eval `./proccgi.sh $QUERY_STRING`

echo Content-type: text/plain

echo

echo $FORM_username

echo $FORM_password

echo here...

echo $#

echo $*

echo $QUERY_STRING

echo

echo `export`

 

3,CGI调用

 网页的部分,为了在网页中调用URL,需要这样做:

<script>

function jv_httpGet(url)
{
	var xmlhttp;
	if (window.XMLHttpRequest)
	{// code for IE7+, Firefox, Chrome, Opera, Safari
		xmlhttp=new XMLHttpRequest();
	}
	else
	{// code for IE6, IE5
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	xmlhttp.open("GET",url,false);
	xmlhttp.send();
	return xmlhttp.responseText;
}
function display()
{
	var url = http://192.168.12.44/cgi-bin/myscript.sh?lfx+123456
	var ret = jv_httpGet(url);
	document.write(ret);
}

</script>


 4,强制刷新

 之所以要强制刷新,是因为IE在运行时,会询问服务器是否有更新,如果没有更新则不重新收数据。服务器也不重新给它发。

然而可恨的是,CGI程序本身没变,但它的运行结果却发生了变化。而服务器又以为没有变化

为解决这个问题,只好强制刷新。

修改方法,是CGI调用时,加上个东西:

function jv_httpGet(url)
{
 var xmlhttp;
 if (window.XMLHttpRequest)
 {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
 }
 else
 {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
 }
 xmlhttp.open("GET",url+"+#"+new Date().getTime(),false);
 xmlhttp.send();
 return xmlhttp.responseText;
}

注意其中红色的部分,是比原来增加的。

对应的,服务端的程序必须处理这多出来的部分。我们用#来认为它是注释,解决掉这个问题


 

你可能感兴趣的:(String,cgi,query,XMLhttpREquest,Path,web服务)