选择显示字体大小

perl常问问题集--第七篇

我的 cgi script可在指令列下执行但无法从浏览器执行。您能不能帮我修修看?

当然,但您恐怕付不起雇我们的签约金 :-)

说真的,如果您能够先证明您已读过下列这几个 faqs ,但遇到的问题并不单纯、非叁言两语即可回答的话,那麽您 post到 comp.infosystems.www.authoring.cgi上(如果是有关 http 、 html ,或 cgi通信协定)的问题可能也会得到口气和缓而有用的答覆。表面上看似 perl,但骨子里是 cgi之类的问题,如果 post到 comp.lang.perl.misc人家可能就不会这麽乐意地接受了。

几个实用的 faqs 分别是:

 http://www.perl.com/perl/faq/idiots-guide.html http://www3.pair.com/webthing/docs/cgi/faqs/cgifaq.shtml http://www.perl.com/perl/faq/perl-cgi-faq.html http://www-genome.wi.mit.edu/www/faqs/www-security-faq.html http://www.boutell.com/faq/

【译者】上面第叁份文件,perl-cgi-faq的中译版可在 http://2ti.com/cgi-bin/2t/perl/perl-cgi-faq-chi/ 处取得。最後一份(www faq)的中译版可自 http://www.acer.net/document/cwwwfaq/ 取得。


如何去除文章中的 html标签?

最正确(尽管不是最快)的方法是使用 html::parse模组(可由 cpan取得,是所有写 web程式者必备的 libwww-perl 套件的一部分)。

许多人尝试用简陋的正规表示式来解决这个问题,譬如说像 s/<.*?>//g,但这个式子在很多情况下会失败,因为要处理的字串可能会跨越断行字元,也可能含有被 quote【跳脱】的箭头号,或有 html comment出现;再加上一些疏忽,譬如,人们常忘了转换如 <的 entities(跳脱字 元)。

以下这个「简陋」的方法对大多数的档案都有效:

 #!/usr/bin/perl -p0777 s/<(?:[^>'"]*(['"]).*?\1)*>//gs

如果您想要更完整的解法,请看叁部曲的 striphtml 程式, http://www.perl.com/cpan/authors/tom_christiansen/scripts/striphtml.gz 。


如何萃取 urls?

一个快速但不完美的做法是

 #!/usr/bin/perl -n00 # qxurl - tchrist@perl.com print "&#36;2\n" while m{ < \s* a \s+ href \s* = \s* (["']) (.*?) \1 \s* > }gsix;

这个版本并不替相对式写法的 urls 作调整,也不懂代换 bases【< link base=``...''>】,或如何处理 html comments、同时处理同一个标签里的 href和 name 属性,或接受 url形式的参数。同时,它要比一个较「完整」、利用 lwp [libwww-perl]模组套件的解法,例如 http://www.perl.com/cpan/authors/tom_christiansen/scripts/xurl.gz这个程 式,快上一百倍。


如何从 user端上传资料?如何在另一台机器上开一个档案?

如果是 html表格的话,您可以使用 multipart/form-data的编码格式。 cgi.pm(可自 cpan取得)中的 start_multipart_form()这个 method 就是为此设计的,它和 startform()这个 method 是两回事。


如何在 html中做 pop-up menu(跳出式选单)?

<select><option>这两个标签。 cgi.pm模组(可由 cpan取得)对这个 widget【此指跳出式选单这个介面成分】还有许多其他的介面成分都有支援【即有制作动态标签的函式】,其中有些是以巧妙模拟的方 式达成。


如何抓 html档案?

有一个方法是,如果您的系统上装有 lynx一类的文字模式html浏览器的话,那麽可以这麽做:

 &#36;html_code = `lynx -source &#36;url`; &#36;text_data = `lynx -dump &#36;url`;

收录在 cpan里的 libwww-perl (lwp)模组则提供了更强的方法来做这件事。它不但可钻过 proxies,而且也不需要 lynx:

 # print html from a url use lwp::simple; getprint "http://www.sn.no/libwww-perl/";;
 # print ascii from html from a url use lwp::simple; use html::parse; use html::formattext; my (&#36;html, &#36;ascii); &#36;html = get("http://www.perl.com/";); defined &#36;html or die "can't fetch html from http://www.perl.com/";; &#36;ascii = html::formattext->new->format(parse_html(&#36;html)); print &#36;ascii;

如何解开或产生 web上那些冠 &#37;的码?

以下是一个解码的实例:

 &#36;string = "http://altavista.digital.com/cgi-bin/query?pg=q&;what=news&fmt=.&q=&#37;2bcgi-bin+&#37;2bperl.exe"; &#36;string =~ s/&#37;([a-fa-f0-9]{2})/chr(hex(&#36;1))/ge;

