跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

方便的 CGI 脚本编程技巧

深入探索 CGI.pm 模块

Eugene Logvinov (rezonal@univer.kharkov.ua), Web 开发员, softPilot.2000 组
Eugene Logvinov 是 softPilot.2000 工程 (CONSUL Bureau, Sevastopol, Ukraine) 的网站开发人员。他是乌克兰 Kharkov 国立大学的三年级本科生,致力于 Web 开发和技术文献的新思想。可通过 rezonal@univer.kharkov.ua 和他联系。

简介: 任一个 CGI 程序员可以从熟悉和使用现成的库中受益。在这篇文章里 Eugene Logvinov 展示了 CPAN 里的 CGI 模块如何帮助您高效和便利地工作,而且为您提供高质量的代码和参考库。因此,在该模块里嵌入 POD (Plain Old Documentation) 会是个好方法。

发布日期: 2001 年 6 月 01 日
级别: 初级
访问情况 : 1909 次浏览
评论: 


当进行 CGI 编程时您通常可以选择使用 CGI 模块或手工编写脚本。现在我们来看一看您使用 CGI 模块和它的源类能做些什么,如 CGI::Fast。虽然当一个 CGI 应用程序仅需使用少量的代码(例如当你分析 $ENV{QUERY_STRING} )或优先考虑运行速度时(例如你正在编译一个 200 KB 的模块),不使用预建立的模块而直接编写脚本会比较好。但通常来说,CGI 模块会更适用。

CGI 模块

使用 CGI 模块的第一个优点是它不可替代的文件上传功能,这一点在不同的平台和浏览器中的体现稍有不同。CGI 模块提供了上传文件所需的所有工具,包括处理 HTTP 标题 和 cookies,从命令行运行脚本,以及支持 NPH 脚本和文件上传功能。此外,模块可以在面向对象的样式和面向函数的样式中方便的使用。

CGI 模块本身是一个复杂的甚至是极难懂的包含许多 Perl 语言特征的应用程序。所以不奇怪,某些专家认为如果您理解了 GGI.pm 模块,自然也就懂得了 Perl!由 Lincoln Stein 编写的 CGI.pm 是大多数通过 Perl 构建 Web 应用程序的开发人员所广泛使用的模块。您可通过 CPAN 获得该模块,请在 CGI.pm 页上参阅它的最新文档。

不幸的是,复杂的库通常包含精妙深奥之处从而增加了使用的难度。但另一方面,CGI 模块的复杂之处只在某种条件下才表现出来。例如,在 HTML 表单里执行文件上传功能,而 CGI 文档却未能告知所有功能。在下面的清单 1 里,用户把一个文件上传到 Web 服务器上。当处理表单时,脚本获得文件的内容并显示在浏览器中;它们被附在 <pre></pre> 标记之间。


清单 1. 文件上传代码样本
#!/usr/bin/perl -Tw
use CGI ':standard';
use strict;
my $out = start_multipart_form.filefield(-name => 'upload');
$out .= br.submit('submit','Send').end_form;
my$file = param('upload');   
        #the filename returned is also a file handle
if(request_method eq 'POST' &&
    defined $file && ref $file && ref $file eq 'Fh')
{
    local $/ = undef; #read the whole file
    $out .= pre <$file>||''; 
        #takes care not to send uninitialized value
    close $file if $CGI::OS ne 'UNIX'; 
        #such as Win32 platforms
}
print header,start_html('Sample upload page'),$out,end_html;
      

在这里, "$out .= pre <$file>||'';" 这一行是必需的。当用户发送一个空文件或键入无效的文件名时,菱形操作符返回未初始化定义的值,使 pre 函数无法正常运行。

此外, $file 需要很多确认信息,因为当一个简单的表单使用 POST 方法时, $file 不再是一个文件句柄。

某些操作系统需要显式地关闭临时文件。Win32 系统是这样的,但 UNIX 平台并不如此。

这些都是文档里没有指出的所有 CGI 模块的精妙之处,而就是这些精妙之处使得模块在这些情况下变得更为复杂。


在浏览器中显示脚本错误

调试代码时,在浏览器窗口显示语法和运行时错误会很有用。在我们看来,编写脚本的整个过程应包含编辑脚本文件,保存脚本及刷新浏览器窗口。让我们来看它是怎么工作的。

清单 2. 最完整的调试打印代码执行

#!/usr/bin/perl -Tw
use strict; #restrict unsafe constructs
use CGI ':standard';
use CGI::Carp qw/carpout fatalsToBrowser set_message/;
use diagnostics -verbose; 
        #print warning diagnostics
