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


in reply to [SOLVED] Unwanted parameter when executing CGI scripts

use CGI; my $cgi = CGI->new; for ($ENV{QUERY_STRING}) { delete $cgi->{param}{keywords} if length && !/[&=]/; } ... rest of the code goes here ...

Of course, the better answer is: stop using CGI.pm; use Plack.

PS: yes, it does have to do with <isindex>. This is a very old HTML tag that was the predecessor to modern HTML forms. It submitted just a single field which was intended as a "search" field. Because only a single field was ever submitted, there was no need for the "&fieldname=" bits of the query string. Thus CGI.pm assumes that when there is no ampersand nor equals sign in the query string, an isindex-style query has been made.

perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Replies are listed 'Best First'.
Re^2: Unwanted parameter when executing CGI scripts
by Anonymous Monk on Jan 04, 2013 at 18:38 UTC

    Wow, that was fast!

    But wouldn't that kill a "wanted" parameter "keywords" as well? In other words, as I wrote above, if I call

    /cgi-bin/script.pl

    the "keyword" parameter should not be existent, but if I call

    /cgi-bin/script.pl?keywords=foo

    the "keyword" parameter should be available in the script.

    Could you please let me know if I have misunderstood the concept of your suggestion?

    Regards,

    Nocturnus

Re^2: Unwanted parameter when executing CGI scripts
by Nocturnus (Beadle) on Jan 04, 2013 at 18:48 UTC

    Please forget about my comment above. It was relating to the first version of your answer and does not make much sense any more; unfortunately, I have posted when I was not logged in and thus can't delete it now.

    I think your solution will work. Thank you very much - I'll try that way. Nevertheless, I was hoping that there is something more elegant. I will look into Plack.

    Thanks again,

    Nocturnus

Re^2: Unwanted parameter when executing CGI scripts
by Nocturnus (Beadle) on Jan 05, 2013 at 08:29 UTC

    After thinking again about your code, I have one question and one additional remark. Please note that C and assembler is my main business, so I am usually using the sort of Perl syntax which is similar to C, and I might have misunderstood what you are doing in your code. Anyways:

    delete $cgi->{param}{keywords} if length && !/[&=]/;

    Do I get this right: The "keywords" parameter is deleted if the length of the query string is >0 and the query string does not contain = or &? The code would then fail when the script would be called without any query string (which was the situation where I was surprised by the problem the first time). If I am right, we should write

    delete $cgi->{param}{keywords} if (!defined || !length || !/[&=]/;

    instead. Correct?

    One more problem / remark: Suppose the script is called via

    /cgi-bin/script.pl?Test

    CGI.pm then would generate a parameter "keywords=Test", and we would remove that parameter accordingly. But that would be only the half of the way: I think that "Test" in that case should be a KEY in the parameter list which has an empty (or undefined) value. How exactly should we handle this? What is the difference between the following calls (from the viewpoint of the CGI specification)?

    /cgi-bin/script.pl /cgi-bin/script.pl? /cgi-bin/script.pl?Test /cgi-bin/script.pl?Test=

    Of course, I'd test myself before boring others, but I am not sure if it would be a good idea to find out by using CGI.pm or Plack, because I now have learned that (at least) CGI.pm does unexpected things, so I could not use that for testing. Not sure about Plack, though.

    Regards,

    Nocturnus

      You needn't test for whether $ENV{QUERY_STRING} is defined or not, because undefined things automatically have zero length.

      "CGI.pm then would generate a parameter "keywords=Test", and we would remove that parameter accordingly. But that would be only the half of the way: I think that "Test" in that case should be a KEY in the parameter list which has an empty (or undefined) value."

      Then you could try something like:

      for ($ENV{QUERY_STRING}) { $cgi->{param}{delete $cgi->{param}{keywords}} = "" if length && !/[&=]/; }
      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

        Thank you very much for your answer, but I just haven't got it yet. Please forgive me if I'm too stupid, but I think you are testing if the query string's length is >0, and your code only gets executed if this condition is true.

        But when calling the script without any parameters, the length of the query string is 0, and that evaluates to false, so the whole line doesn't get executed.

        Please correct me if I am wrong.

        Regards,

        Nocturnus