最近整理笔记时发现了cgi的笔记,想想当时稍费了些周折,现总结一下供需要的朋友参考。如有不妥的地方欢迎指出,共同讨论,我会及时更正。
当时有个任务要升级原来板子的cgi实现和控制页面,需要在原html页面中添加一些新功能,由于旧版的cgi是用C实现的,所以整个html页面也都是使用printf打印输出的,这样一来修改页面的时候就比较繁琐了。由于以前也没有接触过,搜索一阵之后,主要找到了perl,CGIlua和cgic。
google后,出来的cgi首选就是perl,一眼望去,很多资料都说用perl实现,貌似提到perl已经是cgi的代名词了,就像当年的文曲星,一说到电子词典,大家马上想到的就是文曲星,以至于后来不管哪个厂家生产的都先被改名叫一遍文曲星,更夸张的是有一段时间只要是带有LCD,下面又有很多按键的都统统叫“文曲星”,可见文曲星的广告做得一斑。共同的是perl也一斑,于是借着新鲜感打算先用perl试试,于是又从hello world开始,拼拼凑凑做完第一个页面后感觉有些丑,觉得整体感觉不太合适,也许用在其他地方会更好,于是就暂时放下换CGIlua了。和perl一样这两个都是脚本语言,都需要解释器来执行,这样相比较C编译后的可执行文件在执行时就有些慢了,不过好处是脚本不需要编译就可以直接运行了,这是它的优点也是缺点。同时将与lua有关的东西移到2410的板子上还需要改一些东西,为此还加入了一个qq群,于是又从hello world开始,整完测试页面后效果也不是很满意,还是想换。最后终于找到了一个叫cgic的,从名字就可以看出来,这是一个用c实现的cgi,毕竟在板子上运行c更爽一些,同时也免去了从hello world开始。
下面是对使用它的简单总结。
解开压缩包后主要包括以下几个文件(project那个文件夹是我自己建的,里面放的是SourceInsight创建的工程文件,看cgic源码方便些)
|-- Makefile
|-- capture.c
|-- cgic.c
|-- cgic.h
|-- cgic.html
|-- cgic.o
|-- cgictest.c
|-- cgitest.cgi
|-- license.txt
|-- project
| |-- cgic.IAB
| |-- cgic.IAD
| |-- cgic.IMB
| |-- cgic.IMD
| |-- cgic.PFI
| |-- cgic.PO
| |-- cgic.PR
| |-- cgic.PRI
| |-- cgic.PS
| |-- cgic.SearchResults
| `-- cgic.WK3
|-- readme.txt
|-- support.txt
`-- svn-commit.tmp
可以看到文件不多,比较简洁,其中,cgitest.c是测试文件,直接make后就会生成一个cgitest.cgi文件,把它放到sambar或是boa的cgi目录,然后运行就可以看到测试的页面了
。像表单的提交,文本框,按钮的提交都有相关的接口(更多的使用还请参考帮助文档),如:
char name_test[81];
cgiFormStringNoNewlines("name", name_test, 81);
是将html代码中为name的变量的值复制到数组name_test中,而name就是类似于我们登录论坛时在文本框中输入的用户名之类的字符串,这样就完成了与用户的交互,获得了name字符串的值并保存在name_test中,这样,在应用程序中就可以对这个name的字符串进行验证了,比如是否为合法值等。在cgic.c时,需要在自己的源文件中添加cgic.h头文件,然后将原来的main()主函数改为cgiMain()就可以用了,也就是说将原来的源文件作为cgic的一个子函数被调用。cgic的打印输出方式为fprintf(cgiOut,"test");这在cgictest.c中就可以看到:
void ShowForm()
{
fprintf(cgiOut, "<!-- 2.0: multipart/form-data is required for file uploads. -->");
fprintf(cgiOut, "<form. method=/"POST/" enctype=/"multipart/form-data/" ");
fprintf(cgiOut, " action=/"");
cgiValueEscape(cgiScriptName);
fprintf(cgiOut, "/">/n");
fprintf(cgiOut, "
/n");
......
fprintf(cgiOut, "Text Field containing Plaintext/n");
fprintf(cgiOut, "
/n");
fprintf(cgiOut, "<input type=/"submit/" name=/"saveenvironment/" value=/"Save Environment/">/n");
fprintf(cgiOut, "</form>/n");
}
可见整个cgictest.cgi的测试页面都是通过fprintf()输出的,关于这一点,像这样的稍简单的测试页面还可以应付,当要处理的是复杂的html页面时再使用这种方法,对页面以后
的维护和扩展是否方便先不说,光是把页面的html代码通过fprintf()噼里啪啦写到程序里就够人受的,除非你喜欢在键盘上欢快的耕耘,享受着手指踢踏带来的乐趣,否则只好另
想它法,为此,我们可以先用网页制作工具如frontpage之类的事先设计好准备要显示的页面,然后再做个将html转换为c的接口htmltoc(),主要功能就是负责解析html文件,也就是将html代码使用fprintf()输出给浏览器,同时检测html中需要调用cgi更新变量的标识处,我们可以在这些地方用自己定义的标识符表示,比如用"$$$",当htmltoc()遇到"$$$"时就返回,并记住当前读取html文件的指针位置,以便下次接着读。
如,
----------------test.html---------------->
<html>
<head>
</head>
.....
<input type="text" name="T31" readonly size="22" style="background:#EEEEEE" value="$$$"); //文本框1
.....
<input type="text" name="T32" readonly size="22" style="background:#EEEEEE" value="$$$"); //文本框2
.....
</html>
<--------------test.html----------------
/********************************
*负责解析html页面
********************************/
int htmltoc(void)
{
//读取*.html
if(遇到字符串$$$)
{
return 0;
}
else
{
//继续读使用fprintf输出html代码到浏览器
}
}
//定义字符数组
char text_test1[64];
char text_test2[64];
/********************************
*负责处理变量
********************************/
int test_handle(void)
{
//使用cgic的接口获取用户在网页上输入的文本框字符串内容;
//对获取到的字符串根据需要判断处理;
//如简单复制:
// text_test1=文本框1的字符串;
// text_test2=文本框2的字符串;
//将text_test1记录到文件text_log1.txt中
//将text_test2记录到文件text_log2.txt中
}
/********************************
*cgic的主函数
********************************/
int cgiMain(void)
{
test_handle();
htmltoc(); //开始读
fprintf(cgiOut,"%s",text_test1);
htmltoc(); //继续读
fprintf(cgiOut,"%s",text_test2);
return 0;
}
--------------------------
其中test.html文件放在boa的web目录;连同cgic.c,将使用arm-linux-gcc编译后的cgiMain放在cgi-bin目录;
上面的主要功能就是将页面中输入的字符串原样的回显到页面中,同时也把留言记录在文件text_log1.txt和text_log2.txt中了,比如常用的网页中的留言板就可以这样实现,或
是比如把*.txt文件改为*.ini的格式作为配置文件,供后台运行的应用程序读取,就可以达到从网页上更改设备运行参数的目的了。
到此,关于cgic就总结完了,下面是上面提到的相关连接,供参考。
cgic的链接为:
http://www.boutell.com/cgic/
cgilua的链接为:
http://www.keplerproject.org/cgilua/
perl的链接为:
http://www.perl.org/
小结一下:
1.实现cgi的方式有多种,但凭cgic的短小精悍,实在值得推荐居家旅行必备,目前的最新的版本是2.05;
2.觉得cgi与html页面还是分开处理要好一些;
3.调试时发现点问题,好消息是问题找了,原因是cgic中有些接口的调用ms是有顺序的,改变下调用顺序就可以解决问题了;坏消息是,忘了具体是哪些接口了,不过在实际使用时如果遇到反复出问题时注意下就好了。