BEGIN {
        local *LOG;
        my $size = -s "my.log" || 0;
        open LOG, ">>my.log" or die "Can't open: $!";
        carpout(\*LOG);
        my $errors = 0;
        sub handle_errors 
        #will be called with the text of the error
        {
            $errors = defined $_[0] && $_[0] || $errors, $size
        }
        set_message(\&handle_errors);
        }
END {
      my($errors, $size) = handle_errors;
      if($errors)
      {
        local *LOG;
        local $/ = undef;
        open LOG, "my.log" or die "Can't open: $!";
        seek LOG,$size,0; 
        #skip previous error log
        local $_ = <LOG>;
        close LOG;
        s/&/&/g;      
        #replace special characters
        s/"/"/g;
        s/>/>/g;
        s/</</g;
        print "<table><tr><td bgcolor=linen><pre style='color:black'>";
        print "<b>$errors</b>\n$_</pre></td></tr></table>";
      }
}
print header,start_html('Test page'),'test',end_html;
      

现在看到的是一个关于代码调试的最完整和常见的示例(根据使用的模块)。虽然在正常情况下几乎不可能同时使用所有的技术,但是每一种都值得深入研究。

虽然 -w 标记和 &quotuse strict;" 在这里很重要,但 -T 标记更是必不可少的,因为它会高亮显示脚本中的安全漏洞。


CGI::LogCarp 的使用和缺点

当诊断模块和 CGI::Carp 模块一起使用时,您会得到一些有趣的结果。CGI::Carp 把 $::SIG{__WARN__}$::SIG{__DIE__} 的信号处理器设置成几乎相同的形式, 而诊断模块则扩展已安装的信号处理器。这就是在 use 语句中所包含模块的次序是非常重要的原因。此外,模块不允许把整个 STDERR 显示在浏览器窗口,结果,仅有一小部分模块的代码被使用了。

因为重复(而且烦人)的错误信息的存在,诊断模块所显示的附加错误数据不是每次都容易读的。这一点对 -verbose 标记尤为明显,该标记只有在第一次运行时才被使用。

该例中的另一个不理想之处是它相对长的编译时间,可通过将代码碎片复制到其它模块来避免。最好使用绑定的文件句柄把 STDERR 直接写到一个标量值里,接着在浏览器中显示错误信息,这样比把 STDERR 写到文件里要好。不幸的是,由于 Perl 的错误目前还不可能做到这一步。

Tie::STDERR 模块的设计者 Jan Pazdziora 承认“Tie::STDERR 能捕获编译时的错误,但只知道错误的存在,而无法知道原因。我也不知道如何修正。”所以目前唯一的解决办法是将 STDERR 重定向到文件中。

在完成脚本的设计和测试阶段后,也许跳过调试阶段而先把一小部分代码上传到服务器上会更好。Perl Diver(一个简单的 Perl 脚本)可以用来判定某些服务器特征(已安装模块、发送邮件的位置和环境变量等等)。您也可以看一下 脚本详细描述


CGI::* 类型的标准模块

作为主要功能的补充,CGI 模块还有一些附加函数,其中包括一条 HTML 编写函数,据模块的设计者所说,“为了 CGI::* 模块,应该放弃使用该函数。”(HTTP::* 和 HTML::* 也应该补充在此处)。很多模块的函数并不总是方便使用的,这就是为什么经常使用 CGI.pm 来代替而放弃使用 HTML 编写函数的原因。CGI::Minimal 和 CGI_Lite 模块可以更好地完成该功能。

复杂的 CGI 脚本编写有时需要 Web 相关模块。它们的执行通常依赖特定的任务或通用 HTML 编写技术。有关这一点的模块清单可以从 CPAN (请参阅 参考资料)上获得,那里不仅有关于 Perl 的编程档案,还是编程理念的中心。我强烈建议您在编写复杂的脚本之前先访问 CPAN,这是非常值得的。


参考资料

关于作者

Eugene Logvinov 是 softPilot.2000 工程 (CONSUL Bureau, Sevastopol, Ukraine) 的网站开发人员。他是乌克兰 Kharkov 国立大学的三年级本科生,致力于 Web 开发和技术文献的新思想。可通过 rezonal@univer.kharkov.ua 和他联系。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=20888
ArticleTitle=方便的 CGI 脚本编程技巧
publish-date=06012001
author1-email=rezonal@univer.kharkov.ua
author1-email-cc=rezonal@univer.kharkov.ua

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。