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

hi monks, i started learning perl not to long ago, and IMHO id say im doing pretty good, learning at a good rate, but unfortunately im not creative enough to just make up programs to write to practice, so im forced to try to make any task that i, or anyone in my house does, a perl script

anyway, my wife owes her dad some money, and she asked me to load MS Word on a computer so she could keep track of the balance, the amount she just paid him, and have a paper copy. Of course the first thing i did was go and download mysql and install DBI, now this is my first time trying to write anything accessing a database, mysql or otherwise, so if you see errors other than what im asking about, please point them out, like i said this is purely for learning reasons, i know alot of things (like mysql and digest_md5) are not really necessary for what im doing, but im trying to get myself familiar with anything i can

so i have a simple HTML page that just has username and password field and a submit button, from there it comes to the code below which is where im having the problem. when i leave a field blank (either one) it does what it should, when i put an invalid username it does what it should, but when i put a valid username, and invalid password it gives me the invalid username error error message, in the error log it says
[Fri Aug 16 21:49:25 2002] [error] [client 12 +7.0.0.1] [Fri Aug 16 21:49:25 2002] amysloan.cgi: Data +base handle destroyed without explicit disconnect., referer: http://l +ocalhost/cgi-bin/amysloan.cgi [Fri Aug 16 21:49:31 2002] [error] [client 12 +7.0.0.1] [Fri Aug 16 21:49:31 2002] amysloan.cgi: Use +of uninitialized value in string ne at C:/Program Files/Apache Group/ +Apache2/cgi-bin/amysloan.cgi line 32., referer: http://localhost/cgi- +bin/amysloan.cgi
i dont know for sure if that helps or not, i was thinking that the uninitialized error might mean something about the problem im having, now if i put in the correct username and password, it prints the loan amount, just like i want it to, the only time i have a problem is if i put a valid username and invalid password..well here's my code:
#!/Perl/bin/perl -w use Digest::MD5 qw/md5_base64/; use CGI::Carp qw/fatalsToBrowser/; use CGI qw/:standard/; use DBI; use strict; print "Content-type:text/html\n\n"; my %info; my $driver = "mysql"; my $database = "amy"; my $dsn = "DBI:$driver:database=$database;host=localhost"; my $dbh = DBI->connect($dsn) or die "Couldnt connect: $DBI::errstr\n"; my $username = param('username'); my $password = md5_base64(param('password')) if param('password'); if(!$username){ relogin("Enter your username"); }elsif(!$password){ relogin("Enter your password"); } my $sth = $dbh->prepare("SELECT * FROM info WHERE pword='$password'"); $sth->execute() or die "Couldnt do it: $!\n"; while(my $ref = $sth->fetchrow_hashref){ %info = %{$ref}; } $sth->finish(); $dbh->disconnect(); if($username ne $info{'uname'}){ relogin("Invalid Username"); } if($password ne $info{'pword'}){ relogin("Invalid Password"); } print $info{'loan'}; sub relogin{ my $msg = shift; print <<HtmlCode; <html> <head> <title>Login</title> </head> <body> <center> <form action="/cgi-bin/amysloan.cgi" method="post"> <table border="0"> <tr> <td colspan="2"><center>$msg</center></td> </tr> <tr> <td>Login:</td> <td><input name="username" size="10" value="$username"></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password" size="10"></td> </tr> <tr> <td colspan="2"><center><input type="submit" value="login"></center> +</td> </tr> </table> </form> </center> </body> </html> HtmlCode exit; }

Replies are listed 'Best First'.
Re: Accessing information pulled from mysql
by grep (Monsignor) on Aug 17, 2002 at 05:16 UTC
    if(!$username){ relogin("Enter your username"); }elsif(!$password){ relogin("Enter your password"); }

    This says if I have a username go ahead don't look at the next condition

    I really don't know what I was smoking

    You still want

    if (!$username or !$password) { relogin('Username/Password pair not valid'); }

    It stops you from giving too much information to someone who is trying to break in (eg. Ok I have the username right now just work on the password)

    another hint

    my $sth = $dbh->prepare("SELECT * FROM info WHERE pword='$password'"); $sth->execute() or die "Couldnt do it: $!\n"

    This will fail if the MD5'd password has a ' in it. Just imagine what that SQL will look like when the $password is expanded. You can use placeholders to get around this

    my $sth = $dbh->prepare('SELECT * FROM info WHERE pword=?'); $sth->execute($password) or die "Couldnt do it: $!\n"

    DBI will properly escape any characters that need to be escaped



    grep
    Just me, the boy and these two monks, no questions asked.
      Thanks for the suggestions, grep, when i type a valid username, and leave the password blank, it is giving me the correct message "Enter your password" so it is looking at the next condition, i did make the change to the prepare statement though, but actually im pretty sure my problem is in how im assigning the return values to the hash %info because when i type in a valid username and an invalid password, it still gives me the 'invalid username' error even though its a good username, if i type in the correct username and correct password, i get the loan amount printed on the page, which is also what its suppose to do. Any other ideas?

      Thanks for the help

        One other hint is: always specify your field names in your SELECT statments. It helps tracking down problems like this down (eg. you know for certain that the column name is spelled correctly in your code, or your statement would fail) also it prevents MySQL from pulling extra information you do not need

        Also please mark the line your error is coming from - I miscounted lines (my browser doesn't make it easy - where an editor does) and was looking at the wrong code :(. It just helps us help you :).



        grep
        Mynd you, mønk bites Kan be pretti nasti...