in reply to Re^4: Premature end of script headers issue
in thread Premature end of script headers issue

Somehow the $sth->execute seems to have gotten skipped.

Change the following

my $sth = $dbh->prepare("SELECT * FROM $users_table WHERE username = ' +$username' AND user_password = '$userpass'"); $sth->execute;
to
my $sth = $dbh->prepare("SELECT * FROM $users_table WHERE username = ? + AND user_password = ?"); $sth->execute($username,$userpass) or die $dbh->errstr;
It is a more secure way of doing things (protects against arbitrary SQL code injection attacks -- has nothing to do with your present problem)

The only reason I can see why your script sometimes runs and sometimes doesn't run is in a combination of inputs which skips the execute code. Are you sure all the if ... then ... else ...-logic is OK?

CountZero

"If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Replies are listed 'Best First'.
Re^6: Premature end of script headers issue
by Anonymous Monk on Jan 10, 2005 at 21:48 UTC
    I was thinking the same thing about the if/else setup. This script was originally created by someone a few years ago and it DID work back then.

    I rewrote the order of the script and I changed the if/else thinking that might be catching (or not catching) if the case may be. Now I'm certain everything is loading in the order it should but it still hangs up when it hits the test print #4.

    The code really isn't that long or complex and I've been working on getting this to work since about 10am this morning. The entire script is posted below incase you or anyone else can come up with any other suggestions.

    Thank you for your help.

    #!/usr/bin/perl use CGI::Carp qw(fatalsToBrowser); use CGI qw(:all); use CGI::Cookie; use DBI; use Digest::MD5 qw(md5_hex); require("../funcs.cgi"); require("../con.cgi"); %cookies = fetch CGI::Cookie; ################## # THEY ARE ALREADY LOGGED IN # SKIP THIS PAGE ################### if (defined($cookies{'user_id'})) { print "Content-type: text/html\n\n"; print "You are already logged in."; print "<script>window.location = 'index.cgi';</script>\n"; exit; } ################## # THE FORM HAS BEEN SUBMITTED # ################### if (param()) { print "Content-type: text/html\n\n"; use CGI::Carp qw(fatalsToBrowser); $username = (param('form_user')); $userpass = (param('form_pass')); $userpass = md5_hex($userpass); #check the database print "test<br>"; my $dbh = DBI->connect("DBI:mysql:$edt_dbase", $mysql_user, $m +ysql_pass) or print DBI->errstr; my $sth = $dbh->prepare("SELECT * FROM $users_table WH +ERE username = '$username' AND user_password = '$userpass'"); $sth->execute; print "test2<br>"; if ($sth->rows < 1) { print "Content-type: text/html\n\n"; print "Login information incorrect."; $dbh->disconnect; print "<script>window.location = 'login.cgi';</script>\n"; exit; } else { print "test3<br>"; while ($data = $sth->fetchrow_hashref or die $sth->errstr) { print "test4<br>"; $u_id = $$data{"user_id"}; my $auth_user = new CGI::Cookie(-name => + 'user_id', -value => + $u_id); my $auth_pass = new CGI::Cookie(-name => + 'user_pass', -value => + $userpass); #$cookieset = $auth_user . ";" . $auth_pass; print "Set-Cookie: $auth_user\n"; print "Set-Cookie: $auth_pass\n"; print "Content-type: text/html\n\n"; print "Welcome " . $username . ", you have successfull +y logged in.\n"; print "$u_id = UID"; print "<script>window.location = 'index.cgi';</script> +\n"; } } $dbh->disconnect; exit; } else { ################## # NOTHING IS HAPPENING SO LET'S # PRINT THE FORM ################### { print "Content-type: text/html\n\n"; print qq~ <table border='1'> <form method="post" action=""> <tr> <td> <b>Username:</b> </td> <td> <input type='text' length='30' name='form_user'> </td> </tr> <tr> <td> <b>Password:</b> </td> <td> <input type='password' length='30' name='form_pass'> </td> </tr> <tr> <td colspan='2'> <input type='submit'> </td> </tr> </form> </table> ~; } } #print "(..)";
      At first glance the logic seems OK to me.

      I do have some trouble with the $sth->rows

      To get the number of records returned of a select statement one should not rely on the rows function. For one it is not guaranteed to work on all databases and for second its use should be restricted to non-select statements.

      From the DBI-docs:

      rows
      $rv = $sth->rows;

      Returns the number of rows affected by the last row affecting command, or -1 if the number of rows is not known or not available.

      Generally, you can only rely on a row count after a non-SELECT execute (for some specific operations like UPDATE and DELETE), or after fetching all the rows of a SELECT statement.

      For SELECT statements, it is generally not possible to know how many rows will be returned except by fetching them all. Some drivers will return the number of rows the application has fetched so far, but others may return -1 until all rows have been fetched. So use of the rows method or $DBI::rows with SELECT statements is not recommended.

      One alternative method to get a row count for a SELECT is to execute a ``SELECT COUNT(*) FROM ...'' SQL statement with the same ``...'' as your query and then fetch the row count from that.

      Running a SELECT count(*) ... will work and is very fast.

      Anyhow, if I understand your code correctly, you only expect one record anyhow (or none if the log-in failed). So why don't you check if the result of the SELECT count(*) ... is 1, in which case you retrieve the data to set the cookies, or in all other cases (no records or mulltiple records) you raise an error.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law