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

Hello again monks! With regards to my last problem, I some how solved it....it kind of has a bug vbut as long as those witty end-users read before they do (yeah right) it should be fine! Anyway a new day dawns a new problem...... This one is to do with our good friend GREP. The code is as follows......
#!C:\strawberry\perl\bin\perl.exe use dbi; $usernameentered = "user89"; $passwordentered = "password12"; $dbh = DBI->connect('dbi:mysql:Database','username','password') or die "Connection Error: $DBI::errstr\n"; $sql = "select * from usertable"; $sth = $dbh->prepare($sql); $sth->execute or die "SQL Error: $DBI::errstr\n"; while (@row = $sth->fetchrow_array) { @username= grep /$usernameentered/, @row; print "@username\n"; @password= grep /$passwordentered/, @row; print "@password\n"; if (@username !=$usernameentered) { print "incorrect username entered @username\n"; } if (@password !=$passwordentered) { print "incorrect password entered @password\n"; } }
Now as you may or may not be able to tell this aims to match the output from the database (in the @row) with the input from $usernameentered and $passwordentered.....and yes it kind of works......when run it returns user89 password12 but then it says......... incorrect username entered user89 incorrect password entered password12 These arent incorrect, they match just fine with whats in the database and the corresponding password. So whats gone wrong now masters, if only I could go a day without running into such errors.......it would be dreamy! OK I WANT THE PASSWORD ENTERED AND USERNAME ENTERED TO DISPLAY LIKE THEY ARE! HOWEVER I WANT TO GET IT SO THE INCORRECT.....BITS DONT DISPLAY AS I DONT THINK THEY SHOULD BE THERE.......MY QUESTION BEING HOW CAN I GET RID OF THIS AND SOLVE THIS BUG IN MY CODE? See a question now :-D bogglemaster89 bogglemaster89

Replies are listed 'Best First'.
Re: perl grep help!
by cdarke (Prior) on Mar 09, 2010 at 16:38 UTC
    if (@username !=$usernameentered)

    The array @username will be used in scalar context, so will return the number of items in the array.
    If you did use a scalar instead of an array then the != is incorrect, use ne for testing text.

    You must indent your loops and if statements, otherwise a kitten will die.
Re: perl grep help!
by Svante (Sexton) on Mar 09, 2010 at 16:43 UTC

    Have you ever heard of indenting your code?

    Anyway, the first problem is the !=, which does a numeric comparison; you most likely want to do a string comparison with ne. The second problem is that you are obviously trying to compare an array (which has a @ sigil) with a scalar value (which has a $ sigil). That cannot work.

    Edit: Regarding your edit of the question: Could you try to write sentences? Concise and clear language makes you a better programmer. It also helps others understand what you want to say. They can then, in turn, better help you with your problems.

Re: perl grep help!
by jrsimmon (Hermit) on Mar 09, 2010 at 17:09 UTC

    Let's ignore for a moment the strange use of "select *" when what you really want is two specific columns and the seemingly unnecessary usage of grep...

    In that world, you could do something along the lines of:

    #!C:\strawberry\perl\bin\perl.exe use dbi; use strict; use warnings; my $usernameentered = "user89"; my $passwordentered = "password12"; my $dbh = DBI->connect('dbi:mysql:Database','username','password') or die "Connection Error: $DBI::errstr\n"; my $sql = "select * from usertable"; my $sth = $dbh->prepare($sql); $sth->execute or die "SQL Error: $DBI::errstr\n"; while (my @row = $sth->fetchrow_array) { my @username= grep /$usernameentered/, @row; print "@username\n"; my @password= grep /$passwordentered/, @row; print "@password\n"; #if (@username !=$usernameentered) if ($username[0] ne $usernameentered)#??which index?? { print "incorrect username entered **$username[0]**\n"; } #if (@password !=$passwordentered) if ($password[0] ne $passwordentered)#??which index?? { print "incorrect password entered $password[0]**\n"; } }

    Now, back in the real world, why not just let the database do the work for you?

    #!C:\strawberry\perl\bin\perl.exe use dbi; use strict; use warnings; my $usernameentered = "user89"; my $passwordentered = "password12"; my $dbh = DBI->connect('dbi:mysql:Database','username','password') or die "Connection Error: $DBI::errstr\n"; my $sql = "select user from usertable where user = ? and pwd = ?"; my $sth = $dbh->prepare($sql) or die "SQL Error: $DBI::errstr\n"; $sth->execute($usernameentered, $passwordentered) or die "SQL Error: $DBI::errstr\n"; while (my @row = $sth->fetchrow_array) { #do whatever you want with this user }

    The last thing that jumps out is that you are evidently storing pwds in the database in clear text. That's a no-no, unless you really don't care about the passwords, in which case why use them in the first place? But, perhaps this is not your decision. If it is, you should use one of the many one-way hash modules on cpan to create a hash of the password and then store THAT, rather than storing the password itself.

      hi with the 'let the database work for you' example....how would I get it so users define the username and password as its meant to be a login type script? also im ignoring the login issues i.e. access to passwords till the end. Thanks for your help so far! bogglemaster89
        How would I get it so users define the username and password as its meant to be a login type script?

        You ask for user input, whether reading from the STDIN, taking command-line arguments, or reading a file with login credentials.

        You'll have to request their input, presumably via STDIN. You'll also want to look at Term::ReadKey so that their passwords aren't printed to the screen when typed.
Re: perl grep help!
by Illuminatus (Curate) on Mar 09, 2010 at 16:26 UTC
    I did not spy a question-mark in your post. What is your question? Do you only want to match the exact username and password? Because your code would also match 'user899', 'newuser89', etc. You may want /^$usernameentered$/ if this is the case. It is left as an exercise for the user to modify this if possible whitespace could be present...
Re: perl grep help!
by pemungkah (Priest) on Mar 09, 2010 at 23:15 UTC
    As a security consideration ... you're telling me too much when you specifically say "invalid username" or "invalid password".

    If you say "invalid username", then someone can keep throwing usernames with don't-care passwords at the site until they hit a valid one. Then they can start guessing passwords, knowing that they already have a username.

    If you use email addresses for usernames, it gets even worse: you have made social engineering of the target user simpler, as the bad person simply needs to try to finagle a known email address into giving away their password (or being phished).

    If you just say "invalid user ID or password", then you've given the "I can't log you in because you don't have both of these right" information, but you've not allowed random probing to transmit any information, even if by chance one of the two is right.

Re: perl grep help!
by bogglemaster89 (Novice) on Mar 09, 2010 at 16:57 UTC
    ok ive added eq instead on =! but I dont know how to get grep to search through my array and match passwords and usernames together......does anybody know?
      @username = grep /^$usernameentered$/, @row;

      Will give you a list of all the columns containing only $usernameentered (note the ^ and $).
      unless (@username) { print "incorrect username entered @username\n"; }
      Perhaps the best solution would be to replace the wildcard in the query with a named list, starting with username and password. Then, you could avoid grep altogether and just match the array elements directly. Or, you could keep the wildcard and fetchrow_hashref, and use the column names to find the info you need.
Re: perl grep help!
by bogglemaster89 (Novice) on Mar 09, 2010 at 16:36 UTC
    Hi, I want to match the username and password with the ones entered by the end user exactly. If it doesnt exist in the database EXACTLY i want it to say '
    if (@username !=$usernameentered) { print "incorrect username entered @username\n"; }
    OR/OR BOTH
    if (@password !=$passwordentered) { print "incorrect password entered @password\n"; }
A reply falls below the community's threshold of quality. You may see it by logging in.