#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2004
    Posts
    27
    Rep Power
    0

    CGI: param() vs. url_param()


    I have a question regarding when you use param() vs url_param()

    Please take a look at the following script:

    Code:
    #!/usr/bin/perl
    use CGI;
    $cgi = new CGI;
    
    print "Content-type: text/html\n\n";
    print <<EOH;
    <html> <head><title>Test</title></head> <body>
    <a href="?act=login">login</a><br>
    <a href="?">home</a><br>
    <br><br>
    <form action="?act=login&fun=validate" method=post>
    name: <input type=text name=name size=20>
    <input type=submit value=send> <input type=reset value=clear>
    </form>
    <br><br><br><br>
    EOH
    
    print "<hr><b>PARAM Section:</b><br>\n";
    for $a ($cgi->param) {
        $v = $cgi->param($a);
        print "PARAM: $a = $v<br>\n";
    }
    
    print "<hr><b>URL_PARAM Section:</b><br>\n";
    for $a ($cgi->url_param) {
        $v = $cgi->url_param($a);
        print "URL_PARAM: $a = $v<br>\n";
    }
    
    print "</body></html>\n";
    If you Click the "login" link, you will see that the "act" parameter
    shows up in both the param section and the url_param section. I
    would have expected it only in the url_param section. However, if
    you click the "home" link then fill in a name and send it, you see that
    "act" now only shows up in the url_param section (as I would expect
    it too).

    My question is, why does it show up in the param() section in the first test?

    My assumption was that param() was used for postdata, while url_param() was use for the query string?

    I ask because I'm trying to use a condition on

    if ($cgi->param == 0) {
    ... do something ....
    }

    But $cgi->param is 1 when I expect it to be 0.

    Thanks.
    Last edited by abjr; April 12th, 2004 at 03:38 PM.
  2. #2
  3. 11
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Jul 2001
    Location
    Lynn, MA
    Posts
    4,635
    Rep Power
    83
    I have been programming with CGI.pm and perl for 6+ years. I've never used the "url_param" method. param() gives you data that is submitted via POST or GET silently. I've never had a reason to figure out whether data comes one way or another- it doesn't matter.

    url_param() is apparently only used when you break RFC compliance and mix GET and POST data in the same request. I wouldn't do this, as browsers can do whatever they want when you break the RFCs. You can't rely on mixing GET and POST data.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2004
    Posts
    27
    Rep Power
    0
    Originally Posted by Hero Zzyzzx
    I have been programming with CGI.pm and perl for 6+ years. I've never used the "url_param" method. param() gives you data that is submitted via POST or GET silently. I've never had a reason to figure out whether data comes one way or another- it doesn't matter.

    url_param() is apparently only used when you break RFC compliance and mix GET and POST data in the same request. I wouldn't do this, as browsers can do whatever they want when you break the RFCs. You can't rely on mixing GET and POST data.
    Thanks for the reply. I guess I'm still confused tho. If you mix POST and URL parameters, it doesn't seem that param() will work to get the URL parameters.

    The Docs for CGI.pm don't seem to say using url_param is bad.
    http://search.cpan.org/~lds/CGI.pm-3...URL_PARAMETERS

    Since you have so much experience with CGI.pm, I'd like to pick your brain. How do you handle this situation and avoid using url_param in the following code?


    Code:
    <form action="?act=login" method=post>
    name: <input type=text name=username size=20>
    <input type=submit value=send> <input type=reset value=clear>
    </form>
    What do you do to get the values of both "act" and "username" ?

    param('act') won't work, but param('username') will.

    Thanks again.
    Last edited by abjr; April 12th, 2004 at 05:19 PM.
  6. #4
  7. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Posts
    79
    Rep Power
    11
    Try something like this.

    Code:
    <form action="script.cgi" method=post>
    name: <input type=text name=username size=20>
    <input type="hidden" name="act" value="login">
    <input type=submit value=send> <input type=reset value=clear>
    </form>
    then in the script you can
    my $variable = param('act');

    I don't understand your forms "action" quite right, but If you link to the script, CGI param will do the rest.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2004
    Posts
    27
    Rep Power
    0
    Originally Posted by deadbabypizza
    Try something like this.

    Code:
    <form action="script.cgi" method=post>
    name: <input type=text name=username size=20>
    <input type="hidden" name="act" value="login">
    <input type=submit value=send> <input type=reset value=clear>
    </form>
    then in the script you can
    my $variable = param('act');

    I don't understand your forms "action" quite right, but If you link to the script, CGI param will do the rest.

    Basically I was trying to do something with a webpage that has a login and a register link.

    So when you click login the url is http://example.com/?act=login
    or if you click register the link is http://example.com/?act=register.

    The actual script's name is index.cgi, so I don't need to type it in.

    So, index.cgi looks at "act" to see what action is being performed, like login, logout, register, etc.

    When act=login it presents you with the login screen. The screen is basically a form like:

    Code:
    <form action="?act=login&fun=validate" method="POST">
    Username: <input type=text name=username size=20 maxlength=10><br> <br>
    Password: <input type=password name=userpass size=20 maxlength=20><br> <br>
    <input type=submit name=button value=Login>
    <input type=reset  name=button value=Clear>
    </form>
    So when you submit, it still sees act=login, but now it sees fun=validate and tries to validate your username and password by looking them up in a DB and checking everything.

    That's all I was trying to do. So I wasn't using hidden fields.

    I supposed I can get rid of the "fun" part and stick that ina hidden field. Bit, if I'm using a link and not a form, I can't stick "act" in a hidden field.

    My whole question boils down to when you have URL *and* POST parameters, how do you access everything? Seems to me like you need url_param and param. url_param seems like it just gets it's stuff from QUERY_STRING.

    Back in the old days of cgi-lib.pl I think it shoved everything into %in.

    I guess I'm just asking what is the proper way to handle this situation. This can't be that uncommon ask just about every URL these days has a query string


    Thanks.
    Last edited by abjr; April 12th, 2004 at 07:32 PM.
  10. #6
  11. 11
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Jul 2001
    Location
    Lynn, MA
    Posts
    4,635
    Rep Power
    83
    You're thinking about it too much. CGI::param() doesn't care about whether or not it gets its information from GET or POST- but you have to pick one. You can bounce between the two at will.

    What you're essentially doing is trying to create a system that already exists in CGI::Application ( on www.cpan.org ). The "act" parameter would be a "run mode" in CGI::Application land.

    Here's a little example script. On the first invocation it'll use a GET (with a redirect) to set the action, on the second and subsequent it'll use a POST when you use the submit() button. If you click "start over" then you're setting the action via a GET.

    This demonstrates how you can bounce between GET and POST seamlessly with CGI.pm

    If you don't feel like setting this one up yourself, you can try it on my staging server at:

    http://www.collispuro.net/cgi-bin/post_get.pl

    Code:
    #!/usr/bin/perl
    use CGI;
    use strict;
    my $q=CGI->new();
    
    if(lc($q->param('action')) eq 'start'){
        #Create a form that uses POST
        header($q,'start');
        print 
          $q->start_form(),
    	$q->popup_menu(-name=>'action', -values=>['First','Middle','Last']),
    	  $q->submit(),
    	    $q->end_form;
        footer($q);
    } elsif (lc($q->param('action')) eq 'first') {
        header($q,'First');
        footer($q);
    } elsif (lc($q->param('action')) eq 'middle') {
        header($q,'Middle');
        footer($q);
    } elsif (lc($q->param('action')) eq 'last') {
        header($q,'Last');
        footer($q);
    } else {
        #Nothing submitted, we're on an empty invocation.
        #Create a redirect that sets $q->param('action') via a GET
        print $q->redirect(-location=>$q->script_name().'?action=start');
    }
    
    ################################################################################
    sub header{
        my ($q,$parameter)=@_;
        print $q->header(-title=>$parameter||'Start'),
          $q->start_html(-title=>$q->param('action')||'Start'),
    	$q->p("We're at the ".$parameter),
    	  $q->p($q->a({href=>$q->script_name.'?action=start'},"Start Over"));
    }
    ########################################
    
    
    ################################################################################
    sub footer{
        my $q=shift;
        print $q->end_html();
    }
    ########################################
    Mixing the two is generally frowned upon, I could SWEAR I read it somewhere that because it's not RFC compliant to mix GET and POST in the same transaction that browsers couldn't be relied upon to send them both. . . Here's some relevant perlmonks discussions:

    http://www.perlmonks.org/index.pl?node_id=284816
    http://www.perlmonks.org/index.pl?node_id=48840
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2004
    Posts
    27
    Rep Power
    0
    Originally Posted by Hero Zzyzzx

    Mixing the two is generally frowned upon, I could SWEAR I read it somewhere that because it's not RFC compliant to mix GET and POST in the same transaction that browsers couldn't be relied upon to send them both. . . Here's some relevant perlmonks discussions:

    http://www.perlmonks.org/index.pl?node_id=284816
    http://www.perlmonks.org/index.pl?node_id=48840
    Thanks for the help. I guess I have some bad habits that need breaking.

    I'll have to try and avoid posting to URL with query stringshen I want to use data from the query string, and just use a hidden field instead.

    You can see what i've been trying to do here http://brigante.org/y/
    Last edited by abjr; April 13th, 2004 at 02:30 PM.

IMN logo majestic logo threadwatch logo seochat tools logo