简体   繁体   中英

Accessing multiple <select>-ed parameters with Perl CGI

I am using the Perl CGI module. If I have HTML like this

<select multiple name="FILTER_SITE">
  <option>1</option>
  <option>2</option>
</select>

and submit my form I can get something like this in the URL: [..] FILTER_SITE=1&FILTER_SITE=2

Perl's my $FILTER_SITE = $cgi->param('FILTER_SITE'); wil capture only the first instance.

How can I make use of both (in this case)? Hack it and parse the referrer myself and add them to an array is my first idea but it'd be a bit messy, then again I'm hardly versed in CGI.pm or Perl.

With Data::Dumper, interestingly

print "<pre>".Dumper($cgi->param('FILTER_SITE')) . "</pre>";

$VAR1 = '1';
$VAR2 = '2';

NOTE: Current documentation (as of 2020 May 29) says this method could cause a security vulnerability. Please check my answer below.

The param method supplies a single value in scalar context and (potentially) multiple values in list context. Read about it here .

So if you change your code to, for example

my @FILTER_SITE   = $cgi->param('FILTER_SITE');

then the array will contain all selected values of the option.

If it suits your code better, you can also write

for my $FILTER_SITE ($cgi->param('FILTER_SITE')) {
  :
}

I know this is an old post, but looks like few things changed since this question was answered. I want to post the latest info on this, especially because the accepted answer is now considered a security vulnerability. CGI.pm documentation says

{ Warning - calling param() in list context can lead to vulnerabilities if you do not sanitise user input as it is possible to inject other param keys and values into your code. This is why the multi_param() method exists, to make it clear that a list is being returned, note that param() can still be called in list context and will return a list for back compatibility. Warning - calling param() in list context can lead to vulnerabilities if you do not sanitise user input as it is possible to inject other param keys and values into your code. This is why the multi_param() method exists, to make it clear that a list is being returned, note that param() can still be called in list context and will return a list for back compatibility. }

It is recommended to use $cgi->multi_param method instead.

Example of parsing values

    #!/usr/bin/perl

    use Encode;

    print "Content-Type: text/html; charset=UTF-8\n\n";

    if($ENV{'REQUEST_METHOD'} eq "POST") {
      read(STDIN, $querystring, $ENV{'CONTENT_LENGTH'});
     print "<h1>POST</h1>";
    } else {
      print "<h1>GET</h1>";
      $type = "display_form";
      $querystring = $ENV{'QUERY_STRING'};
    }

    print "<p>$querystring</p>";

    if (length ($querystring) > 0){
      @pairs = split(/&/, $querystring);
      foreach $pair (@pairs){
           ($name, $value) = split(/=/, $pair);
           $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
           $name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
           if (exists $in{$name}) {
             $value = "$value,$in{$name}";
           }
           $in{$name} = $value;
      }
    }

   foreach my $val (sort keys %in) {
     print "<p>$val: $in{$val}</p>";
   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM