Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

CGI problem: USING THE FUNCTION-ORIENTED INTERFACE

by PhillipHuang (Beadle)
on Nov 18, 2015 at 15:48 UTC ( [id://1148035]=perlquestion: print w/replies, xml ) Need Help??

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

Hi monks, I read the CGI.pm: 'http://search.cpan.org/~lds/CGI.pm-3.43/CGI.pm#USING_THE_FUNCTION-ORIENTED_INTERFACE', and then try to use function-oriented interface to run the cgi example as the manual shows:
use CGI qw/:standard/; print header, start_html('Simple Script'), h1('Simple Script'), start_form, "What's your name? ",textfield('name'),p, "What's the combination?", checkbox_group(-name=>'words', -values=>['eenie','meenie','minie','moe'], -defaults=>['eenie','moe']),p, "What's your favorite color?", popup_menu(-name=>'color', -values=>['red','green','blue','chartreuse']),p, submit, end_form, hr,"\n"; if (param) { print "Your name is ",em(param('name')),p, "The keywords are: ",em(join(", ",param('words'))),p, "Your favorite color is ",em(param('color')),".\n"; } print end_html;
Yes, the cgi scripts run well and show the expected result, however, I see a lot of warnings at 'error.log':
root@Sparta:/var/www/cgi-bin# tail -f /var/log/apache2/error.log CGI::param called in list context from /var/www/cgi-bin/test.cgi line +22, this can lead to vulnerabilities. See the warning in "Fetching th +e value or values of a single named parameter" at /usr/local/share/pe +rl/5.18.2/CGI.pm line 404.
I used object-oriented style before, and this is my first experience to function-oriented style. I googled for this question and just found the items according to 'object-oriented style'. Would you please help me explain the warning message at log? and how to fix it as function-oriented style? Thanks, PH

Replies are listed 'Best First'.
Re: CGI problem: USING THE FUNCTION-ORIENTED INTERFACE
by stevieb (Canon) on Nov 18, 2015 at 16:08 UTC

    This is a known issue in CGI that can potentially lead to vulnerabilities, which can be read about here.

    Essentially, if you want to obtain a list, the documentation mentioned above states to use multi_param():

    my @values = $query->multi_param('foo');

    ...and for individual items (scalar context), use the original param() method:

    my $value = $query->param('foo');

    -stevieb

      That is all correct, but it doesn't actually address how to solve the stated problem. The presented problem appears to me to likely be about getting a single parameter but in a place where you are using a list context. It is unfortunate that the recent CGI changes didn't actually bother to address this problem. We should add a single_param() or one_param() or such method that always returns a single scalar even when called in a list context (and that value is the last value for the named parameter if multiple values were specified for the parameter).

      To suppress the warning, you need to use something like:

      ..., scalar param($name), ...

      Note that this gives you the first value and it would make more sense, IMHO, to get the last value instead. You could easily make that choice explicitly with something like:

      ... ( multi_param($name) )[0] ... # First value ... ( multi_param($name) )[-1] ... # Last value

      Except that Perl doesn't get this expression right, IMHO. The above two expressions actually have exactly the same problem as originally motivated the recent changes to CGI.pm. Those expressions that explicitly ask for a single scalar value but Perl allows them to return you other than a single scalar value.

      Specifically, ( get_list() )[$index] can (unfortunately) return an empty list instead of a single scalar. It does this when get_list() returns an empty list. In this case, it should instead return undef().

      Yes, I understand the motivation for this behavior. It is meant to allow writing code similar to:

      my( $one, $two ); while( ( $One, $two ) = ( get_list() )[0,3] ) { # Loops until get_list() returns an empty list. }

      (I know this because Larry and I talked about it in the chatterbox years ago.)

      But applying that motivation to the case of using a single index in the list slice is pretty darn convoluted:

      my $scalar; while( ( $scalar ) = ( get_list() )[0] ) { ... }

      I actually think that the original use case I presented is rather convoluted and would much rather have ( get_list() )[$i,$j] always return a list of size 2 (just like happens when using an array slice instead of a list slice).

      But I find it especially unfortunate that a list slice with a single index isn't safe to use in a scalar context without jumping through extra hoops.

      - tye        

        It is unfortunate that the recent CGI changes didn't actually bother to address this problem.

        Patches welcome.

        To the original poster - you're referring to out of date documentation. Rule one (perhaps two) with perl - look at the latest documentation, because there's a lot of old, outdated, and bad advice out there. Latest CGI.pm docs are here

        Thank you ,stevieb and tye. As your suggestions, use multi_param() or scalar param() fix it, there's no warning printed. I would raise a bug report at CPAN, and suggest to modify the example code which makes the reader confused(Since the example returns list context, it should not use 'param()').
        "Your name is ",em(scalar param('name')),p,
        or
        "Your name is ",em(multi_param('name')),p,

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1148035]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-23 22:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found