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

Here is the snippit I wrote:
sub verify { open FILE, "$user_file" || die "Can't open user's login files: $! +"; while(<FILE>) { my ($user,$pass)=split(/\|/); foreach $user($user) { if ($user eq $q->param('ueq &encrypt_pass) { &good; } else { &bad; } } } close FILE; }
Basically given that user|encrypted_pass| for each user will be on a seperate line in the file $user_file, I want to verify that the username/password is correct. In the first form of my script, the user inputs their username and password, after pushing "Submit", this piece of code is run. However, this only reads the first line, not every line for some reason.

I have this same piece in another program (same function) that does not use the CGI.pm modual, but it works there. I can't figure out what's wrong with it. Anyone have any ideas? Keep in mind, I'm still learning the modual, so I might just be missing something obvious here.

Replies are listed 'Best First'.
Re: Reading from multi line file -> CGI.pm
by fruiture (Curate) on Jan 02, 2003 at 22:16 UTC

    I don't mean to offend you, usually i'd not have answered at all, but: You haven't thought before you wrote that code, apart from the fact that it shows lack of basic knowledge about Perl 5.

    But it may help you if i'm constructive. Let's strip syntax errors and nonsense:

    sub verify { # open FILE, "$user_file" || die "Can't open user's login files: $!" +; # the previous line doesn't obey operator precedence rules # see `perldoc perlop` # as well as it uses "" for nothing.. open FILE, $user_file or die "... $!"; while(<FILE>) { my ($user,$pass)=split(/\|/); # foreach $user($user) { # the previous line does exactly nothing but aliasing $user # to $user, that's really quite useless # See `perldoc perlsyn` # if ($user eq $q->param('ueq &encrypt_pass) { # hmm? i try to guess this might be if( $user eq $q->param('u') ){ # &good; # you're calling a sub and i'm sure you don't know what the # & means and does. See `perldoc perlsub` # Apart from that this routine will sometime return and # you want to go on reading the file then? # } else { &bad; # same problem + you will call 'bad' for every name in the # file that doesn't equal the submitted username. # Is that your intention? } } } close FILE; }

    After all, Perl is only a procedural language and it will do what you tell it to and Perl won't do much more and nothing less. You have to know which steps have to be taken to achieve what you want and that's what you tell Perl. If you want it differently, use Prolog.

    Try to formulate the procedure, use pseudo-code:

    for each line in the file split up into name and password if the name is the needed name verify the password if it is correct end the loop successfully otherwise cry for help or simply die of error ... if the name doesn't match go to the next line

    This directly translates to Perl:

    while( <FILE> ){ # = for each line of the file chomp; # (remove trailing newline) my ($name,$pass) = split /\|/; # = split up into name and password if( $name eq $wanted_name ){ # = if the name is the needed name if( $pass eq $submitted_passord ){ # = verify the password # = if it is correct last; # = end the loop successfully } else { # = otherwise die "bastard $name gave me wrong password!\n" # = cry for help or simply die of error ... } } # = if the name doesn't match # go to the next line }

    But before you copy that code and try to put it into your script now, be self-ciritcal. You need to learn the basics of Perl and some procedural programming. Then you should write a lot of small programs to grok concepts of clean design, because your code has also problems with more abstract aspects of programming: you don't use function parameters, you don't localize handles/variables, you try to do everything on globals.

    CGI is, although a lot of dumb AOL-Kiddies think differently, NOT the most trivial programming environment and you're (sorry) far from "working" on that.

    Try Learning Perl if the manpages don't get you started, but try something before you go on writing "CGI programs" that will never work correctly.

    Thanks.

    --
    http://fruiture.de
      Ok first, thank you for replying with your input.

      Second, I am not some dumb 5 year old that can't write a simple "Hello, world!" program, so DON'T treat me like that. I know what a subroutine is, otherwise I wouldn't be using one, let alone about a dozen in total that I have. I said I was new to the CGI.pm modual, not Perl itself. Granted I am not some all knowing guru, but I don't care right now -- I am learning and having fun. I do not make software for any companies, but for myself for simple distribution, so don't give me any of that "you suck, don't know a thing, need to learn how to use the 'print' command, blah blah" garbage.

      "I don't mean to offend you, usually i'd not have answered at all, but: You haven't thought before you wrote that code, apart from the fact that it shows lack of basic knowledge about Perl 5."

      Do me a favour next time, DON'T answer to my question. I'd rather have someone help me get moving then someone come in and start flaming me for asking a simple question. And I havn't thought before posting?? That has got to be the lamest thing I have ever read on this site! Why the heck would I be posting, if not for help?? It appears that YOU are the one who did not THINK before posting your reply. And as I stated, I am no Perl guru, however I do know fair bit about Perl.

      So do me a favour, next time you decide to post, how's about just stopping and thinking as to if your post will be HELPFUL or just a waist of time.

      As to the rest of you who posted, thanks for the help.
        Granted that fruiture's post could be viewed as a bit condescending, but it did make some valid points. The most pertinent one I can immediately think of is using a '&' in front of a sub call. There is a difference between using it and not using it which you may not be aware of and fruiture pointed this out (quite correctly, IMO, given the level of Perl knowledge demonstrated in the rest of the code) and where to find the relevant documentation. A laudable post it would seem to me. As for your own post, if I can go OT for a second or two:
        • "modual" should be "module"
        • "waist of time" should be "waste of time"
        • "make software" is probably better written as "write software"
        • "I do know fair bit about Perl" is probably less true than "I know enough Perl to be dangerous"
        The Monestary is free, and the people here devote their time for free, so don't get shirty when someone takes a lot of time and trouble to go into great detail about where you've gone wrong and how to get more information on how to get out of trouble. fruiture++, FireBird34--.

        rdfield

        Also, there was a bit of a typo on my behalf:
        ($user eq $q->param('ueq &encrypt_pass)
        Should have been:
        ($user eq $q->param('username') && $pass eq &encrypt_pass)
Re: Reading from multi line file -> CGI.pm
by virtualsue (Vicar) on Jan 02, 2003 at 21:49 UTC
    Your problem here is not due to CGI.pm. while does not set $_. Plus I think you're forgetting to get rid of the newline. Try this instead:
    while (chomp($_ = <FILE>)) { do stuff; }
    Update - I'm crazy. while does set $_, but I customarily chomp in the fashion above and I guess I forgot why. :-(
    if ($user eq $q->param('ueq &encrypt_pass) {

    The above code shouldn't compile. The foreach after it is also completely unnecessary (no sense looping over 1 value). Maybe it ought to look something like:

    my $user = $q->param('username'); my $pass = $q->param('password'); verify($user, $pass) or die "No user or password incorrect"; sub verify { my ($ck_user, $ck_pass) = @_; open FH, $user_file" or die "Can't open file, $!"; while (chomp($_=<FH>)) { my ($user, $pass) = split '\|'; if ($user eq $ck_user) { if ($pass ne crypt(ck_pass)) { return 0; } else { return 1; } } } return 0; }
    Adjust the return values to suit the logic of your program. I assume that at a minimum you might like to know if the user exists in the user list and whether or not their password is correct.

      Have you noticed that skips the last line of files that don't end with $\? Be very careful about the return value of chomp.

        I confess to knowing about that particular pitfall and ignoring it. I am a much lazier programmer in Perl than I am in any other language (other than sh/ksh).