http://qs321.pair.com?node_id=640119

jpk236 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I'm having some issues processing a Multiple Select box with Perl, and who else better to leverage than the Monks!

HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http:/ +/www.w3.org/TR/2002/REC-xhtml1-20020801/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Test Form</title> </head> <body> <form method="post" action="/cgi-bin/test_form.cgi"> Function:<br/> <br/> <select name="Blah[]" multiple="multiple"> <option value=""></option> <option value="Blah1">Blah1</option> <option value="Blah2">Blah2</option> <option value="Blah3">Blah3</option> <option value="Blah4">Blah4</option> <option value="Blah5">Blah5</option> </select> <br/><br/> <input type="submit" value=" Submit " /> </form> </body> </html>
Perl:
#!/usr/bin/perl -w use strict; my ($buffer, $pair, $var, $payload, $i); my (@pairs); my (%POST); read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); foreach $pair (@pairs) { ($var, $payload) = split(/=/, $pair); $payload =~ tr/+/ /; $payload =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $POST{$var} = $payload; } foreach $i ($POST{Blah}) { print "Blah: ".$i."<br/>\n"; }
This is what I thought would work.

I've tried various ways of retrieving the data, and I either get nothing back or I only get back the last element.

Thanks for any help!

- Justin

Replies are listed 'Best First'.
Re: Processing a multiple="multiple" <select>
by Corion (Patriarch) on Sep 20, 2007 at 13:37 UTC

    Don't do CGI decoding yourself, use CGI.pm or CGI::Lite:

    #!/usr/bin/perl -w use strict; use CGI; my $q = CGI->new(); my @pairs = $q->param('Blah[]'); for (@pairs) { print "Blah: $_<br />\n"; };

    Update: It is ->param('Blah[]'), not ->param('Blah')

Re: Processing a multiple="multiple" <select>
by ikegami (Patriarch) on Sep 20, 2007 at 13:38 UTC
    Use CGI! Specifically, use param in list context.
    use CGI; my $cgi = CGI->new(); my @values = $cgi->param('Blah[]');

    The problem you have is that you are assigning multiple values to a single scalar ($POST{'Blah[]'}).

Re: Processing a multiple="multiple" <select>
by snopal (Pilgrim) on Sep 20, 2007 at 13:47 UTC

    There is nothing wrong with not using the CGI module, but it has done most of the work for you.

    As far as your code, $payload =~ tr/+/ /; should really use a regex to detect multiple parameters, and an assignment to an array. It's going to take additional logic to handle the contents of your payload when the results are not a SCALAR type, as in multiple select results.

      Is there any benefit to using s///g over tr///, in this context?

      I figured that tr/// would be less "expensive" since it's designed to only do character matching.

      - Justin

        Since you brought it up, 'sed' style matching is too heavy. All you want to do is detect the situation of multiple responses.

        if ($payload =~ /+/) { # process as list }
Re: Processing a multiple="multiple" <select>
by jpk236 (Monk) on Sep 20, 2007 at 13:55 UTC
    Great suggestions. Thank you all!

    - Justin