如何验证perl CGI中的表单?

时间:2016-10-17 23:10:07

标签: perl cgi

我正在创建一个CGI perl脚本,用户输入名字,姓氏和电话号码。然后我用一些正则表达式检查他们输入的数据,以确保数据格式正确,例如:电话号码不是字母。

问题是当我从浏览器执行我的脚本时,我得到了表单,但是当我输入错误的格式时,我没有收到错误。我试过改变我的脚本,但我没有纠正这个问题。 这是我的剧本:

    #!/usr/bin/perl -w

use strict; #options

my %errors;
my %form;

my %fields = (
                "lname" => "Last Name",
                "phone" => "Phone Number",
                "fname" => "First Name"
             );

my %patterns = (
        "fname" => '[A-Z][a-z]{2,50}',
        "phone" => '[\d{3}-\d{3}-\d{4}',
        "lname" => '[A-Z][A-Za-z]{2,60}'
                );


#sequence that form fields are printed/processed
my @formSequence = ("fname", "lname", "phone");

print "Content-Type: text/html;charset=ISO-8859-1\n\n";

&startxhtml;

if ($ENV{REQUEST_METHOD} eq "GET") {
        &printform;
        exit;
}
else {
        &readformdata;
    if (&checkrequiredfields) {
        print "Form Data validated successfully!";
        exit;   
    }
    else {
        &checkrequiredfields;
        &printform;
    }
}


=for
if($ENV{REQUEST_METHOD} eq "POST")
        {
        &readformdata();
    #&printformdata;
                if(&checkrequiredfields)
                {
                print "Form data validated successfully";
                }
        else
                {
                &printform();
                }
}
=cut
print qq~</body></html>\n~;


sub checkrequiredfields
{
        my $success = 1;
        foreach(keys (%fields))
        {
                if($form{$_} !~ $patterns{$_})
                {
                        $errors{$_} = "Error: $fields{$_} is missing or incorrect format\n";
                        $success = 0;
                }
        }
        return $success;
}

sub printform
{
    print qq~<html>
         <head>
         <title>Taint Checking</title>
         </head>
         <body>
         <form action="/new-cgi/file5.cgi" method="POST">
         <center>
         <h2>Student Survery</h2>
         Last Name:<input type=text name=lname value=$form{lname}>
         <br>
         $errors{lname}
         First Name:<input type=text name=fname value=$form{fname}>
                 <br>
         $errors{fname}
         Phone Number:<input type=text name=phone value=$form{phone}>
                 <br>
         $errors{phone}
         <input type=submit value="Insert" name=Insert>
         </form>
         </center>
         </body>
         </html>
         ~;


}

sub startxhtml
{
print qq~
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Taint checking</title>
<body>
~;
}

sub readformdata
{
        #Read and decode form data
        my $input = <>;
        my @pairs = split(/&/, $input);
        my ($name, $value);
        foreach(@pairs)
                {
                ($name, $value) = split(/=/, $_);
                $value =~ tr/+/ /;
                $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
                $form{$name} = $value;
                }
}

当我从浏览器访问此脚本时,我会收到表单,但如果我输错了格式,我就不会收到警告。

有人可以建议我做错了什么。谢谢

1 个答案:

答案 0 :(得分:0)

  

当我输入错误的格式时,我没有收到错误

你在哪里寻找错误?您的代码中有错误,因此我认为您将在Web服务器错误日志中收到错误。错误在正则表达式中用于检查phone参数的有效性:

my %patterns = (
        "fname" => '[A-Z][a-z]{2,50}',
        "phone" => '[\d{3}-\d{3}-\d{4}',
        "lname" => '[A-Z][A-Za-z]{2,60}'
                );

phone正则表达式在其开头有一个额外的[。你删除它,然后我认为你的代码将按预期工作。

但是,正如I said yesterday,此代码显示了一些相当古老的编码实践。我不确定你从哪里得到这个代码,但我会敦促你研究一些更现代的Perl编码资源。我已经清理了你的代码,但是还有很多改进。

#!/usr/bin/perl

use strict;
# Use warnings rather than "-w" on the shebang
use warnings;

# Use the module that helps us write CGI programs
use CGI qw[:cgi];

my %errors;

my %fields = (
  # No need to quote the LHS of =>
  lname => 'Last Name',
  phone => 'Phone Number',
  fname => 'First Name',  # Perl tip: Always add optional comma at end of list
);

my %patterns = (
  fname => '[A-Z][a-z]{2,50}',
  phone => '\d{3}-\d{3}-\d{4}',
  lname => '[A-Z][A-Za-z]{2,60}',
);


#sequence that form fields are printed/processed
# Less punctuation using qw(...)
my @formSequence = qw(fname lname phone);

# Use the header function to print a header
print header(-charset => 'ISO-8859-1');

# No ampersands on function calls (but parenthesese look nice)
startxhtml();

if (request_method eq 'GET') {
  printform();
  exit;
}

# exit() above means we don't need the else block

# Declare variables where they are used.
my %form = readformdata();

# Inverted to logic here as checkrequiredfields() returns true (a hash of errors)
# for invalid fields
if (my %errors = checkrequiredfields(%form)) {
  # Slightly weird logic here. If checkrequiredfields() ... else checkrequiredfields() ?
  checkrequiredfields();
  printform(%errors);
} else {
  print "Form Data validated successfully!";
  exit;
}


# Don't use raw HTML. Use the Template Toolkit (or some other templating system)
print qq~</body></html>\n~;


sub checkrequiredfields {
  my %form = @_;

  my %errors;

  my $success = 1;
  foreach (keys %fields) {
    if($form{$_} !~ $patterns{$_}) {
      $errors{$_} = "Error: $fields{$_} is missing or incorrect format\n";
      $success = 0;
    }
  }
  return %errors;
}

# Please use a templating engine!
sub printform {
  # Get rid of "uninitialised value" warnings
  my %errors = (
    fname => '',
    lname => '',
    phone => '',
  );

  %errors = (%errors, @_) if @_;

  print qq~<html>
         <head>
         <title>Taint Checking</title>
         </head>
         <body>
         <form action="/new-cgi/file5.cgi" method="POST">
         <center>
         <h2>Student Survery</h2>
         Last Name:<input type=text name=lname value=$form{lname}>
         <br>
         $errors{lname}
         First Name:<input type=text name=fname value=$form{fname}>
                 <br>
         $errors{fname}
         Phone Number:<input type=text name=phone value=$form{phone}>
                 <br>
         $errors{phone}
         <input type=submit value="Insert" name=Insert>
         </form>
         </center>
         </body>
         </html>
         ~;
}

# Please use a templating system
sub startxhtml {
  print qq~
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Taint checking</title>
<body>
~;
}

# Using the param() function from CGI.pm makes this a lot easier.
sub readformdata {
  my %form;
  my @params = qw[fname lname phone];

  foreach (@params) {
    $form{$_} = param($_);
  }

  return %form;
}