输出数据你输出的数据应该符合你所规定的content-type; 如果content-type是text/html, 输出安置应该是在HTML. 如果content-type是image/gif, 输出应该是在一个二进制的GIF文件. 练习1: 小试试.T这是个简单的输出日期的简单脚本,这个CGI脚本还检查看看我是否已经登陆到我的Web服务器,并且报告发现了什么(如在图4). 图4. 脚本的结果 <A HREF="http://www.popchina.com/cgi-bin/pinglaura">Is Laura Logged in?</A> 这是没有输入的脚本,它只运行并且返回数据. 根据前面的阐述,这个脚本内容是这样:: echo Content-type: text/html echo "<HTML><HEAD>" echo "<TITLE>Is Laura There?</TITLE>" echo "</HEAD><BODY>" ison='who | grep lemay' 试验结果及返回相应提示的脚本是这样: if [ ! -z "$ison" ]; then echo "<P>Laura is logged in."</P> else echo "<P>Laura isn't logged in."</P> fi 最后关闭HTML: echo "</BODY></HTML>" 现在你通过从命令行运行他,测试一下,你将得到一个结果说我未登陆你的系统,当然不可能的,他的输出是这样的: Content-type: text/html <HTML><HEAD> <TITLE>Are You There?</TITLE> </HEAD><BODY> <P>Laura is not logged in. </BODY></HTML> 这是输出的一个HTML文本,这样你的浏览器能正常显示他,因为他是个HTML文件。
这个例子完整的脚本如下: #!/bin/sh echo "Content-type: text/html" echo echo "<HTML><HEAD>" echo "<TITLE>Is Laura There?</TITLE>" echo "</HEAD><BODY>" ison='who | grep lemay' if [ ! -z "$ison" ]; then echo "<P>Laura is logged in" else echo "<P>Laura isn't logged in" fi echo "</BODY></HTML>" 带有参数的脚本为了传递一个参数给脚本,可以在URL中使用 (?) 插入脚本名词和参数之间, 用加号(+) 表示每个单一的参数, 如: <A HREF="/cgi-bin/myscript?arg1+arg2+arg3">run my script</A> 当服务器接收到这个请求,它传递 arg1, arg2, 和 arg3 参数给脚本. 你然后能在脚本中使用这些参数. 这个方法有时叫查询, 因为早期它用在搜索功能中. 练习2: 检查是否有人登陆.既然你知道怎样使用参数,让我们继续上面的例子pinglaura,通过修改这个例子我们得到下面这个脚本pinggeneric. 我们取个不同题目: #!/bin/sh echo "Content-type: text/html" echo echo "<HTML><HEAD>" echo "<TITLE>Are You There?</TITLE>" echo "</HEAD><BODY>" 在上面的例子中, 下一步应该是测试我是否登陆,在这里我们用参数${1}代替我的名字lemay, ${1}作为第一个参数, ${2}作为第二个, ${3}作为第三个. ison='who | grep "${1}"'剩下的所有修改如下: if [ ! -z "$ison" ]; then echo "<P>$1 is logged in" else echo "<P>$1 isn't logged in" fi echo "</BODY></HTML>" 好了,让我们修改HTML页中的连接吧!原来是这样: <A HREF="http://www.lne.com/cgi-bin/pinglaura">Is Laura Logged in?</A> 修改为通用查询功能后是这样,比如查询名字叫john的人是否登陆: <A HREF="http://www.lne.com/cgi-bin/pinggeneric?john">Is John Logged in?</A> 在你的服务器上试试,看是否有结果。 传递其他信息给脚本有第二种方法传递信息给CGI脚本. 它叫作路径信息path information 用作那些在脚本调用是不用变更的参数, 象一个临时文件名或调用脚本自己的文件名. 正如你看到的,在上面的例子问号后面的参数是因用户表单的输入而改变的. 路径信息Path info用作其他信息传递给脚本,实际上,你可以用它作任何事情. 看下面一个路径信息path information例子, : http://myhost/cgi-bin/myscript/remaining_path_info?arg1+arg2 当脚本运行时,在路径中的信息将被放置于环境参数PATH_INFO. 你能在你的脚本内容中使用这些信息. 比如说, 让我们假设你在多页上已有多个连接到同一个脚本. 你能用这个路径信息显示那个有连接的HTML文件名. 这样, 在你完成处理你的脚本之后, 当你发回一个HTML文件时, 你能在这个文件里包含一个连接,发回用户一开始那个页。 你会在下一章节学到更多路径信息:有用的表单和脚本. 待后来登出 创建一个特殊的脚本输出现在你已经学习了诸如输出数据 一般地HTML数据 发给浏览器解释显示的数据. 但是如果你不想把脚本结果作为一个数据流形式发回浏览器,而是想把一个存在的页发回,怎么办? 如果你只是要脚本做一些事而不让任何结果回答给浏览器,怎么办? 不用怕, 这里开始解释这些情况. 用调用另一个文本作为响应CGI输出不是非得一个数据流,有时可以告诉浏览器是存在服务器上的一个页,为了发出这个信息,看下面的例子: Location: ../docs/final.html 这个Location行用作通常的输出位置,也就是说,如果你用了Location, 你就不必再用象Content-type这样的数据输出(实际上,你也不能). 正如Content-type, 你也必须在这一行后面跟一个空行. 指向这个文件的路径可以是一个URL或相对路径. 所有相对路径是指相对于脚本所在的位置. 例子中的final.html文本是在当前上一个目录下docs的目录下: echo Location: ../docs/final.html echo No Response很幸运, 这一切很容易. 你只要输出下面这个命令即可(后面跟一个空行): echo Status: 204 No Response echo 这个Status头部提供状态码给服务器(并且也给浏览器). 特别的204将传递给浏览器,如果能识别它,它将什么也不做.
处理表单的脚本记住, 大多数表单有两个部分: HTML的表单格式;处理表单数据的CGI脚本. 这个CGI脚本使用标签<FORM>属性调用的. 表单形式和表单脚本正如上面所说,由于表单有两个部分. 如下: 这个ACTION属性包含着处理表单的脚本: <FORM ACTION="http://www.popchina.com/cgi-bin/processorscript"> 在这个表单中, 每个输入区都有一个NAME的属性, 用来称呼表单元素. 当这个表单数据被递交给你在ACTION中定义的CGI脚本, 这样这些name和输入内容被作为一个数字或字符传递给脚本. GET 和 POST表单从浏览器发给服务器有两种方法. GET 和 POST. 我们上面谈论的方法,实际是GET,它将数据打包放置在环境变量QUERY_STRING中作为URL整体的一部分传递给服务器。 POST做很多类似GET同样的事情, 不同的地方就是它是分离地传递数据给脚本. 你的脚本通过标准输入获取这些数据. (有些Web服务器是存储在临时文件中.) 这个QUERY_STRING环境变量将不再设置. 那你用那个方法呢? POST是个安全的方法, 尤其如果你的表单中有很多数据的话. 当你用GET, 这个服务器就分配变量QUERY_STRING给所有的表单数据, 但是这个变量可存储量是有限的. 换句话说,如果你有很多数据但是你又用GET,你会丢失很多数据. 如果你用POST, 你可以尽可能多地使用数据, 因为这些数据从来也不分配到一个变量里. URL 编码URL 编码是一种浏览器用来打包表单输入的格式. 浏览器从表单中获取所有的name和其中的值,将他们作为name/value参数编码, 移去那些不能传送的字符, 将数据排行等等,这些还取决于你用GET还是POST?作为URL的一部分或者分离地发给服务器. 不管哪种情况, 在服务器端的表单输入格式样子象这样: theName=Ichabod+Crane&gender=male&status=missing&headless=yes URL编码遵循下列规则:
因为表单输入是用这个URL编码传递给你的脚本的,在你用这些参数之前必须解码,因为解码是个很普遍的工作,可以有很多工具做这个工作 . 你没有必要自己写这个解码程序. 这里介绍一个叫uncgi的解码程序, 你可以从http://www.hyperion.com/~koreth/uncgi.html. 得到原码,安装在你自己的cgi-bin目录下. 练习3: 告诉我你的名字.让我们以这个例子来说明,如图5. 这个输入被发给脚本, 然后发回显示一个hello的信息(间图.6). 如果你在姓名输入处不输入任何东东,会怎样?见图7. 修改表单的HTML现在我们举一个真实的例子: <FORM METHOD=POST ACTION="../cgi-bin/form-name"> </FORM> 如果你在用uncgi从input中解码, 情况有点不同. 为了是uncgi正常工作, 你首先必须调用uncgi , 如果uncgi是个目录,加上实际的脚本名, 象这样: <FORM METHOD=POST ACTION="../cgi-bin/uncgi/form-name"> </FORM> 这样,你不必修改表单中原始的HTML; 原始的HTML可以工作得很好. 脚本处理表单输入的是个CGI脚本, 让我们来仔细地看看。 在脚本中第一步是解码,在这个例子中, 我们已经使用uncgi解码输入数据, 实际这个表单已经为你做好解码. 通过建立一个uncgi的目录,一旦表单递交给服务器,服务器会自动进行解码,这样,所有的name/value已经准备就绪等待你的使用. 现在,一个例子开始部分假设是下面这样: echo Content-type: text/html echo echo "<HTML><HEAD>" echo "<TITLE>Hello</TITLE>" echo "</HEAD><BODY>" echo "<P>" 接下来,有两种情况要处理:一件是处理用户不输入名字的情况,一个是如果输入了向他们说hello. 这个Name元素的值, 是包含在WWW_theName环境变量中. 用一个简单的测试命令(-z), 你能查看环境变量是否是空的还是包括相应的输出值: if [ ! -z "$WWW_theName" ]; then echo "Hello, " echo $WWW_theName else echo "You don't have a name?" fi 最后增加一个连接"go back" . 用来返回: echo "</P><P><A HREF="../lemay/name1.html">Go Back</A></P>" echo "</BODY></HTML>" 问题这里是使用CGI脚本比较普遍的问题:
CGI变量表2 总结那些环境变量.
表单输入的解码程序目前有两个程序: 通用目的的uncgi, 和cgi-lib.pl, 这是个Perl库,用于perl编写的CGI脚本. 当然也有表单上载时可以解码的程序,很少。 uncgi说明原码可以从 http://www.hyperion.com/~koreth/uncgi.html获得。 cgi-lib.pl这是由Steve Brenner编写的, 帮助你管理输入. 他能从GET和POST获取输入并且放置在一个Perl列表或阵列中. 更新的版本也能处理来自表单的文件上传. 从这儿可以得到信息与原码 http://www.bio.cam.ac.uk/cgi-lib. 如果你决定用Perl语言处理你的表单输入,cgi-lib是个很好的库. 为了使用cgi-lib.pl,你通常要这样写: require 'cgi-lib.pl'; cgi-lib中尽管有很多子程序, 最重要的是ReadParse子程. ReadParse 读取输入方便地将name/value储存在一个Perl阵列中. 在你的Perl脚本中通常是这样调用的: &ReadParse(*in); 此例中,阵列名是in, 可以随便取名的. 在表单输入解码后, 你能读取和处理这个name/value,方法是象下面这样: print $in{'theName'};这个将显示名字name是theName的值value. 如果你有多个用同样名字的name对, cgi-lib.pl用(\0)分隔多个名字. 这样可以正常处理你的脚本. 解码上传的文件输入基于表单的文件上传需要不同的表单输入,有一些程序可以对其进行解码。 cgi-lib.pl 后来版本可以很好支持, 在http://www.bio.cam.ac.uk/cgi-lib/ 了解更多的情况. 另一个处理用Perl编写的CGI地址是 http://valine.ncsa.uiuc.edu/cgi_docs.html . 自己做找专门书籍学习吧: ftp://ds.internic.net/rfc/rfc1867.txt. 非解剖的脚本头部按照本书阐述,大多数情况可以正常操作,在一些情况下不是这样的,你可以翻阅说明书了解。 <ISINDEX> 脚本为了在CGI中完成讨论组, 我们看看叫<ISINDEX>的搜索. 这是早期在浏览器中用来向服务器发出搜索关键字的办法,参看以前的资料。 总结CGI脚本, 有时叫服务器端脚本或网关脚本。 在internet上有很多免费资源,你可以搜索下载读懂他们,当然都是英文的,如果你下决心翻译他们(可能更加强理解). 这样一举两得啊. 注意:上述程序可以用ultra edit来编辑,注意转换UNIX格式 ,必须采用UNIX格式存盘,再上载,用telnet登陆,在命令行键入perl sample.pl,看有无bug,再 在浏览器中调用。CGI程序包括放置CGI的目录一定要改属性为777, 要写入的HTML文件也要改属性为777. 现在网上有很多免费的cgi,基本可以满足一般需求,请到这个网址查询你要的cgi:http://www.itm.com/cgicollection/ 本人汉化了一个古老的通用留言簿,大家可以拿去做自己的留言簿。这里下载 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||