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

Greetings!! I'm setting up a database for users who can register and then log in to allow them to change various information corresponding to the database which is a flat text file (.db).

Example: 1|Michael Brown|24 XXX Street, London, UK|423-3429|Male|34|MrX|Secret (ID, Full Name, Address, Tel.#, Gender, Age, User name, Password)

Right now, I only know how to alter information *all* at once. What if a user would want to change only his password? Is there a way for him to change only that without having to include everything else? I have tried to do this but always ends up erasing everything except for the password. I've tried all means but getting nowhere!

Here's what I'm asking for...

I will offer an HTML form page called 'change_password.html' which is available only if a user has already logged in. There will be four fields: User Name: <field> Old Password: <field> New Password: <field>

The last <field> being hidden containing the ID#.

In my current script,

###
my (%rec) = &get_record ($in{'ID'});
###

is called to get all the information according the ID#. Each bit is signified by i.e. $rec{'ID'}, $rec{'Address'} etc. Before any changes occur, the User Name must match $rec{'Username'} and the Password must match $rec{'Password'}. Any success that I've had so far is when all fields are filled up. Otherwise, all is erased except for the information provided. Here's a piece of script that does all this (which I didn't write):
$found = 0; # Makes sure the record is in the database. open (DB, "<record.db") if ($db_use_flock) { flock(DB, 1); } LINE: while (<DB>) { (/^#/) and ($output .= $_ and next LINE); (/^\s*$/) and next LINE; chomp; @data = &split_decode($_); if ($data[$db_key_pos] eq $in{$db_key}) { # $db_key_pos re +fers to ID# in the database I think $output .= &join_encode(%in); $found = 1; } else { $output .= "$_\n"; # else print regular line. } } close DB; if ($found) { open (DB, ">record.db") if ($db_use_flock) { flock(DB, 2) } print DB $output; close DB; &site_html_modify_success; } else { &site_html_modify_failure; } } sub get_record { my ($key, $found, @data, $field); $key = shift; $found = 0; open (DB, "<record.db") if ($db_use_flock) { flock(DB, 1); } LINE: while (<DB>) { (/^#/) and next LINE; (/^\s*$/) and next LINE; chomp; @data = &split_decode($_); if ($data[$db_key_pos] eq $key) { $found = 1; %rec = &array_to_hash (0, @data); last LINE; } } close DB; $found ? (return %rec) : (return undef); } sub join_encode { my %hash = @_; my ($tmp, $col, $output); foreach $col (@db_cols) { $tmp = $hash{$col}; $tmp =~ s/^\s+//g; # Trim leading blanks... $tmp =~ s/\s+$//g; # Trim trailing blanks... $tmp =~ s/\Q$db_delim\E/~~/og; # Change delimeter to ~~ symbo +l. $tmp =~ s/\n/``/g; # Change newline to `` symbol. $tmp =~ s/\r//g; # Remove Windows linefeed char +acter. $output .= $tmp . $db_delim; # Build Output. } chop $output; # remove extra delimeter. $output .= "\n"; # add linefeed char. return $output; } sub split_decode { my ($input) = shift; my (@array) = split (/\Q$db_delim\E/o, $input, $#db_cols+1); foreach (@array) { s/~~/$db_delim/g; # Retrieve Delimiter.. s/``/\n/g; # Change '' back to newlines.. } return @array; }

Please help me out with a script that could handle changing the password and nothing more without sacrificing the other bits of information! I would greatly appreciate it! Thank you in advance. If you would like more code I would gladly provide it. :-) Cheers!

Replies are listed 'Best First'.
Re: Help with database management
by trs80 (Priest) on Feb 19, 2002 at 07:20 UTC
    This doesn't solve your problem, but might help or trigger someone elses memory. It appears you are running DBMan code or a derivative thereof. Check out this link for some possible insight is you haven't already.
Re: Help with database management
by princepawn (Parson) on Feb 20, 2002 at 05:14 UTC
    Spend some time learning DBD::AnyData, it will reduce your personally required effort greatly.
Re: Help with database management
by Ryszard (Priest) on Feb 20, 2002 at 04:13 UTC
    You mention that a user has to be logged in to change their password, why not use their session key to look up the user_id in your .db file?

    If I were to change the "hidden" value I could change someone elses password. Using the extra layer of abstraction (sess_id) makes this take substantially more difficult.

    I have never used the DBI for text files, however there is a csv driver that looks like it would do exactly what youre after. It would mean a bit of work, but you'd be able to update only the fields you want to.

    There is also the advantage of making your app more portable, and flexible. For example if one day you're able to use an RBDMS there shouldnt be too much you'll need to change in your code.

Re: Help with database management
by Xanatax (Scribe) on Feb 20, 2002 at 04:50 UTC
    I'm doing the same thing myself, but strictly with file reads and prints, no DBI anywhere, which looks quite alot like what you have.

    My system reads the entire passwd file into @passwd, the splits it into $line and @new_passwd (all lines minus the user we want to change). I parse the whole line into individual variables, then rebuild it with the new password and append it to @new_passwd. Then the file is rebuild and swapped into the place of the original...

    this looks something like:

    ##### #read passwd into @pwfile #### foreach (@pwfile) { if (/^$old_userid:.*/) { $line = $_; }else{ push(@new_pwfile, $_); } } ($userid, $passwd, $uid, $gid, $gcos, $name, $home, $shell) = split(': +', $line); $new_line = join(':', $login, $new_passwd, $uid, $gid, $gcos, $home, $ +shell); push(@new_pwfile, $new_line); ##### #write @new_pwfile to file, swap into place #####
Re: Help with database management
by drewboy (Sexton) on Feb 20, 2002 at 19:17 UTC
    Greetings! I appreciate y'all for your help! Xanatax, would I be able to use your code for my predicament? I'm not a big Perl/scripting expert. I kind of understand what you wrote, but I'm not sure how I can apply it to solve my problem. Can you tell me how to get the db file into an array? So I think from then on I can get things started. Thanks again!!
      yes, absolutely, use the code if it is useful.

      code to read file:

      # deal with absence of pwfile. unless ( -e $passwd ) { # PANIC, quit, etc. die("No passwd file found"); } # open file handle for read open(PASSWD, $passwd) or die("Cannot open passwd file for read."); # push each entry into an array while (<PASSWD>) { # remove the trailing \n chomp $_; # add line to array push (@pwfile, $_); } #close the file handle. close(PASSWD);


      then all your data is stored in @pwfile.