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

making loop in perl script

by rakie (Initiate)
on Jan 23, 2004 at 20:57 UTC ( #323687=perlquestion: print w/replies, xml ) Need Help??
rakie has asked for the wisdom of the Perl Monks concerning the following question:

Hi you y'all,

I have question about looping in a perl program, please check this code. This script is much longer, but I've shrunk it to the problem part. I have a sub called random_password wich I call with:

$password = &random_password();
After that the password is inserted into the array that goes just fine, but my problem is that I don't want to use the same password (stored in the array) for all the users I insert into the database, so I think a loop or something like that must be created to generate diffrent passwords. Who can help me with this? Thanks in advance,

Avanti check me AT:

# Sub to create a random password sub random_password { my($length, $vowels, $consonants, $alt, $s, $newchar, $i); ($length) = @_; if ($length eq "" or $length < 3) { $length = 15; # make it at least 15 chars long. } $vowels = "0000000"; $consonants = "aaaaaaaaaaaa"; srand(time() ^ ($$ + ($$ << 234)) ); $alt = int(rand(933)) - 4; $s = ""; $newchar = ""; foreach $i (0..$length-1) { if ($alt == 1) { $newchar = substr($vowels,rand(length($vowels)),1); } else { $newchar = substr($consonants, rand(length($consonants)) +,1); } $s .= $newchar; $alt = !$alt; } return $s; } sub dienice { my($msg) = @_; print "<h2>Error</h2>\n"; print $msg; exit; } # query to insert the password in the database $password = &random_password(); $sql = qq{ INSERT INTO login (login, password) VALUES ($c[1], '$passwo +rd')}; $sth = $dbh->prepare($sql); $sth->execute();

Replies are listed 'Best First'.
Re: making loop in perl script
by PERLscienceman (Curate) on Jan 23, 2004 at 22:59 UTC
    Greetings Fellow Monk!

    I see in your script that you are trying to generate for your users random passwords.
    I would like to recommend to you this module: Crypt::GeneratePassword.
    I have found it to be quite useful. Here is a snippet of code to demo it:
    #!/usr/bin/perl -w use strict; my $minlen=6; my $maxlen=10; use Crypt::GeneratePassword qw(word chars); my $word = chars($minlen,$maxlen); print "$word\n";
Re: making loop in perl script
by talexb (Canon) on Jan 23, 2004 at 21:22 UTC

    It looks like you've posted some code that makes up passwords -- I haven't tried it -- and shown roughly how you call it. Your code fragment isn't complete -- I am guessing you have a list of users and want to create unique passwords for each user, but I can't tell.

    Maybe you want to do something like this

    my @users = qw/Albert Bob Charlie/; foreach my $thisUser ( @users ) { my $password = makePassword(); my $sql = "INSERT INTO login (login, password) VALUES (?,?)"; my $sth = $dbh->prepare($sql); $sth->execute($thisUser, $password); }

    Alex / talexb / Toronto

    Life is short: get busy!

Re: making loop in perl script
by flyingmoose (Priest) on Jan 23, 2004 at 21:41 UTC

    First off, your code is pretty darn long, highly inefficient, ugly, and can be shaped up a bit. But that's not why you are here. But I want you to understand -- when debugging bad code, it's harder to find the problem. Hence this is why (so far) no one has figured out what your problem is....we're lazy. Give us clean code, and we'll jump to the challenge!

    My eyes immediately look to the placement of srand -- seed random number generator. This needs to be called at the top of the application, not inside the random_number function. Reseeding the random number generator between each call isn't good. In fact, it's a very bad idea for security reasons. The time xor'ing with the PID is something I haven't seen before, I assume you think there is a chance of a random number generator being started at the same time and you don't want them to coincide. I find this very odd for a database program -- so most likely this code was copied and pasted from somewhere. If it were me, I'd rewrite this whole thing from scratch. It's a maintainance problem and better password routines exist...much better routines that actually make sense to read.

    Just guessing here, but I bet you are feeding the same value to srand every time. Check it out.

Re: making loop in perl script
by Anonymous Monk on Jan 23, 2004 at 23:45 UTC
    Hi there,

    There are lots of usefull modules around for generating secure passwords, so you might consider searching CPAN for them.

    Also, you ask for a way to generate different passwords every time you call the function, well, this is perl's default! If you use rand() in perl it'll initialize a seed in such a way that it's pretty impossible to get the same seed next time. And it's hard to guess what seed will be given also. So leave the sranding to perl and you'll be fine here.
Re: making loop in perl script
by graff (Chancellor) on Jan 24, 2004 at 18:06 UTC
    Others have commented on the problems with your approach and the way you have coded it. But I gather that your main concern is to make sure that each new person is guaranteed to get a unique password, and you're worried that your current code might not accomplish that.

    You are using an SQL-ish database to store names and passwords, so it should be the case that you can (and should) apply a "UNIQUE" constraint on both the name and the password fields -- this way, it you try to insert a row that uses a value already present in the table, the database will reject it, and the insert statement will fail.

    This would also mean that you need to work out how to check and handle the return status of the statement execution. Sometimes, the default behavior with DBI is to "die" when something goes wrong, but the way to alter and control this is explained in the DBI man page. (Yes, that man page is long and complicated, but if you're going to use DBI, you need to need to read the man page.)

    Of course, you could also take the time to check for the existence of a given user name in the database before you try to insert it -- e.g. (using the table and column names that you seem to have in your database):

    my $sql = "select login from login where login like ?"; # (I would have used different names for table and column) my $sth = $dbh->prepare( $sql ); my $newname = "whatever"; $sth->execute( $newname.'%' ); my $likenames = $sth->fetchall_arrayref; # update: remembered that fetchall_arrayref returns AoA, # so added map to get actual field values into grep # (also remembered to include the "execute" step above) if ( grep /^\Q$newname\E$/, map { $$_[0] } @$likenames ) { $newname .= "00"; while ( grep /^\Q$newname\E$/, map { $$_[0] } @$likenames ) { $newname++; } }
    After you generate some password string (preferably using the CPAN module suggested above), you can use this sort of logic to check that it's unique and tweak it if necessary.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://323687]
Approved by dws
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (7)
As of 2017-01-18 13:18 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (161 votes). Check out past polls.