Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Random F%^k up strings!

by TroyH (Initiate)
on May 20, 2017 at 22:59 UTC ( [id://1190776]=perlquestion: print w/replies, xml ) Need Help??

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

I have problem with comparing two strings, one is generated from a random “if else” it's called $answer, the other is input from a form, it called $useranswe. If I test to see if there the same it fails but if I say $answer = “HsRtm” then compare it to $useranswer it works.

1. $randomNumber = int(rand(100)) +1; if ($randomNumber < 100 and $randomNumber > 50) { $answer = "kbNtA"; } else { $answer = "WiaNq"; } 2. $answer = “qUfuT”;

1. doesn't work but 2. does.

Can anyone explain to me why does the random statement corrupt the $answer

Replies are listed 'Best First'.
Re: Random F%^k up strings!
by marinersk (Priest) on May 21, 2017 at 04:08 UTC

    I'd lay good odds that randis not actually messing up your strings. You are probably making a mistake in the declaration of your variables.

    Let's walk through the process.

    I added one line to your code so we could see the results:

    $randomNumber = int(rand(100)) +1; if ($randomNumber < 100 and $randomNumber > 50) { $answer = "kbNtA"; } else { $answer = "WiaNq"; } print "Answer = [$answer]\n";

    It seems to be working fine:

    S:\PerlMonks>perl scope0.pl Answer = [kbNtA] S:\PerlMonks>perl scope0.pl Answer = [kbNtA] S:\PerlMonks>perl scope0.pl Answer = [kbNtA] S:\PerlMonks>perl scope0.pl Answer = [kbNtA] S:\PerlMonks>perl scope0.pl Answer = [WiaNq]

    However, you're not running strictand warnings, which are critical to avoid mistakes and many bad programming techniques. So I cleaned up the code a bit:

    #!/usr/bin/perl use strict; use warnings; $randomNumber = int(rand(100)) +1; if ($randomNumber < 100 and $randomNumber > 50) { $answer = "kbNtA"; } else { $answer = "WiaNq"; } print "Answer = [$answer]\n";

    That doesn't work so well, and the issues raised could be the source of your problem. (It's hard to tell since you clearly did not show enough code and data to reproduce the problem.)

    S:\PerlMonks>perl scope2.pl Global symbol "$randomNumber" requires explicit package name at scope2 +.pl line 5. Global symbol "$randomNumber" requires explicit package name at scope2 +.pl line 6. Global symbol "$randomNumber" requires explicit package name at scope2 +.pl line 6. Global symbol "$answer" requires explicit package name at scope2.pl li +ne 7. Global symbol "$answer" requires explicit package name at scope2.pl li +ne 9. Global symbol "$answer" requires explicit package name at scope2.pl li +ne 11. Execution of scope2.pl aborted due to compilation errors. S:\PerlMonks>

    So I cleaned up the errors:

    #!/usr/bin/perl use strict; use warnings; my $answer = ''; my $randomNumber = int(rand(100)) +1; if ($randomNumber < 100 and $randomNumber > 50) { $answer = "kbNtA"; } else { $answer = "WiaNq"; } print "Answer = [$answer]\n";

    And it seems to be working again:

    S:\Steve\Dev\PerlMonks\P-2017-05-20@2349-Variable-Scope-Failure>perl s +cope3.pl Answer = [WiaNq] S:\Steve\Dev\PerlMonks\P-2017-05-20@2349-Variable-Scope-Failure>perl s +cope3.pl Answer = [WiaNq] S:\Steve\Dev\PerlMonks\P-2017-05-20@2349-Variable-Scope-Failure>perl s +cope3.pl Answer = [kbNtA]

    I'd suggest using strictand warningsand declaring your variables with myand then re-run the script. I would not be surprised if Perl tells you what you're doing wrong.

      #!/usr/bin/perl use CGI qw/:html3 :standard/; use Fcntl qw/:flock/; # ################################################# # # # My Capcha # # # # Starting Date: April 20, 2017 # # Last Modified: May 21, 2017 # # # # Written by Troy Hammack # # Email: troylh@pacbell.net # # # ################################################# # # $ENV{"PATH"}=''; $ENV{"BASH_ENV"}=''; print "Content-type:text/html\n\n"; if ($ENV{'REQUEST_METHOD'} eq 'GET') { @pairs = split(/&/, $ENV{'QUERY_STRING'}); } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') { read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @pairs = split(/&/, $buffer); } else { print "Content-type: text/html\n\n"; print "<P>Use Post or Get"; } foreach $pair (@pairs) { ($key, $value) = split (/=/, $pair); $key =~ tr/+/ /; $key =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $value =~s/<!--(.|\n)*-->//g; if ($formdata{$key}) { $formdata{$key} .= ", $value"; } else { $formdata{$key} = $value; } # # Test to see if Reset button was selected and clear all values in the + keys # if ($formdata{'reset'} eq "Reset") { foreach $pair (@pairs) { ($key, $value) = split (/=/, $pair); $formdata{$key} = ""; } } # # The answer < -- If I use this it doesn't work! # my @chars = ("A".."Z", "a".."z"); my $answer; $answer .= $chars[rand @chars] for 0..4; # # $answer = "ghRuE"; <-- If I use this it works fine. # print <<EndHTML; <html><head> <meta http-equiv="Content-Type" content="text/html; charset=windows-12 +52"> <title>My Capcha</title></head> <body background="http://www.astrologybythesea.com/images/bg_coastR.jp +g"> <!-- <p><u><font size="5" color="#0000FF">My Capcha</font></u></p> --> <form action="/cgi/mycapcha.cgi" method="post"> <table border="0" width="100%"> <center> <H5>AntiBot Verifiication</H><br> <div style='height:20px;width:70px;border:1px solid blue'> <font size="2">$answer</font></div> <!-- Now get users input --> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <input type="text" size="8" maxlength="8" name="useranswer" value="$fo +rmdata{'useranswer'}"> <input type="submit" name="verify" value="Verify"><br>&nbsp;&nbsp;&nbs +p;Type the above characters</center> EndHTML # # $UpperCaseUserAnswer is UserAnswer converted to uppercase # $UpperCaseUserAnswer = uc $formdata{'useranswer'}; # # $UpperCaseAnswer is Upper case of $anwser # ================================================= $UpperCaseAnswer = uc $answer; if ($UpperCaseUserAnswer eq $UpperCaseAnswer) { goto END; exit(0); } print <<EndHTML; </table></form></body></html> EndHTML exit(0); #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= END: print "<br>Finished Capcha; exit(0);

        You should have used <code> and </code> to delimit your code. it makes it much easier to read

        Despite that i dont think you understand the nature of how cgi works. Each time that runs because the user pressed verify it generates a new $answer, that bears no relationship to whatever was typed into $useranswer the previous time it was displayed to the user. This is what you test against the users answer so it is bound not to match this run.

        I dont do capcha stuff much, but i would include a hidden string to return in the post. This hidden string would have been used to create the previous "$answer" in a way that the end user would not be able to replicate easily. When this parameter is found in the reply you would then use it to regenerate the previous answer and compare it to what was returned in $useranwser. I might pick CGI::Session as the mechanism to store the previous answer and have the sessionid be used as the returned value to regenerate the $answer.

        Edit: add example code

        #!/usr/bin/perl use strict; use warnings; select STDOUT; $| = 1; my $session_dir='/home/huck/monks-sessions'; # must exist and be wr +iteable by www userid my $expires='+1m'; use CGI; use CGI::Session; my $session; my $cgi = CGI->new; my $tssid = $cgi->param('tssid'); my $sessiona1=undef; my $sessiona3={Directory=>$session_dir}; unless ($tssid){ new_capcha(''); } # no tssid else { $session = CGI::Session->load($sessiona1, $tssid, $sessiona3); if ( $session->is_expired ) { $session->delete(); $session->flush(); new_capcha('Try again: took too long'); } elsif ( $session->is_empty ) { $session->delete(); $session->flush(); new_capcha('Try Again:Session not found'); } else { my $oldanswer=$session->param('answer'); my $useranswer= $cgi->param('useranswer'); if (uc($oldanswer) ne uc($useranswer)) { $session->delete(); $session->flush(); new_capcha('Try Again:didnt Match'); } } } # the only way it can get here is if answer is right print $cgi->header(); print <<EndgoodHTML; <html><head> <meta http-equiv="Content-Type" content="text/html; charset=windows-12 +52"> <title>My Capcha</title></head> <body> You won </body></html> EndgoodHTML CGI::Session->find($sessiona1 ,sub {} ,$sessiona3); # clean expired +sessions exit; sub new_capcha{ my $reason=shift; $session = CGI::Session->new($sessiona1, undef,$sessiona3); my @chars = ("A".."Z", "a".."z"); my $answer; $answer .= $chars[rand @chars] for 0..4; $session->expires($expires); $session->param('answer',$answer); $session->flush(); $tssid= $session->id; print "Content-type:text/html\n\n"; print <<EndHTML; <html><head> <meta http-equiv="Content-Type" content="text/html; charset=windows-12 +52"> <title>My Capcha</title></head> <body background="http://www.astrologybythesea.com/images/bg_coastR.jp +g"> <!-- <p><u><font size="5" color="#0000FF">My Capcha</font></u></p> --> <form action="/monks-bin/capcha.pl" method="post"> <table width="100%" border="0"> <center> <h5>AntiBot Verifiication</H><br /> $reason <div> <font size="2">$answer</font></div> <!-- Now get users input --> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs +p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <input type="text" size="8" maxlength="8" name="useranswer" value=""> <input type="hidden" name="tssid" value="$tssid"> <input type="submit" name="verify" value="Verify"><br />&nbsp;&nbsp;&n +bsp;Type the above characters </h5></center></table></form></body></html> EndHTML exit; } # newcapcha

Re: Random F%^k up strings!
by tobyink (Canon) on May 21, 2017 at 09:10 UTC

    the other is input from a form, it called $useranswe.

    Okay.

    then compare it to $useranswer

    Well, there's your problem. $useranswe and $useranswer are two different variable names.

    Now, I know what you're thinking. I spelt the variable name wrong when posting on PerlMonks. It's correct in my code. But how do we know that? You haven't shown us the code where you read the user input. You haven't shown us the code where you do the string comparison.

Re: Random F%^k up strings!
by derby (Abbot) on May 20, 2017 at 23:47 UTC

    Hi TroyH and welcome to the monastery. Your question is a bit vague and does not really give enough info to give a proper answer (see How do I post a question effectively?). Is the form a web form or some type of console input. If console, I'd hazard a guess that the input has a trailing newline that needs to be chomped. Other than that, I think you'd need to reduce your comparison code to a simple test case and post it back here ... could be a problem with your comparison (ahh ... the many times I used = instead of == or eq).

    -derby
Re: Random F%^k up strings!
by AnomalousMonk (Archbishop) on May 21, 2017 at 00:27 UTC

    This doesn't speak to your problem, but FWIW there's a neat way to equally select at random from an array, as you seem to be doing:

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my @ra = qw(x y z); printf '%s ', $ra[ rand @ra ] for 1 .. 20; print ''; ;; my %h; $h{ $ra[ rand @ra ] }++ for 1 .. 1_000_000; dd \%h; " y y y x x z y y z z z y x z x y x y y x { "x" => 333660, "y" => 332908, z => 333432 }
    (Of course, the rand built-in isn't all that random, but that's another tale for another thread.)


    Give a man a fish:  <%-{-{-{-<

Re: Random F%^k up strings!
by dsheroh (Monsignor) on May 21, 2017 at 08:29 UTC
    Can anyone explain to me why does the random statement corrupt the $answer
    It doesn't. Your problem lies in some of the code that you haven't shown us. At a guess, my money is on the comparison itself, based on where I've seen other people report similar problems.

    Can you pare your code down to a minimal (don't just post the whole program!), but complete, stand-alone example that we can run for ourselves which demonstrates the problem? That would allow us to answer definitively (because we can run your code, see it work incorrectly, then fix it, run it again, and see it work correctly), plus there's a very strong chance that you'll find the answer yourself in the process of trying to create the minimal example program.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (7)
As of 2024-03-28 08:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found