Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Filtering CGI Input

by awohld (Hermit)
on Apr 24, 2005 at 05:17 UTC ( #450871=perlquestion: print w/replies, xml ) Need Help??

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

I have a filter at the beginning of my CGI:
my $sid = $q->param ('sid'); if($sid !~ /0-9/) { print "Content-type: text/html\n\n"; print "Invalid Input!"; exit(0); }
I want it to exit out if the input contains anything but numbers. My input should be any number from 0 to 99999.

This code seems to match every input. What's wrong?

Replies are listed 'Best First'.
Re: Filtering CGI Input
by Tanktalus (Canon) on Apr 24, 2005 at 05:29 UTC

    Your regexp is matching anything that has the literal string "0-9" in it. And then the !~ negates that match. Thus, since anything you've tried probably does not include the literal string "0-9" somewhere in it, the full expression is always true.

    You want to match a character class - e.g., \d matches all digits, thus using /\d/ is a bit closer. What this does is match any digit, anywhere in the string.

    You actually want to match 1 to 5 digits. So you can use the {} modifier: /\d{1,5}/. This matches anywhere from 1 to 5 digits, anywhere in the string. But that still matches "a1b" since it has somewhere between 1 and 5 digits. So you want to anchor the match to both the beginning and the end. And thus we get /^\d{1,5}$/.

    Hope that helps. perlretut may help.

      I want to modify this filter so that it will accept lat/longs (-88.88888) that is 9 characters long and can include 0-9 and - and .

      So does this look right?

      ~/^\d|\c(.|-)$/

      All that I really want to do is make sure no other characters get in there except digits (0 thru 9) and the "." and "-" characters.

        9 characters long? Does 1.3456789 count? Or do you really mean 5 digits after the decimal place only? I'm assuming the latter. And that the - sign doesn't count.

        /^-?(\d{1,3}(?:\.\d{1,5})?)$/
        That is, an optional leading - sign, followed by 1 to 3 digits (to allow for 180 degrees East/West), followed, optionally, by a dot, and then 1 to 5 more digits.

        Better yet, try:

        use Regexp::Common; /^$RE{num}{decimal}{-places=>'0,5'}$/ and $_ <= 180;
        No sense reinventing the wheel. :-)

Re: Filtering CGI Input
by matthewb (Curate) on Apr 24, 2005 at 08:30 UTC

    Both CGI::Untaint and Data::FormValidator provide an already-tested mechanism to do what you're attempting. They also both allow you to integrate your own patterns.

    Overkill for a simple situation? I think not - as your application grows (and it will) would you prefer a scalable solution that you can get advice about from other users or a bunch of special-case regexes in your code?


    MB
Re: Filtering CGI Input
by davido (Cardinal) on Apr 24, 2005 at 05:31 UTC

    Several things are wrong. /0-9/ will match '0-9' (exactly). And since it's a negated match, basically you are accepting all input unless it contains the literal text '0-9'.

    You need a character class.

    if( $sid =~ /^[^0-9]$/ ) { # exit here...... }

    The above code states if there are any characters in the string that are not numbers 0 through 9, exit.

    It might actually be better to do it this way though:

    if( $sid !~ m/^([0-9]{1,5})$/ ) { # exit } else { $input = $1; }

    ...or better yet...

    if( $sid =~ m/^([0-9]{1,5})$/ ) { $input = $1; } else { # exit }

    I think negated matches ( the !~ operator ) are usually just a way of adding confusion, and should be avoided unless absolutely necessary.


    Dave

Re: Filtering CGI Input
by chas (Priest) on Apr 24, 2005 at 05:29 UTC
    $sid !~ /0-9/ is true if the input does not contain the exact sequence "0-9". You probably want something like
    $sid =~ /^\d{1,5}$/
    (That also matches 000, etc, but presumably that's OK.)
    chas
Re: Filtering CGI Input
by crashtest (Curate) on Apr 24, 2005 at 06:15 UTC
    My input should be any number from 0 to 99999.
    Well, then why use regular expressions at all? Isn't this just a simple number comparison? How about:
    if ($sid < 0 or $sid > 99_999){ ... }
      No, it is not that simple as the following code demonstrates:
      #!/usr/bin/perl use strict; my $num = "123abc"; print "valid\n" if $num > 0 && $num < 99999; exit;
      This will print 'valid', even though it does not meet the OP's criteria.

      Thus, if the value "123abc" is passed from a web form to a cgi script, the code you suggest will validate it. The reason for this is because when using numeric comparisons, Perl will treat any string that begins with a number as a number. This is clearly not what the OP wants.

      davidj

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2019-06-17 00:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Is there a future for codeless software?



    Results (76 votes). Check out past polls.

    Notices?
    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!