Here is the db.cfg (part 1) file content:
(Code before sub signup sub routine)
DB.CGI File Content
-------------------------------------------
# -- ! -- /usr/local/bin/perl -- disabled, shouldn't need this for Windows NT
#
# ----------------------
# DBMan
# ----------------------
# Database Administrator
#
# File: db.cgi
# Description: This is the main program file and contains all the functionality
# of the database manager.
# Author: Alex Krohn
# Email: alex@gossamer-threads.com
# Web: http://www.gossamer-threads.com/
# Version: 2.04
#
# COPYRIGHT NOTICE:
#
# Copyright 1997
Gossamer Threads Inc. All Rights Reserved.
#
# This program is being distributed as shareware. It may be used and
# modified free of charge for personal, academic, government or non-profit
# use, so long as this copyright notice and the header above remain intact.
# Any commercial use should be registered. Please also send me an email,
# and let me know where you are using this script. By using this program
# you agree to indemnify
Gossamer Threads Inc. from any liability.
#
# Selling the code for this program without prior written consent is
# expressly forbidden. Obtain permission before redistributing this
# program over the Internet or in any other medium. In all cases
# copyright and header must remain intact.
#
# Please check the README file for full details on registration.
# =====================================================================
# If you run into problems, set $db_script_path to the full path
# to your directory.
$db_script_path = ".";
# Load the form information and set the config file and userid.
local(%in) = &parse_form;
$in{'db'} ? ($db_setup = $in{'db'}) : ($db_setup = 'default');
$in{'uid'} ? ($db_uid = $in{'uid'}): ($db_uid = '');
# Required Librariers
# --------------------------------------------------------
# Make sure we are using perl 5.003, load the config file, and load the auth file.
eval {
unshift (@INC, $db_script_path);
require 5.003; # We need at least Perl 5.003
unless ($db_setup =~ /^[A-Za-z0-9]+$/) { die "Invalid config file name: $db_setup"; }
require "$db_setup.cfg"; # Database Definition File
require "auth.pl"; # Authorization Routines
};
if ($@) { &cgierr ("Error loading required libraries.\nCheck that they exist, permissions are set correctly and that they compile.\nReason: $@"); }
# If we are using benchmarking, then we start a timer and stop it around &main. Then we print the difference.
if ($db_benchmark) { $t0 = new Benchmark; }
eval { &main; }; # Trap any fatal errors so the program hopefully
if ($@) { &cgierr("fatal error: $@"); } # never produces that nasty 500 server error page.
# Stop the timer and print.
if ($db_benchmark) { $t1 = new Benchmark; print "<h6>Processing Time: " . timestr(timediff($t1, $t0)) . "</h6>"; }
# Display debugging information if requested.
&cgierr("Debug Information") if ($db_debug);
exit; # There are only two exit calls in the script, here and in in &cgierr.
sub main {
# --------------------------------------------------------
my ($status, $uid);
local($per_add, $per_view, $per_mod, $per_del, $per_admin);
$|++; # Flush Output Right Away
&auth_cleanup unless ($auth_no_authentication); # Remove old session files.
($status, $uid, $per_view, $per_add, $per_del, $per_mod, $per_admin)
= &auth_check_password; # Authenticate User, get permissions and userid.
if ($status eq "ok") {
# Set the script link URL with db and user info for links. Use $db_script_url for forms.
$db_script_link_url = "$db_script_url?db=$db_setup&uid=$db_uid";
if ($uid eq "default") { $db_userid = $uid; }
else { ($db_userid) = $db_uid =~ /([A-Za-z0-9]+)\.\d+/; }
# Main Menu. Check to see what the user requested, then, if he has permission for that
# request, do it. Otherwise send the user off to an unauthorized request page.
if ($in{'add_form'}) { if ($per_add) { &html_add_form; } else { &html_unauth; } }
elsif ($in{'add_record'}) { if ($per_add) { &add_record; } else { &html_unauth; } }
elsif ($in{'view_search'}) { if ($per_view) { &html_view_search; } else { &html_unauth; } }
elsif ($in{'view_records'}) { if ($per_view) { &view_records; } else { &html_unauth; } }
elsif ($in{'delete_search'}) { if ($per_del) { &html_delete_search; } else { &html_unauth; } }
elsif ($in{'delete_form'}) { if ($per_del) { &html_delete_form; } else { &html_unauth; } }
elsif ($in{'delete_records'}) { if ($per_del) { &delete_records; } else { &html_unauth; } }
elsif ($in{'modify_search'}) { if ($per_mod) { &html_modify_search; } else { &html_unauth; } }
elsif ($in{'modify_form'}) { if ($per_mod) { &html_modify_form; } else { &html_unauth; } }
elsif ($in{'modify_form_record'}) { if ($per_mod) { &html_modify_form_record; } else { &html_unauth; } }
elsif ($in{'modify_record'}) { if ($per_mod) { &modify_record; } else { &html_unauth; } }
elsif ($in{'admin_display'}) { if ($per_admin) { &admin_display; } else { &html_unauth; } }
elsif ($in{'logoff'}) { &auth_logging('logged off') if ($auth_logging);
$auth_logoff ? (print "Location: $auth_logoff\n\n") : (print "Location: $db_script_url\n\n"); }
elsif ((keys(%in) <= 2) | |
($in{'login'})) { &html_home; }
else { &html_unkown_action; }
}
# If we allow users to signup, and they want to, go to the signup form.
elsif ($auth_signup and $in{'signup_form'}) {
&html_signup_form;
}
elsif ($auth_signup and $in{'signup'}) {
&signup;
}
# Auth Check Password has determined that the user has not logged in, so let's send
# him to the login screen.
elsif ($status eq "no login") {
&html_login_form;
}
# Auth Check Password had an error trying to authenticate the user. Probably there was
# an invalid user/password or the user file has expired. Let's go to an error page and
# ask the user to re log on.
else {
&html_login_failure($status);
}
}
sub add_record {
# --------------------------------------------------------
# Adds a record to the database. First, validate_record is called
# to make sure the record is ok to add. If it is, then the record is
# encoded and added to the database and the user is sent to
# html_add_success, otherwise the user is sent to html_add_failure with
# an error message explaining why. The counter file is also updated to the
# next number.
my ($output, $status, $counter);
# Set the userid to the logged in user.
($auth_user_field >= 0) and ($in{$db_cols[$auth_user_field]} = $db_userid);
# First we validate the record to make sure the addition is ok.
$status = &validate_record;
# We keep checking for the next available key, or until we've tried 50 times
# after which we give up.
while ($status eq "duplicate key error" and $db_key_track) {
return "duplicate key error" if ($counter++ > 50);
$in{$db_key}++;
$status = &validate_record;
}
if ($status eq "ok") {
open (DB, ">>$db_file_name") or &cgierr("error in add_record. unable to open database: $db_file_name.\nReason: $!");
if ($db_use_flock) {
flock(DB, 2) or &cgierr("unable to get exclusive lock on $db_file_name.\nReason: $!");
}
print DB &join_encode(%in);
close DB; # automatically removes file lock
if ($db_key_track) {
open (ID, ">$db_id_file_name") or &cgierr("error in get_defaults. unable to open id file: $db_id_file_name.\nReason: $!");
if ($db_use_flock) {
flock(ID, 2) or &cgierr("unable to get exclusive lock on $db_id_file_name.\nReason: $!");
}
print ID $in{$db_key}; # update counter.
close ID; # automatically removes file lock
}
&auth_logging("added record: $in{$db_key}") if ($auth_logging);
&html_add_success;
}
else {
&html_add_failure($status);
}
}
sub delete_records {
# --------------------------------------------------------
# Deletes a single or multiple records. First the routine goes thrrough
# the form input and makes sure there are some records to delete. It then goes
# through the database deleting each entry and marking it deleted. If there
# are any keys not deleted, an error message will be returned saying which keys
# were not found and not deleted, otherwise the user will go to the success page.
my ($key, %delete_list, $rec_to_delete, @lines, $line, @data, $errstr, $succstr, $output, $restricted);
$rec_to_delete = 0;
foreach $key (keys %in) { # Build a hash of keys to delete.
if ($in{$key} eq "delete") {
$delete_list{$key} = 1;
$rec_to_delete = 1;
}
}
if (!$rec_to_delete) {
&html_delete_failure("no records specified.");
return;
}
open (DB, "<$db_file_name") or &cgierr("error in delete_records. unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>;
close DB;
($restricted = 1) if ($auth_modify_own and !$per_admin);
LINE: foreach $line (@lines) {
if ($line =~ /^$/) { next LINE; }
if ($line =~ /^#/) { $output .= $line; next LINE; }
chomp ($line);
@data = &split_decode($line);
($output .= "$line\n" and next LINE) if ($restricted and ($db_userid ne $data[$auth_user_field]));
$delete_list{$data[$db_key_pos]} ? # if this id is one we want to delete
($delete_list{$data[$db_key_pos]} = 0) : # then mark it deleted and don't print it to the new database.
($output .= $line . "\n"); # otherwise print it.
}
foreach $key (keys %delete_list) {
$delete_list{$key} ? # Check to see if any items weren't deleted
($errstr .= "$key,") : # that should have been.
($succstr .= "$key,"); # For logging, we'll remember the one's we deleted.
}
chop($succstr); # Remove trailing delimeter
chop($errstr); # Remove trailing delimeter
open (DB, ">$db_file_name") or &cgierr("error in delete_records. unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) {
flock(DB, 2) or &cgierr("unable to get exclusive lock on $db_file_name.\nReason: $!");
}
print DB $output;
close DB; # automatically removes file lock
&auth_logging("deleted records: $succstr") if ($auth_logging);
$errstr ? # Do we have an error?
&html_delete_failure($errstr) : # If so, then let's report go to the failure page,
&html_delete_success($succstr); # else, everything went fine.
}
sub modify_record {
# --------------------------------------------------------
# This routine does the actual modification of a record. It expects
# to find in %in a record that is already in the database, and will
# rewrite the database with the new entry. First it checks to make
# sure that the modified record is ok with validate record.
# It then goes through the database looking for the right record to
# modify, if found, it prints out the modified record, and returns
# the user to a success page. Otherwise the user is returned to an error
# page with a reason why.
my ($status, $line, @lines, @data, $output, $found, $restricted);
$status = &validate_record; # Check to make sure the modifications are ok!
if ($status eq "ok") {
open (DB, "<$db_file_name") or &cgierr("error in modify_records. unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
@lines = <DB>; # Slurp the database into @lines..
close DB;
($restricted = 1) if ($auth_modify_own and !$per_admin);
$found = 0; # Make sure the record is in here!
LINE: foreach $line (@lines) {
if ($line =~ /^$/) { next LINE; } # Skip and Remove blank lines
if ($line =~ /^#/) { $output .= $line; next LINE; } # Comment Line
chomp ($line);
@data = &split_decode($line);
($output .= "$line\n" and next LINE) if ($restricted and ($db_userid ne $data[$auth_user_field]));
if ($data[$db_key_pos] eq $in{$db_key}) {
# If we have userid's and this is not an admin, then we force the record to keep it's own
# userid.
if ($auth_user_field >= 0 and (!$per_admin or !$in{$db_cols[$auth_user_field]})) {
$in{$db_cols[$auth_user_field]} = $data[$auth_user_field];
}
$output .= &join_encode(%in);
$found = 1;
}
else {
$output .= $line . "\n"; # else print regular line.
}
}
if ($found) {
open (DB, ">$db_file_name") or &cgierr("error in modify_records. unable to open db file: $db_file_name.\nReason: $!");
if ($db_use_flock) {
flock(DB, 2) or &cgierr("unable to get exclusive lock on $db_file_name.\nReason: $!");
}
print DB $output;
close DB; # automatically removes file lock
&auth_logging("modified record: $in{$db_key}") if ($auth_logging);
&html_modify_success;
}
else {
&html_modify_failure("$in{$db_key} (can't find requested record)");
}
}
else {
&html_modify_failure($status); # Validation Error
}
}
sub view_records {
# --------------------------------------------------------
# This is called when a user is searching the database for
# viewing. All the work is done in query() and the routines just
# checks to see if the search was successful or not and returns
# the user to the appropriate page.
my ($status, @hits) = &query("view");
if ($status eq "ok") {
&html_view_success(@hits);
}
else {
&html_view_failure($status);
}
}
sub query {
# --------------------------------------------------------
# First let's get a list of database fields we want to search on and
# store it in @search_fields
my ($i, $column, @search_fields, @search_gt_fields, @search_lt_fields, $maxhits, $numhits, $nh,
$field, @regexp, $line, @values, $key_match, @hits, @sortedhits, $next_url, $next_hit, $prev_hit,
$first, $last, $upper, $lower, $left, $right, $restricted);
local (%sortby);
# First thing we do is find out what we are searching for. We build a list of fields
# we want to search on in @search_fields.
if ($in{'keyword'}) { # If this is a keyword search, we are searching the same
$i = 0; # thing in all fields. Make sure "match any" option is
$in{'ma'} = "on"; # on, otherwise this will almost always fail.
foreach $column (@db_cols) {
if (($db_sort{$column} eq 'date') or &date_to_unix($in{'keyword'})) { $i++; next; }
if ($i == $auth_user_field) { $i++; next; }
push (@search_fields, $i); # Search every column
$in{$column} = $in{'keyword'}; # Fill %in with keyword we are looking for.
$i++;
}
}
else { # Otherwise this is a regular search, and we only want records
$i = 0; # that match everything the user specified for.
foreach $column (@db_cols) {
if ($in{$column} =~ /^\>(.+)$/) { ($db_sort{$column} eq 'date') and (&date_to_unix($1) or return "Invalid date format: '$1'");
push (@search_gt_fields, $i); $in{"$column-gt"} = $1; $i++; next; }
if ($in{$column} =~ /^\<(.+)$/) { ($db_sort{$column} eq 'date') and (&date_to_unix($1) or return "Invalid date format: '$1'");
push (@search_lt_fields, $i); $in{"$column-lt"} = $1; $i++; next; }
if ($in{$column} !~ /^\s*$/) { ($db_sort{$column} eq 'date') and (&date_to_unix($in{$column}) or return "Invalid date format: '$in{$column}'");
push(@search_fields, $i); $i++; next; }
if ($in{"$column-gt"} !~ /^\s*$/) { ($db_sort{$column} eq 'date') and (&date_to_unix($in{"$column-gt"}) or return "Invalid date format: '$in{$column}'");
push(@search_gt_fields, $i); }
if ($in{"$column-lt"} !~ /^\s*$/) { ($db_sort{$column} eq 'date') and (&date_to_unix($in{"$column-lt"}) or return "Invalid date format: '$in{$column}'");
push(@search_lt_fields, $i); }
$i++;
}
}
# If we don't have anything to search on, let's complain.
if (!@search_fields and !@search_gt_fields and !@search_lt_fields) {
return "no search terms specified";
}
# Define the maximum number of hits we will allow, and the next hit counter.
$in{'mh'} ? ($maxhits = $in{'mh'}) : ($maxhits = $db_max_hits);
$in{'nh'} ? ($nh = $in{'nh'}) : ($nh = 1);
$numhits = 0;
# Let's set restricted to 1 if the user can only view/mod their own and
# this isn't an admin.
($restricted = 1) if ($_[0] eq "view" and $auth_view_own and !$per_admin);
($restricted = 1) if ($_[0] eq "mod" and $auth_modify_own and !$per_admin);
# Now let's build up all the regexpressions we will use. This saves the program
# from having to recompile the same regular expression every time.
foreach $field (@search_fields) {
my $tmpreg = "$in{$db_cols[$field]}";
(!$in{'re'}) and ($tmpreg = "\Q$tmpreg\E");
($in{'ww'}) and ($tmpreg = "\\b$tmpreg\\b");
(!$in{'cs'}) and ($tmpreg = "(?i)$tmpreg");
($in{$db_cols[$field]} eq "*") and ($tmpreg = ".*"); # A "*" matches anything.
$regexp_func[$field] = eval "sub { m/$tmpreg/o }";
$regexp_bold[$field] = $tmpreg;
}
# Now we go through the database and do the actual searching.
# First figure out which records we want:
$first = ($maxhits * ($nh - 1));
$last = $first + $maxhits - 1;
open (DB, "<$db_file_name") or &cgierr("error in search. unable to open database: $db_file_name.\nReason: $!");
if ($db_use_flock) { flock(DB, 1); }
LINE: while (<DB> ) {
(/^#/) and next LINE; # Skip comment Lines.
(/^\s*$/) and next LINE; # Skip blank lines.
$line = $_; chomp ($line); # Remove trailing new line.
@values = &split_decode($line);
# If we are only allowed to view/mod our own record, then let's check here.
next LINE if ($restricted and ($db_userid ne $values[$auth_user_field]));
# Normal searches.
$key_match = 0;
foreach $field (@search_fields) {
$_ = $values[$field]; # Reg function works on $_.
$in{'ma'} ?
($key_match = ($key_match or &{$regexp_func[$field]})) :
(&{$regexp_func[$field]} or next LINE);
}
# Greater then searches.
foreach $field (@search_gt_fields) {
$term = $in{"$db_cols[$field]-gt"};
if ($db_sort{$db_cols[$field]} eq "date") {
$in{'ma'} ?
($key_match = ($key_match or (&date_to_unix($values[$field])) > &date_to_unix($term))) :
(&date_to_unix($values[$field]) > (&date_to_unix($term)) or next LINE);
}
elsif ($db_sort{$db_cols[$field]} eq 'alpha') {
$in{'ma'} ?
($key_match = ($key_match or ($values[$field] > $term))) :
((lc($values[$field]) gt lc($term)) or next LINE);
}
else {;
$in{'ma'} ?
($key_match = ($key_match or ($values[$field] > $term))) :
(($values[$field] > $term) or next LINE);
}
}
# Less then searches.
foreach $field (@search_lt_fields) {
$term = $in{"$db_cols[$field]-lt"};
if ($db_sort{$db_cols[$field]} eq "date") {
$in{'ma'} ?
($key_match = ($key_match or (&date_to_unix($values[$field]) < &date_to_unix($term)))) :
(&date_to_unix($values[$field]) < (&date_to_unix($term)) or next LINE);
}
elsif ($db_sort{$db_cols[$field]} eq 'alpha') {
$in{'ma'} ?
($key_match = ($key_match or ($values[$field] < $term))) :
((lc($values[$field]) lt lc($term)) or next LINE);
}
else {
$in{'ma'} ?
($key_match = ($key_match or ($values[$field] < $term))) :
(($values[$field] < $term) or next LINE);
}
}
# Did we find a match? We only add the hit to the @hits array if we need it. We can
# skip it if we are not sorting and it's not in our first < > last range.
if ($key_match | | (!($in{'keyword'}) && !($in{'ma'}))) {
if (exists $in{'sb'}) {
$sortby{(($#hits+1) / ($#db_cols+1))} = $values[$in{'sb'}];
push (@hits, @values);
}
else {
(($numhits >= $first) and ($numhits <= $last)) and push (@hits, @values);
}
$numhits++; # But we always count it!
}
}
close DB;
# Now we've stored all our hits in @hits, and we've got a sorting values stored
# in %sortby indexed by their position in @hits.
$numhits ? ($db_total_hits = $numhits) : ($db_total_hits = 0);
($db_total_hits == 0) and return ("no matching records.");
# Sort the array @hits in order if we are meant to sort.
if (exists $in{'sb'}) { # Sort hits on $in{'sb'} field.
my ($sort_order, $sort_func);
$in{'so'} ? ($sort_order = $in{'so'}) : ($sort_order = "ascend");
$sort_func = "$db_sort{$db_cols[$in{'sb'}]}_$sort_order";
foreach $hit (sort $sort_func (keys %sortby)) {
$first = ($hit * $#db_cols) + $hit; $last = ($hit * $#db_cols) + $#db_cols + $hit;
push (@sortedhits, @hits[$first .. $last]);
}
@hits = @sortedhits;
}
# If we have to many hits, let's build the next toolbar, and return only the hits we want.
if ($numhits > $maxhits) {
# Remove the nh= from the query string.
$next_url = $ENV{'QUERY_STRING'};
$next_url =~ s/\&nh=\d+//;
$next_hit = $nh + 1; $prev_hit = $nh - 1;
# Build the next hits toolbar. It seems really complicated as we have to do
# some number crunching to keep track of where we are on the toolbar, and so
# that the toolbar stays centred.
# First, set how many pages we have on the left and the right.
$left = $nh; $right = int($numhits/$maxhits) - $nh;
# Then work out what page number we can go above and below.
($left > 7) ? ($lower = $left - 7) : ($lower = 1);
($right > 7) ? ($upper = $nh + 7) : ($upper = int($numhits/$maxhits) + 1);
# Finally, adjust those page numbers if we are near an endpoint.
(7 - $nh >= 0) and ($upper = $upper + (8 - $nh));
($nh > ($numhits/$maxhits - 7)) and ($lower = $lower - ($nh - int($numhits/$maxhits - 7) - 1));
$db_next_hits = "";
# Then let's go through the pages and build the HTML.
($nh > 1) and ($db_next_hits .= qq~<a href="$db_script_url?$next_url&nh=$prev_hit">[<<]</a> ~);
for ($i = 1; $i <= int($numhits/$maxhits) + 1; $i++) {
if ($i < $lower) { $db_next_hits .= " ... "; $i = ($lower-1); next; }
if ($i > $upper) { $db_next_hits .= " ... "; last; }
($i == $nh) ?
($db_next_hits .= qq~$i ~) :
($db_next_hits .= qq~<a href="$db_script_url?$next_url&nh=$i">$i</a> ~);
if (($i * $maxhits) >= $numhits) { last; } # Special case if we hit exact.
}
$db_next_hits .= qq~<a href="$db_script_url?$next_url&nh=$next_hit">[>>]</a> ~ unless ($nh == $i);
# Slice the @hits to only return the ones we want, only have to do this if the results are sorted.
if (exists $in{'sb'}) {
$first = ($maxhits * ($nh - 1)) * ($#db_cols+1);
$last = $first + (($#db_cols+1) * $maxhits) - 1;
$last = $#hits if ($last > $#hits);
@hits = @hits[$first .. $last];
}
}
# Bold the results
if ($db_bold and $in{'view_records'}) {
for $i (0 .. (($#hits+1) / ($#db_cols+1)) - 1) {
$offset = $i * ($#db_cols+1);
foreach $field (@search_fields) {
$hits[$field + $offset] =~ s,(<[^>]+> )|($regexp_bold[$field]),defined($1) ? $1 : "<B>$2</B>",ge;
}
}
}
return ("ok", @hits);
}
sub admin_display {
# --------------------------------------------------------
# Let's an admin add/update/remove users from the authorization file.
#
my ($message, @lines, $line);
# Do we have anything to do?
CASE: {
# If we've been passed in new_username, then we are adding a new user. Do
# some basic error checking and then add him into the password file.
$in{'new_username'} and do {
unless ((length($in{'new_username'}) >= 3) and (length($in{'new_username'}) <= 12) and ($in{'new_username'} =~ /^[a-zA-Z0-9]+$/)) {
$message = "Invalid username: $in{'new_username'}. Must only contain letters and numbers and be less then 12 and greater then 3 characters.";
last CASE;
}
unless ((length($in{'password'}) >= 3) and (length($in{'password'}) <= 12)) {
$message = "Invalid password: '$in{'password'}'. Must be less then 12 and greater then 3 characters.";
last CASE;
}
open (PASS, ">>$auth_pw_file") or &cgierr ("unable to open: $auth_pw_file.\nReason: $!");
if ($db_use_flock) {
flock(PASS, 2) or &cgierr("unable to get exclusive lock on $auth_pw_file.\nReason: $!");
}
my @salt_chars = ('A' .. 'Z', 0 .. 9, 'a' .. 'z', '.', '/');
my $salt = join '', @salt_chars[rand 64, rand 64];
my $encrypted = crypt($in{'password'}, $salt);
print PASS "$in{'new_username'}:$encrypted:$in{'per_view'}:$in{'per_add'}:$in{'per_del'}:$in{'per_mod'}:$in{'per_admin'}\n";
close PASS;
$message = "User: $in{'new_username'} created.";
last CASE;
};
# If we've been passed in delete, then we are removing a user. Check
# to make sure a user was selected then try and remove him.
$in{'delete'} and do {
unless ($in{'username'}) {
$message = "No username selected to delete.";
last CASE;
}
open (PASS, "<$auth_pw_file") or &cgierr ("unable to open: $auth_pw_file.\nReason: $!");
if ($db_use_flock) { flock(PASS, 1) }
@lines = <PASS>;
close PASS;
open (PASS, ">$auth_pw_file") or &cgierr ("unable to open: $auth_pw_file.\nReason: $!");
if ($db_use_flock) {
flock(PASS, 2) or &cgierr("unable to get exclusive lock on $auth_pw_file.\nReason: $!");
}
my $found = 0;
foreach $line (@lines) {
($line =~ /^$in{'username'}:/) ?
($found = 1) :
print PASS $line;
}
close PASS;
$found ?
($message = "User: $in{'username'} deleted.") :
($message = "Unable to find userid: $in{'username'} in password file.");
last CASE;
};
# If we have a username, and the admin didn't press inquire, then
# we are updating a user.
($in{'username'} && !$in{'inquire'}) and do {
open (PASS, "<$auth_pw_file") or &cgierr ("unable to open: $auth_pw_file.\nReason: $!");
if ($db_use_flock) { flock(PASS, 1); }
@lines = <PASS>;
close PASS;
open (PASS, ">$auth_pw_file") or &cgierr ("unable to open: $auth_pw_file.\nReason: $!");
if ($db_use_flock) {
flock(PASS, 2) or &cgierr("unable to get exclusive lock on $auth_pw_file.\nReason: $!");
}
my $found = 0;
foreach $line (@lines) {
if ($line =~ /^$in{'username'}:/) {
my $password = (split (/:/, $line))[1];
unless ($password eq $in{'password'}) {
my @salt_chars = ('A' .. 'Z', 0 .. 9, 'a' .. 'z', '.', '/');
my $salt = join '', @salt_chars[rand 64, rand 64];
$password = crypt($in{'password'}, $salt);
}
print PASS "$in{'username'}:$password:$in{'per_view'}:$in{'per_add'}:$in{'per_del'}:$in{'per_mod'}:$in{'per_admin'}\n";
$found = 1;
}
else {
print PASS $line;
}
}
$in{'inquire'} = $in{'username'};
$found ?
($message = "User: $in{'username'} updated.") :
($message = "Unable to find user: '$in{'username'}' in the password file.");
last CASE;
};
};
# Now let's load the list of users.
open (PASS, "<$auth_pw_file") or &cgierr ("unable to open: $auth_pw_file.\nReason: $!");
if ($db_use_flock) { flock(PASS, 1); }
@lines = <PASS>;
close PASS;
# If we are inquiring, let's look for the specified user.
my (@data, $user_list, $perm, $password);
$user_list = qq~<select name="username"><option> </option>~;
LINE: foreach $line (@lines) {
$line =~ /^#/ and next LINE;
$line =~ /^\s*$/ and next LINE;
chomp $line;
@data = split (/:/, $line);
if ($in{'inquire'} and ($in{'username'} eq $data[0])) {
$user_list .= qq~<option value="$data[0]" SELECTED>$data[0]</option>\n~;
$perm = qq|
View <input type=checkbox name="per_view" value="1" |; ($data[2] and $perm .= "CHECKED"); $perm .= qq|>
Add <input type=checkbox name="per_add" value="1" |; ($data[3] and $perm .= "CHECKED"); $perm .= qq|>
Delete <input type=checkbox name="per_del" value="1" |; ($data[4] and $perm .= "CHECKED"); $perm .= qq|>
Modify <input type=checkbox name="per_mod" value="1" |; ($data[5] and $perm .= "CHECKED"); $perm .= qq|>
Admin <input type=checkbox name="per_admin" value="1" |; ($data[6] and $perm .= "CHECKED"); $perm .= qq|>|;
$password = $data[1];
}
else {
$user_list .= qq~<option value="$data[0]">$data[0]</option>\n~;
}
}
$user_list .= "</select>";
# Build the permissions list if we haven't inquired in someone.
if (!$perm) {
$perm = qq|
View <input type=checkbox name="per_view" value="1" |; ($auth_default_perm[0] and $perm .= "CHECKED"); $perm .= qq|>
Add <input type=checkbox name="per_add" value="1" |; ($auth_default_perm[1] and $perm .= "CHECKED"); $perm .= qq|>
Delete <input type=checkbox name="per_del" value="1" |; ($auth_default_perm[2] and $perm .= "CHECKED"); $perm .= qq|>
Modify <input type=checkbox name="per_mod" value="1" |; ($auth_default_perm[3] and $perm .= "CHECKED"); $perm .= qq|>
Admin <input type=checkbox name="per_admin" value="1" |; ($auth_default_perm[4] and $perm .= "CHECKED"); $perm .= qq|>|;
}
&html_admin_display ($message, $user_list, $password, $perm);
}