编码比较困难一点,因为您不能盲目地把所有非字母数字的字元 (\w)都一律转换成十六进位的跳脱码。很重要的是有特殊意义的字元,如 /? 便不可以 转换。要做得正确,最简单的方法大概是使用现成的 uri::escape模组,而不要重新发明轮子。这个模组是 libwww-perl 套件 (lwp)的一部分,可自 cpan取得。


如何【将 requests】转向到另一页去?

在您的回应中不要使用 content-type这个标头,相反地,用 location: 这个标头。按正式规定,应当 url: 才是正确的标头。因此 cgi.pm模组(可 由cpan取得)两个标头都送:

 location: http://www.domain.com/newpage uri: http://www.domain.com/newpage

要注意的是,由於 servers采用「最高效率化」的运作方式,故在这些标头中如 果使用相对式的 urls可能会产生奇怪的後果。


如何替网页加上密码?

不一定,要看情况。您需要读您 server的使用手册,或者查查看上头所列的几个 faqs。


要怎麽用 perl来编辑 .htpasswd和 .htgroup这两个档案?

httpd::useradmin 和 httpd::groupadmin等模组为这些档案提供了统一的物件导向介面,尽管这些档案可能以各种不同的格式储存。这些资料库可能是纯文字格式、 dbm、berkeley db或任何 dbi相容的资料库驱动程式 (drivers)。 httpd::useradmin支援`basic' 和 `digest'这两个认证模式所用的档案。以下是 一例:

 use httpd::useradmin (); httpd::useradmin ->new(db => "/foo/.htpasswd") ->add(&#36;username => &#36;password);

如何防范使用者藉由填我的 cgi表格来做坏事?

阅读 cgi security faq,(可在 http://www-genome.wi.mit.edu/www/faqs/www-security-faq.html取得),还有 perl cgi faq,在 http://www.perl.com/cpan/doc/faqs/cgi/perl-cgi-faq.html

简单一句话:使用 tainting(沾腥?)这项功能(详见 perlsec )。它会让所有不在您的 script中、来路不明的资料(譬如, cgi参数)无法放到 evalsystem等呼叫中使用。除了使用 tainting之外,绝对不要使用单一参数 的方式下参数给 system()exec(),而应将欲执行的指令及其参数放在一个序 列或阵列里面,再传给 system()exec(),这样便可避免 globbing【即被 shell先做解译】。


如何解读、萃取 email标头资料?

如果您只需要一个「快而脏」的解法的话,您可以试试这个从再版的 ``programming perl''第 222页中拿出来的例子:

 &#36;/ = ''; &#36;header = <msg>; &#36;header =~ s/\n\s+/ /g; #将延续行合并成单行 &#37;head = ( unix_from_line, split /^([-\w]+):\s*/m, &#36;header );

譬如说,您若想保留所有 received栏位资料的话【因 received栏位通常不止一个】,这个解法便不太行了。一个完整的解法是使用收录在 cpan的 mail::header模组( mailtools 套件的一部分)。


如何解译 cgi表格?

很多人忍不住要自己写程式来处理这部分的工作,所以您们大概都看过一大堆其中有 &#36;env{content_length}&#36;env{query_string}的程式码。没错,这麽 写是可以行得通,但事实上也有很多在网路上出没的这类程式根本不能用!

请不要忍不住去重新发明轮子【译者:这是英文的说法 (reinventing the wheels),也就是浪费时间做人家做过的事的意思】。请改用 cgi.pm或 cgi_lite.pm(可自 cpan取得)。如果您被困在无模组的 perl1 .. perl4的土地上,您可以试看看 cgi-lib.pl(可至 http://www.bio.cam.ac.uk/web/form.html取得)。


如何验证 email位址?

无法度。

如果没有寄封信到一个位址去试试看它会不会弹回来(即使是这麽做您还得面对停顿的问题),您是无法确定一个位址是否真的存在的。即使您套用 email 标头的标准规格来做检查的依据,您还是有可能会遇到问题,因为有些送得到的位址并不 符合 rfc-822(电子邮件标头的标准)的规定,但有些符合标准的位址却无法投 递。

许多人试图用一个简单的正规表示式,例如 /^[\w.-]+\@([\w.-]\.)+\w+&#36;/来消除一些通常是无效的 email位址。不过,这样做也把很多合格的位址给一起滤掉了,而且对测试一个位址有没有希望投递成功完全没有帮助,所以在此建议大家不要这麽做;不过您可以看看: http://www.perl.com/cpan/authors/tom_christiansen/scripts/ckaddr.gz。这个 script真的彻底地依据所有的 rfc规定来做检验(除了内嵌式 comments外),同时会排除一些您可能不会想送信去的位址(如 bill clinton【美国柯林顿总统】或您的 postmaster),然後它会确定位址中的主机名称可在 dns中找得到。这个 script 跑起来不是很快,但至少有效。

不少 cgi scripts的作者使用另一个替代的方案:用一个简单的正规表示式,(如上头的那个)。如果一个位址能让这个式子对得上的话,那麽就接受这个位址。如果这个位址对不上这个式子的话,便再向使用者讯问,以确定她们填入的这个位 址正确无误。


如何解 mime/base64字串?

mime-tools套件(可自 cpan取得)不但可处理这个问题而且有许多其他的功能。有了这个套件,解 base64码就变得像这麽容易:

 use mime::base64; &#36;decoded = decode_base64(&#36;encoded);

一个比较直接的解法是先做一点简单的转译,然後使用 unpack()这个函数的 ``u'' 格式:

 tr#a-za-z0-9+/##cd; #去除非 base64字元 tr#a-za-z0-9+/# -_#; #转换成 uu码格式 &#36;len = pack("c", 32 + 0.75*length); #计算长度字元 print unpack("u", &#36;len . &#36;_); # uu解码後 print

如何根据使用者帐户名称自动合成 email位址?

在支援 getpwuid【unix系统呼叫】、 &#36;<这个变数,和 sys::hostname模组(标准 perl 发行的一部分)的系统上,您可试试这样的做法:

 use sys::hostname; &#36;address = sprintf('&#37;s@&#37;s', getpwuid(&#36;<), hostname);

有的公司对 email位址有统筹规画,因此这麽一来您可能会合成出不被公司的 email 主机接受的位址。所以如果有这类的顾虑的话,您应该直接向 users要他们的 email 位址。 而且,并不是所有能跑 perl的系统都像 unix一样,可以很容易得到这些资料。

cpan里的 mail::util模组( mailtools 套件的一部分)中有一个 mailaddress()函数,它会试着去猜 user的 email位址。这个函数使用比上面的 code聪明的方法,它会参考安装时所得到的设定资料,但是错误仍可能发生。所以,再一次地,最好的方法通常是直接问 user 本人。


我的程式如何送/读 email?

送信:cpan 上头的 mail::mailer模组( mailtools套件的一部分)只适合在 unix 上使用,但利用到.net::smtp的 mail::inte.net模组则没有这个限制。 读信:用 cpan 上的 mail::folder模组( mailfolder 套件的一部分)或是用 cpan 上头的 mail::inte.net模组( 也是 mailtools 套件的一部分)。

 #送信 use mail::inte.net; use mail::header; #设定使用哪台主机 &#36;env{smtphosts} = 'mail.frii.com'; #制作标头 &#36;header = new mail::header; &#36;header->add('from', 'gnat@frii.com'); &#36;header->add('subject', 'testing'); &#36;header->add('to', 'gnat@frii.com'); #制作本文 &#36;body = 'this is a test, ignore'; #产生 mail物件 &#36;mail = new mail::inte.net(undef, header => &#36;header, body => \[&#36;body]); #送出 &#36;mail->smtpsend or die;

如何找出我的主机名/网域名/ip位址?

长久以来许多 code都很草率地直接呼叫 `hostname`这个程式来取得主机名。 虽然这麽做很方便,但也同时增加了移植到其他平台上的困难。这是一个很典型的 例子,在方便和可移植性之间作抉择,不论选哪一边,必须付出一些牺牲和代价。

sys::hostname这个模组(标准 perl发行的一部分)可用来取得机器的名字,然後您便可利用 gethostbyname()这个系统呼叫来找出该机的 ip位址了(假定您的 dns 运作正常)。

 use socket; use sys::hostname; my &#36;host = hostname(); my &#36;addr = .net_ntoa(scalar(gethostbyname(&#36;name  'localhost')));

至少在 unix底下,取得 dns网域名最简单的方法大概要算是直接从 /etc/resolv.conf这个档案里面找。当然,这麽做的前提是 resolv.conf这个档 案的设定必须照惯例的格式,还有就是这个档案必先存在才行。

perl在非 unix系统下尚需要一有效的方法来测出机器和网域名)


如何抓新闻讨论群的文章或群组名录?

使用.net::nntp或 news::nntpclient模组,两者皆可自 cpan下载。这些模组 让抓群组名录这类的差事变得这麽容易:

 perl -mnews::nntpclient -e 'print news::nntpclient->;new->list("newsgroups")'

如何抓/丢 ftp档案?

lwp::simple模组(可自 cpan下载)可以抓,但不能丢档案。.net::ftp模组(也可自 cpan下载)虽比较复杂,但可用来丢、也能抓档案。


如何用 perl做 rpc?

有一个 dce::rpc模组正在发展阶段(但尚未完成)。一旦完成後它会随着 dce-perl这个套件发行(可由 cpan 下载)。至於 onc::rpc这样的模组则还没听说有人在发展。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons