中文版 Perl CGI 程式写作常问问题集(四)
3.0 - CGI 与 WWW Server
---------------------------------------------------------------------------
Q3.1: 我的 Perl CGI 程式要放在哪里执行?cgi-bin 这个目录是做甚麽用的?
server 通常是设定成去执行放在 ``cgi-bin'' 目录底下的 CGI 程式。不过,
server 管理者同时也可以在设定档中设定 aliases,让所有含某些副档名(如
..cgi
、.pl)的 scripts 都能执行*。
【译者】设定 CGI aliases 和副档名固然很方便,但 server 管理者须注
意到相关的安全问题。
---------------------------------------------------------------------------
Q3.2: 什麽是档案使用权限?怎样改?
档案权限是根据使用者识别代号(又称
uid),以及他们所属的团体来决定是否赋与
使用者读、写,和执行某档案的权利。您可使用 chmod
这个指令去修改档案的使用
权限。例如:
% ls -ls form.cgi
1 -rwx------ 1 shishir 974 Oct 31 22:15 form.cgi*
此一档案的权限为
0700(八进制),意味著没有人(档案所有人除外)能够读取、
写进,或执行这个档案。我们可以用 chmod 这个指令去修改它的权限:
% chmod 755 form.cgi
% ls -ls form.cgi
1 -rwxr-xr-x 1 shishir 974 Oct 31 22:15 form.cgi*
这样一来,权限就变了。现在和 ``shishir''
在同一个团体的使用者,还有其他任
何的使用者都有权利去读取和执行这个档案了。
如欲知 chmod 指令各八进制数码所代表的含意,请参阅 chmod
manpages的说明。
---------------------------------------------------------------------------
Q3.3: Perl 应该安装在哪里才可以执行它?
Perl 可以安装在系统上任何一个角落!您唯一要注意的是 server
不能在chroot 的
环境下跑,否则它便无法跑 perl
解译器。换言之,系统管理者可以把根目录改变,
让 ``/'' 指到另一个目录,而不是实际真正的根目录(``/'')。
---------------------------------------------------------------------------
Q3.4: 我为什麽一直得到 ``Server: Error 500'' 的讯息?
以下几种情形会触发这个错误讯息:
* 如果 script 开头的地方没有 ``#!/usr/local/bin/perl'' 这个指到
Perl 解
译器的标头,或者是指到解译器(或 library 档)的路径错误。
* 如果 script 输出的第一行是一个不正确的标头(即 ``Content-Type:
text/html'' ),或者是该标头後面没有跟著一个空行。
* 如果您的 script 有句法上的错误。您的 scripts
都应在指令列先跑跑看才
是。
---------------------------------------------------------------------------
Q3.5: 我试著打开一个档案,想把资料储存在里头,但是 open()
的指令失败了。到
底是怎麽搞的?
一般说来,HTTP server 是以
``nobody''、``www'',或其他这类权限低的使用者的
身份来跑的。因为这个缘故,您打算在其中制造新档案的目录,对 server
跑的使用
者 ID 必须要是可写(writable)才行。
为了确定起见,您每次都应该先检查 open 这个指令送回的结束状态(return
status
),看看 open 有没有成功。
open(FILE, "/abc/data.txt")
|| error("Could not open file /abc/data.txt");
.
.
.
sub error {
my($message) = @_;
print <<End_of_Error;
Content-type: text/html
Status: 500 CGI Error
<HTML>
<HEAD><TITLE>CGI Error</TITLE></HEAD>
<BODY>
<H1>Oops! Error</H1>
<HR>
$message
<HR>
</BODY>
</HTML>
End_of_Error
}
4.0 -程式设计疑难杂症
---------------------------------------------------------------------------
Q4.1: 我想让 user 填的 form 资料自动寄给我,该怎麽做?有没有范例?
其实做这个很容易。您的 CGI script 必须能做到这两件事:
1. 将 form 中的资料整理出来。别忘了,所有的 form 资料都会被
URL-编码起来
(先不考虑 Netscape 2.0 【及 2.0 以上所支援】的 multipart
MIME资料)。
2. 开一个管路 (pipe) 到 mail (或 sendmail ),然後把 form
资料写过去。
我们就假设您用的是 CGI::* 模组。您可用以下的方法去叫 sendmail:
$cgi_form = new CGI::Form;
$from = $cgi_form->param('from');
$name = $cgi_form->param('name');
$to = $cgi_form->param('to');
$subject = $cgi_form->param('subject');
$message = $cgi_form->param('message');
open SENDMAIL, "| /usr/bin/sendmail -t -n";
print SENDMAIL <<End_of_Mail;
From: $from <$name>
To: $to
Reply-To: $from
Subject: $subject
$message
End_of_Mail
有一个该注意的地方是 ``Reply-To:'' 的信头。由於 server 是以
``nobody''
这个使用者的身份来跑,信头的地方可能会被搞坏(尤其是当有人想回这封信
的时後)。加上 ``Reply-To'' 的信头这个问题便解决了。
网路上有许多的 mail 渠道 (gateway)* 是以底下这种方法来送 mail:
【译者】gateway 在此指送 email 的 CGI 程式
open MAIL, "| mail -s 'Subject' $to";
^
|
--
可能会出问题的漏洞!!!
如果您没有先检查看 $to 这个变数有没有内含 shell 的特殊符号
(metacharacters),您是在自讨苦吃!譬如,如果哪个恶劣的 user
输入了以下
的资料:
; rm -fr / ;
那麽您的麻烦可大了*。
【译者】这里头的 ``;'' 便是一个危险的 shell metacharacter。
另一个危险的符号是 ``