http://www.perlmonks.org?node_id=1233567


in reply to CGI scoping question

You have seemed to have left quite a bit out of your description.

but based on what you did say let me propose an explanation. If i expected that

my $index = $q->param('orderby');
was to give me the value of a cgi parameter called orderby i would expect to see a html section something like
<input type="text" name="orderby" value="10" />
But i do not see you posting such a section.

Replies are listed 'Best First'.
Re^2: CGI scoping question
by WoodyWeaver (Monk) on May 10, 2019 at 18:14 UTC
    I did try to omit pieces that seemed irrelevant, so I didn't include how the parameters were being set. Several parameters are being set through classical forms, e.g.
    print $q->start_form(), 'Please choose an action: &nbsp;', $q->popup_menu( -name => 'exec', -values => ['add', 'list', 'search' +] ), $q->popup_menu( -name => 'table', -values => ['users', 'VPN', 'VMacc +ounts', 'supporting tables'] );
    This orderby and desc fields are not -- they are being manually set via
    print $q->h2($subtitle), "\n<table border>\n\t<tr><th>ID</th><th>Type +"; foreach (my $i=1; $i<=$#USER_FIELDS; $i++) { my $flags = '?exec=list&amp;table=users&amp;orderby='.$i; if ($i == $index) { $flags .= '&amp;desc=1'; } print "</th><th><a href=\"$flags\">$LABELS{$USER_FIELDS[$i]}</a>"; } print "</th></tr>\n";
    (The titles on the table lets you sort by that field, and if you click on an already-sorted field it reverses it.)

    I didn't think that relevant, because its all upstream: at the invocation I'm looking at, the value of orderby is being shown in the $q->Dump output; yet its vanished by the time the first subroutine is called. That is, I've got a print statement, a couple of local assignments, two if's that call listUsers(), a little DB work at the top of sub listusers, and then orderby has vanished. I am assuming there is some sort of global variable passing between CGI instances that I don't know about? ... well, I'm confused.

      I also think you haven't yet provided enough information.

      I didn't think that relevant

      To determine what is relevant and what isn't, remove a piece of code. If the problem remains, that piece of code wasn't relevant, if the problem goes away or changes, that piece of code probably was relevant, so keep it in. One of the important aspects of a Short, Self-Contained, Correct Example is that it runs, so that we can download and run the code ourselves to reproduce the problem on our end - you'll get help much quicker this way, and with less guessing :-)

      Also, in case you're not, Use strict and warnings.

        Good point. It should help with my enlightenment, as well as make it easier for others to see and comment. I've stripped out what is clearly not relevant, and left just bits of the global block and the subroutine. It does still reflect the issue. Error log complains about some undefined $term in a print statement, which is ok. In an example where I see the issue, the source code of the rendered page has
        <!--bless({ ".charset" => "ISO-8859-1", ".fieldnames" => {}, ".parameters" => ["exec", "table", "orderby"], ".r" => bless(do{\(my $o = 94308584056848)}, "Apache2::RequestRec"), "escape" => 1, "param" => { exec => ["list"], orderby => [2], table => ["users"] }, "use_tempfile" => 1,
        yet
        <!-- variables (index, desc) are (10, 1) -->
        which would have been correct from a previous instance. The CGI:
        #!/usr/bin/perl -w # vim:sw=2:et:ic:sm:syn=perl:nu:si use Getopt::Std; use strict; use warnings; use DBI; use CGI; use CGI::Carp qw(warningsToBrowser fatalsToBrowser); use Data::Dump qw(dump); my $DEBUG = 1; # SQL fields for table users my @USER_FIELDS = qw(usertypes_idusertypes lastname firstname middlename suffix email +cellPhone authorizingParty lastAccountReview lastReviewRequest accoun +tsOwned); # Human names for user fields my %LABELS = ( 'usertypes_idusertypes' => 'Type of User', 'lastname' => 'Last Name', 'firstname' => 'First Name', 'middlename' => 'Middle Name', 'suffix' => 'Suffix', 'cellPhone' => 'Cell', 'email' => 'Email Address', 'authorizingParty' => 'ID for Authorizing Party', 'lastAccountReview' => 'Date Accounts Last Validated', 'lastReviewRequest' => 'Latest Date for Account Revalidation', 'accountsOwned' => 'Number of Accounts Owned' ); my %opts; my $OPTIONS = 'h'; my $optsStat = getopts( $OPTIONS, \%opts ); # sanity checks go here; provide prompt and set $optsStat = 0; if ( ( $optsStat != 1 ) or ( $opts{'h'} ) ) { HELP_MESSAGE(); exit; } my $q = CGI->new; print '<!--', dump($q), "-->\n"; print $q->header, $q->start_html( -title => 'Update identity user base for identity management store' +, -author => 'woody.weaver@us.ibm.com', ), $q->h1('Manage users and other lists for the OMS master repository') +, $q->p('Web interface for managing users in the OMS centralized back +end repository'), "\n"; if ($DEBUG) { print $q->hr; print $q->p('Debugging: '), $q->Dump, $q->hr; } print $q->start_form(), 'Please choose an action: &nbsp;', $q->popup_menu( -name => 'exec', -values => ['add', 'list', 'search' +] ), $q->popup_menu( -name => 'table', -values => ['users', 'VPN', 'VMacc +ounts', 'supporting tables'] ), '<p>', $q->submit, '<p>', $q->hr; my $exec = $q->param('exec'); my $table = $q->param('table'); if ($exec) { # ok, so this should be a jump table. Sue me. if ( $exec eq 'list' ) { if ( $table eq 'users' ) { listUsers(); } else { print "Sorry, I don't know how to list the table $table\n"; } } else { print "Sorry, I don't understand the action $exec\n"; } } ## end if ($exec) print "<p>", $q->submit; print $q->hr, $q->end_form, "\n", $q->end_html; sub listUsers { my $dbh = DBI->connect( 'DBI:mysql:identity', 'idmanagement', + '' ) or die "Cannot connect: $DBI::errstr"; my $preparestr = 'SELECT * FROM usertypes'; my $sth = $dbh->prepare($preparestr) or die "Can't prepare $p +reparestr: $dbh->errstr()"; $sth->execute() or die "Can't execute $preparestr: $dbh->errstr()"; my %usertypes; while ( my $ref = $sth->fetchrow_arrayref() ) { $usertypes{$$ref[0]} = $$ref[1]; } $preparestr = 'SELECT idusers, category'; foreach (my $i=1; $i<=$#USER_FIELDS; $i++) { $preparestr .= ", $USER_FIELDS[$i]"; } $preparestr .= ' FROM users, usertypes WHERE usertypes_idusertypes = usertypes.idusertypes ORDER by '; # what should we order the table by? die "q got killed!" unless defined $q; my $index = $q->param('orderby'); my $desc = $q->param('desc'); $index = 1 if not defined $index; print "\n<!-- variables (index, desc) are ($index, $desc) -->\n" if +$DEBUG; $preparestr .= $USER_FIELDS[$index]; $preparestr .= ' DESC' if $desc == 1; print "\n<!-- Preparing $preparestr -->\n" if $DEBUG; $sth = $dbh->prepare($preparestr) or die "Can't prepare $preparestr: + " . $dbh->errstr(); $sth->execute() or die "Can't execute $preparestr: ".$dbh->errstr(); print 'Found ', $sth->rows, " users in table\n"; my $subtitle = 'Listing of Users, ordered by '; $subtitle .= $LABELS{$USER_FIELDS[$index]}; $subtitle .= ' (descending)' if $desc == 1; print $q->h2($subtitle), "\n<table border>\n\t<tr><th>ID</th><th>Typ +e"; foreach (my $i=1; $i<=$#USER_FIELDS; $i++) { my $flags = '?exec=list&amp;table=users&amp;orderby='.$i; if ($i == $index) { $flags .= '&amp;desc=1'; } print "</th><th><a href=\"$flags\">$LABELS{$USER_FIELDS[$i]}</a>"; } print "</th></tr>\n"; while ( my $ref = $sth->fetchrow_arrayref() ) { my $firstone = 1; print "\t<tr>"; foreach my $term (@$ref) { if ($firstone) { print "<td><a href=\"editUser.pl?iduser=$term\">$term</a></td> +"; $firstone = 0; } else { print "<td>$term</td>"; } } print "</tr>\n"; } print "</table>\n"; } ## end sub listUsers sub HELP_MESSAGE { print <<EOH; usage: $0 [-$OPTIONS] -h this message EOH return; }
      Several parameters are being set through classical forms
      ...
      This orderby and desc fields are not
      If you are sending a form to your script then the parameters in the URL are not available to CGI's param(). You need to use url_param()
      my $index = $q->url_param('orderby');
        (Bows head) Fascinating, and an issue I would not have guessed. http://127.0.0.1/id/bin/example.pl?exec=list&table=users&orderby=10 has lines
        my $index_url = $q->url_param('orderby'); my $index = $q->param('orderby'); my $desc_url = $q->url_param('desc'); my $desc = $q->param('desc');
        and produces <!-- variables (index, desc, index_url, desc_url) are (1, , 10, ) -->. The namespace collision did me in.