cgi开发遇到的问题续
1. fopen打开文件的问题
Fopen以写方式打开文件时,如果只是文件名(默认当前目录),则可以打开成功;如果指定一个相对路径,如/usr/local/apache/cgi-bin/upload/filename,则打开失败。出现这个问题的原因是因为权限不够(cgi程序运行时,是apache的用户,权限有限),虽然给cgi-bin更改了权限(chmod o+w /usr/local/apache/cgi-bin),但是它的上面几级目录没有写权限,以绝对路径打开文件时,对每一级路径都需要有写权限。于是
#chmod o+w -R /usr/local/apache/cgi-bin/upload
然后就可以打开成功了。
疑问:目录的x控制能否进去和通过目录,x和r的组合控制能否列出目录,x和w的组合控制能否在目录中删除、新建、修改文件。
解答:fopen以读方式打开时,只要该用户具有upload目录的读权限,在upload上几级目录有x权限即可打开成功;通过chmod o+w -R这条命令修改权限,查看local目录和apache目录的权限,对于other用户来说还是只有x权限(默认对于other用户就有x权限),如果不加-R选项,以写方式打开还是会失败,加了-R选项就可以打开成功,但是local和apache目录对other的权限还是x;x和r组合可以列出目录,x和w的组合控制能够在目录中删除、新建和修改文件。
2. Cgi获取html表格中数据的问题
通过js比较容易获取html表格中的数据,但是通过cgi就很麻烦,还不一定能成功,所以采用一个简单的办法,因为我要获取表格中的文件名来进行操作,比如
而这个文件名是通过遍历目录来得到的,因此直接将“下载”操作的文件名写死,比如
在cgi中这样写
printf("<a href=\"download.cgi?name=%s\">下载</a>", name);
其中的name是之前获取保存下来的。
3. Cgi中printf javascript的问题
Cgi中打印javascript比较麻烦,而且很容易出错。比如上面第一个问题中的“下载”链接,之前是用按钮做的。如下:
printf("<form name=form_download method=\"get\" action=\"download.cgi?name=%s\"/>", name);
printf("<input type=\"submit\" value=\"下载\"/>");
printf("</form>");
结果点击网页之后通过getenv("QUERY_STRING")没有获取出name参数来。
所以改用简单的方法,直接用href。
printf("<a href=\"download.cgi?name=%s\">下载</a>", name);
4. Cgi执行成功或失败后跳转到某一页面的方法
在cgi中打印如下语句即可。
printf("Content-type: text/html\n\n");
printf("<html>");
printf("<script language=\"javascript\">\n");
printf("window.location=\"/cgi-bin/list_dir.cgi\";");
printf("</script>");
printf("</html>");
5. 下载和删除时,文件名中有空格的问题
比如下载文件“c cgi.ppt”,文件名中有空格,通过getenv("QUERY_STRING")获取出来的文件名是“c%20gi.ppt”,因此需要把"%20"替换成“ ”。
6. Utf-8中文编码问题
网页编码一般选用utf-8,源代码里面如果有中文,需要以编码utf-8另存。
服务器的.bashrc里加上
export LANG=zh_CN.UTF-8
export LC_ALL=zh_CN.UTF-8
.vimrc里加上
set termencoding=utf-8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,latin1
set encoding=utf-8
language messages zh_CN.utf-8
这样用vim编写代码的时候就可以显示中文,而不是乱码了。
7. Url编解码问题
在用cgi编写程序时,一些特殊字符(如空格、&等),还有中文字符,经过url之后都很重新编码,所以c语言用getenv接收的数据会是编码之后的字符串。如“c gi.txt”经过url之后变成“c%20gi.txt”。一般url是使用urlencode来进行编码,所以cgi程序中需要使用urldecode来解码。
具体参考
http://www.cnblogs.com/greatverve/archive/2011/12/12/URL-Encoding-Decoding.html
http://www.abc188.com/info/html/caozuoxitong/FreeBSD/20090513/132147.html
8. Linux c获取目录下所有文件大小的问题
void list_dir(char *path)
{
DIR *dir;
struct dirent *entry;
struct stat stat_buf;
if ((dir = opendir(path)) == NULL)
{
printf("cannot open dir:%s\n", path);
return;
}
while ((entry = readdir(dir)) != NULL)
{
lstat(entry->d_name, &stat_buf);
if (!S_ISDIR(stat_buf.st_mode))
printf("%s, %d", entry->d_name, (int)stat_buf.st_size);
}
closedir(dir);
}
结果打印出来的是这种结果:
httpd-2.4.2.tar.gz, 4096
Firefox-latest.exe, 4096
Makefile.pdf, 4096
cr-SecureCRT.rar, 4096
putty.exe, 4096
结果显示大小都是4096,有时候只是其中一个文件的大小比如,都是xxx文件的大小,那个4096应该是目录"."和".."的大小,这就很奇怪了,为什么打印出来的不是自身文件的大小。
后来没办法用以下方法获取文件大小:
FILE *fp = fopen(name, "r");
if (fp)
{
fseek(fp, 0L, SEEK_END);
int len = ftell(fp);
fseek(fp, 0L, SEEK_SET);
return len;
}
至于为什么用stat_buf.st_size获取的大小有问题,还没有搞清楚原因。