📄 perlfaq9.html
字号:
</A></H2>HTTPD::UserAdmin 和 HTTPD::GroupAdmin等模组为这些档案提供了统一的物件导向介面,尽管这些档案可能以各种不同的格式储存。这些资料库可能是纯文字格式、 dbm、Berkeley DB或任何 DBI相容的资料库驱动程式 (drivers)。 HTTPD::UserAdmin支援`Basic' 和 `Digest'这两个认证模式所用的档案。以下是 一例:<P><PRE> use HTTPD::UserAdmin (); HTTPD::UserAdmin ->new(DB => "/foo/.htpasswd") ->add($username => $password);</PRE><P><P><HR><H2><A NAME="_p_d_CGI_">如何防范使用者藉由填我的 CGI表格来做坏事?</A></H2>阅读 CGI security FAQ,(可在 <A HREF="../../tppmsgs/msgs0.htm#92" tppabs="http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html">http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html</A>取得),还有 Perl CGI FAQ,在 <A HREF="../../tppmsgs/msgs1.htm#130" tppabs="http://www.perl.com/CPAN/doc/FAQs/cgi/perl-cgi-faq.html">http://www.perl.com/CPAN/doc/FAQs/cgi/perl-cgi-faq.html</A> 。<P>简单一句话:使用 tainting(沾腥?)这项功能(详见 <A HREF="../../tppmsgs/msgs1.htm#102" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlsec.html#">perlsec</A>)。它会让所有不在您的 script中、来路不明的资料(譬如, CGI参数)无法放到 <CODE>eval</CODE> 或 <CODE>system</CODE>等呼叫中使用。除了使用 tainting之外,绝对不要使用单一参数 的方式下参数给 <CODE>system()</CODE>或 <CODE>exec(),</CODE>而应将欲执行的指令及其参数放在一个序 列或阵列里面,再传给 <CODE>system()</CODE>或 <CODE>exec(),这样便可避免</CODE> globbing【即被 shell先做解译】。<P><P><HR><H2><A NAME="_p_B_email_Y_H">如何解读、萃取 email标头资料?</A></H2>如果您只需要一个「快而脏」的解法的话,您可以试试这个从再版的 ``ProgrammingPerl''第 222页中拿出来的例子:<P><PRE> $/ = ''; $header = <MSG>; $header =~ s/\n\s+/ /g; #将延续行合并成单行 %head = ( UNIX_FROM_LINE, split /^([-\w]+):\s*/m, $header );</PRE><P>譬如说,您若想保留所有 Received栏位资料的话【因 Received栏位通常不止一个】,这个解法便不太行了。一个完整的解法是使用收录在 CPAN的 Mail::Header模组( MailTools 套件的一部分)。<P><P><HR><H2><A NAME="_p_CGI_H">如何解译 CGI表格?</A></H2>很多人忍不住要自己写程式来处理这部分的工作,所以您们大概都看过一大堆其中有 <CODE>$ENV{CONTENT_LENGTH}</CODE> 和 <CODE>$ENV{QUERY_STRING}</CODE>的程式码。没错,这麽写是可以行得通,但事实上也有很多在网路上出没的这类程式根本不能用!<P>请不要忍不住去重新发明轮子【译者:这是英文的说法 (reinventing the wheels),也就是浪费时间做人家做过的事的意思】。请改用 CGI.pm或 CGI_Lite.pm(可自 CPAN取得)。如果您被困在无模组的 perl1 .. perl4的土地上,您可以试看看 cgi-lib.pl(可至 <A HREF="../../tppmsgs/msgs1.htm#131" tppabs="http://www.bio.cam.ac.uk/web/form.html">http://www.bio.cam.ac.uk/web/form.html</A>取得)。<P><P><HR><H2><A NAME="_p_email_H">如何验证 email位址?</A></H2>无法度。<P>如果没有寄封信到一个位址去试试看它会不会弹回来(即使是这麽做您还得面对停顿的问题),您是无法确定一个位址是否真的存在的。即使您套用 email 标头的标准规格来做检查的依据,您还是有可能会遇到问题,因为有些送得到的位址并不 符合 RFC-822(电子邮件标头的标准)的规定,但有些符合标准的位址却无法投 递。<P>许多人试图用一个简单的正规表示式,例如 <CODE>/^[\w.-]+\@([\w.-]\.)+\w+$/</CODE>来消除一些通常是无效的 email位址。不过,这样做也把很多合格的位址给一起滤掉了,而且对测试一个位址有没有希望投递成功完全没有帮助,所以在此建议大家不要这麽做;不过您可以看看: <A HREF="../../tppmsgs/msgs1.htm#132" tppabs="http://www.perl.com/CPAN/authors/Tom_Christiansen/scripts/ckaddr.gz">http://www.perl.com/CPAN/authors/Tom_Christiansen/scripts/ckaddr.gz</A>。这个 script真的彻底地依据所有的 RFC规定来做检验(除了内嵌式 comments外),同时会排除一些您可能不会想送信去的位址(如 Bill Clinton【美国柯林顿总统】或您的 postmaster),然後它会确定位址中的主机名称可在 DNS中找得到。这个 script 跑起来不是很快,但至少有效。<P>不少 CGI scripts的作者使用另一个替代的方案:用一个简单的正规表示式,(如上头的那个)。如果一个位址能让这个式子对得上的话,那麽就接受这个位址。如果这个位址对不上这个式子的话,便再向使用者讯问,以确定她们填入的这个位 址正确无误。<P><P><HR><H2><A NAME="_p_MIME_BASE64_r_H">如何解 MIME/BASE64字串?</A></H2>MIME-tools套件(可自 CPAN取得)不但可处理这个问题而且有许多其他的功能。有了这个套件,解 BASE64码就变得像这麽容易:<P><PRE> use MIME::base64; $decoded = decode_base64($encoded);</PRE><P>一个比较直接的解法是先做一点简单的转译,然後使用 <CODE>unpack()</CODE>这个函数的 ``u'' 格式:<P><PRE> tr#A-Za-z0-9+/##cd; #去除非 base64字元 tr#A-Za-z0-9+/# -_#; #转换成 uu码格式 $len = pack("c", 32 + 0.75*length); #计算长度字元 print unpack("u", $len . $_); # uu解码後 print</PRE><P><P><HR><H2><A NAME="_p_b_W_X_e">如何根据使用者帐户名称自动合成 email位址?</A></H2>在支援 getpwuid【UNIX系统呼叫】、 $<这个变数,和 Sys::Hostname模组(标准 perl发行的一部分)的系统上,您可试试这样的做法:<P><PRE> use Sys::Hostname; $address = sprintf('%s@%s', getpwuid($<), hostname);</PRE><P>有的公司对 email位址有统筹规画,因此这麽一来您可能会合成出不被公司的 email 主机接受的位址。所以如果有这类的顾虑的话,您应该直接向 users要他们的 email 位址。 而且,并不是所有能跑 Perl的系统都像 Unix一样,可以很容易得到这些资料。<P>CPAN里的 Mail::Util模组( MailTools 套件的一部分)中有一个 <CODE>mailaddress()</CODE>函数,它会试着去猜 user的 email位址。这个函数使用比上面的 code聪明的方法,它会参考安装时所得到的设定资料,但是错误仍可能发生。所以,再一次地,最好的方法通常是直接问 user 本人。<P><P><HR><H2><A NAME="_p_e_email_H">我的程式如何送/读 email?</A></H2>送信:CPAN 上头的 Mail::Mailer模组( MailTools套件的一部分)只适合在 Unix 上使用,但利用到 Net::SMTP的 Mail::Internet模组则没有这个限制。 读信:用 CPAN 上的 Mail::Folder模组( MailFolder 套件的一部分)或是用 CPAN 上头的 Mail::Internet模组( 也是 MailTools 套件的一部分)。<P><PRE> #送信 use Mail::Internet; use Mail::Header; #设定使用哪台主机 $ENV{SMTPHOSTS} = 'mail.frii.com'; #制作标头 $header = new Mail::Header; $header->add('From', 'gnat@frii.com'); $header->add('Subject', 'Testing'); $header->add('To', 'gnat@frii.com'); #制作本文 $body = 'This is a test, ignore'; #产生 mail物件 $mail = new Mail::Internet(undef, Header => $header, Body => \[$body]); #送出 $mail->smtpsend or die;</PRE><P><P><HR><H2><A NAME="_p_X_D_W_W_IP_">如何找出我的主机名/网域名/IP位址?</A></H2>长久以来许多 code都很草率地直接呼叫 <CODE>`hostname`</CODE>这个程式来取得主机名。虽然这麽做很方便,但也同时增加了移植到其他平台上的困难。这是一个很典型的例子,在方便和可移植性之间作抉择,不论选哪一边,必须付出一些牺牲和代价。<P>Sys::Hostname这个模组(标准 perl发行的一部分)可用来取得机器的名字,然後您便可利用 <CODE>gethostbyname()</CODE>这个系统呼叫来找出该机的 IP位址了(假定您的 DNS 运作正常)。<P><PRE> use Socket; use Sys::Hostname; my $host = hostname(); my $addr = inet_ntoa(scalar(gethostbyname($name || 'localhost')));</PRE><P>至少在 Unix底下,取得 DNS网域名最简单的方法大概要算是直接从/etc/resolv.conf这个档案里面找。当然,这麽做的前提是 resolv.conf这个档案的设定必须照惯例的格式,还有就是这个档案必先存在才行。<P>(Perl在非 Unix系统下尚需要一有效的方法来测出机器和网域名)<P><P><HR><H2><A NAME="_p_s_D_Q_s_s_W_">如何抓新闻讨论群的文章或群组名录?</A></H2>使用 Net::NNTP或 News::NNTPClient模组,两者皆可自 CPAN下载。这些模组让抓群组名录这类的差事变得这麽容易:<P><PRE> perl -MNews::NNTPClient -e 'print <A HREF="News::NNTPClient->">News::NNTPClient-></A>;new->list("newsgroups")'</PRE><P><P><HR><H2><A NAME="_p_FTP_H">如何抓/丢 FTP档案?</A></H2>LWP::Simple模组(可自 CPAN下载)可以抓,但不能丢档案。 Net::FTP模组(也可自 CPAN下载)虽比较复杂,但可用来丢、也能抓档案。<P><P><HR><H2><A NAME="_p_Perl_RPC_H">如何用 Perl做 RPC?</A></H2>有一个 DCE::RPC模组正在发展阶段(但尚未完成)。一旦完成後它会随着 DCE-Perl这个套件发行(可由 CPAN 下载)。至於 ONC::RPC这样的模组则还没听说有人在发展。<P><P><HR><H1><A NAME="_v_y">作者及版权事宜</A></H1>Copyright (c) 1997 Tom Christiansen and Nathan Torkington.着作权所有, Allrights reserved。有关使用、(转)发行事宜,详见 <A HREF="perlfaq.html" tppabs="http://202.96.217.5/~xiaoyi/perlfaq.html">perlfaq</A>。<P>中译版着作权所有:萧百龄及两只老虎工作室。本中译版遵守并使用与原文版相同的使用条款发行。<P></DL> </BODY> </HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -