#!/usr/bin/perl
# Name: db_manager.cgi
# Version: 6.0
# Last Modified: 04-02-98
#
# Copyright Information: This application was written by Selena Sol
# (selena@eff.org, http://www.extropia.com) and Gunther Birznieks
# (birzniek@hlsun.redcross.org) having been inspired by
# countless other Perl authors. Feel free to copy, cite, reference,
# sample, borrow, resell or plagiarize the contents. However, if you
# don't mind, please let me know where it goes so that I can at least
# watch and take part in the development of the memes. Information wants
# to be free, support public domain freware. Donations are appreciated
# and will be spent on further upgrades and other public domain scripts.
#######################################################################
# Flush the Perl Buffer. #
#######################################################################
$| = 1;
#######################################################################
# Send out the http Header #
#######################################################################
print "Content-type: text/html\n\n";
#######################################################################
# Read and Parse Form Data #
#######################################################################
&require_supporting_libraries (__FILE__, __LINE__,
"./Library/cgi-lib.pl",
"./Library/auth-lib.pl",
"./Library/db-lib.pl");
&ReadParse(*form_data);
#######################################################################
# Load Supporting Files #
#######################################################################
# For example, you might use the following hyperlink to
# direct the script to access address_book.setup:
#
# http://www.katsation.com/cgi-bin/db_manager.cgi?setup_file=CT_chimera.setup
#
# You can also send this information as a hidden field in
# an HTML form using something like the following.
#
#
#
# For example, the following code would define a setup
# file called address_book.setup:
#
#
#
# You might also create a select box so that the user can
# choose from a number of databases dynamically:
#
#
#
# All these examples assume you placed the setup files in
# the provided subdirectory called Setup_files.
#
# The script uses the subroutine require_supporting_libraries
# documented later in this script to actually load the
# setup file and all of its configuration options.
$setup_file = $form_data{'setup_file'};
$setup_file =~ /([\w-.]+setup[\w-.]+)/;
$untainted_setup_file = $1;
&require_supporting_libraries (__FILE__, __LINE__,
"./Setup_files/breeders.setup.cgi");
#######################################################################
# Authenticate User #
#######################################################################
if ($should_i_authenticate eq "yes")
{
&authentication;
}
#######################################################################
# Perform Management Functions #
#######################################################################
if ($form_data{'add_item_button'} ne "")
{
&generic_header("Add an Item to the Database");
&generic_form_header;
&add_form_header;
&add_modify_data_entry_form;
&add_form_footer;
&generic_form_footer;
exit;
}
elsif ($form_data{'submit_addition'} ne "")
{
&submit_addition;
exit;
}
elsif ($form_data{'modify_item_button'} ne "")
{
&modify_search_form;
exit;
}
elsif ($form_data{'search_and_display_for_modification_button'} ne "")
{
&search_and_display_for_modification;
exit;
}
elsif ($form_data{'submit_modification_button'} ne "")
{
&submit_modification;
exit;
}
elsif ($form_data{'delete_item_button'} ne "")
{
&delete_search_form;
exit;
}
elsif ($form_data{'search_and_display_for_deletion_button'} ne "")
{
&search_and_display_for_deletion;
exit;
}
elsif ($form_data{'submit_deletion_button'} ne "")
{
&submit_deletion;
exit;
}
elsif ($form_data{'view_database_button'} ne "")
{
&generic_header("Welcome !");
&display_frontpage;
&generic_form_header;
&display_generic_search_form;
&generic_form_footer;
exit;
}
elsif ($form_data{'search_and_display_db_button'} ne "")
{
&search_and_display_db_next;
exit;
}
elsif ($form_data{'search_and_display_db_for_view_next_button'} ne "")
{
&search_and_display_db_next;
exit;
}
else
{
&generic_header("Welcome !");
&display_frontpage;
&generic_form_header;
&display_generic_search_form;
&generic_form_footer;
exit;
}
#######################################################################
# Require Supporting Libraries. #
#######################################################################
sub require_supporting_libraries
{
local ($file, $line, @require_files) = @_;
local ($require_file);
foreach $require_file (@require_files)
{
if (-e "$require_file" && -r "$require_file")
{
require "$require_file";
}
else
{
print "Content-type: text/html\n\n";
print "I am sorry but I was unable to require $require_file at line
$line in $file. Would you please make sure that you have the
path correct and that the permissions are set so that I have
read access? Thank you.";
exit;
}
} # End of foreach $require_file (@require_files)
} # End of sub require_supporting_libraries
#######################################################################
# Perform Authentication #
#######################################################################
sub authentication
{
$session_file = "$form_data{'session_file'}";
$session_file =~ s/\///g;
# Now perform the authentication and gather the returned
# values.
($session_file, $session_username, $session_group,$session_first_name,
$session_last_name, $session_email) =
&GetSessionInfo($session_file, $this_script_url, *form_data);
}
#######################################################################
# Submit an Addition #
#######################################################################
#added this routine to get count.. cross fingers....lol...
sub get_count2 {
open (COUNTER_FILE, "<$location_of_counter_file") ||
&file_open_error ("$location_of_counter_file", "Submit Addition",
__FILE__, __LINE__);
while ()
{
$current_counter3 = $_;
}
close (COUNTER_FILE);
$current_counter3;
}
sub get_count {
open (COUNTER_FILE, "<$location_of_counter_file") ||
&file_open_error ("$location_of_counter_file", "Submit Addition",
__FILE__, __LINE__);
while ()
{
$current_counter = $_;
}
close (COUNTER_FILE);
$current_counter++;
$new_counter = $current_counter;
return $new_counter;
}
sub submit_addition
{
&get_file_lock("$location_of_lock_file");
open (COUNTER_FILE, "<$location_of_counter_file") ||
&file_open_error ("$location_of_counter_file", "Submit Addition",
__FILE__, __LINE__);
while ()
{
$current_counter = $_;
}
close (COUNTER_FILE);
$current_counter++;
$new_counter = $current_counter;
open (COUNTER_FILE, ">$location_of_counter_file") ||
&file_open_error ("$location_of_counter_file", "Submit Addition",
__FILE__, __LINE__);
print COUNTER_FILE "$new_counter";
close (COUNTER_FILE);
$when_modified = &get_date;
# With that, we are ready to open the database for
# appending (>>).
open (DATABASE, ">>$data_file_path") ||
&file_open_error ("$data_file_path", "Submit Addition",
__FILE__, __LINE__);
# Now, for every field that the user could define on the
# add form, we will append the value they entered to a
# variable called $new_row using the append operator (.=).
# Notice that we will add a pipe (|) delimiter between
# every field in a database row.
foreach $field (@db_user_definable_field_order)
{
$form_data{$field} =~ s/\n/ /g;
$form_data{$field} =~s/(\s)\s*/\1/g;
$new_row .= "$form_data{$field}\|";
}
# Then, we will tag on the administrative fields of
# when the addition was made,who made the addition, what
# group are they in and the unique database id number.
$new_row .= "$when_modified\|$session_username\|$session_group\|$new_counter\n";
print DATABASE $new_row;
close (DATABASE);
# Once the database has been appended to, we will note
# what we did in the log file, release the lock file so
# that others can make their own additions and let the
# user know that their item was added successfully.
open (LOG_FILE, ">>$location_of_log_file") || &file_open_error
("$location_of_log_file", "Submit Addition",
__FILE__, __LINE__);
print LOG_FILE "ADD\|$new_row";
close (LOG_FILE);
&release_file_lock("$location_of_lock_file");
&successful_addition_message;
}
#######################################################################
# Submit a Modification #
#######################################################################
# The user might also be submitting a modification to the
# database.
sub submit_modification
{
# The first thing we must do is make sure that they
# actually chose a database item to modify. If they did
# not, we better warn them and stop processing.
if ($form_data{'item_to_modify'} eq "")
{
&no_item_submitted_for_modification;
exit;
}
# If they did choose an item, we need to find that items
# so that we can modify it. To do so, we'll open the data
# file and read through it a line at a time. We'll then
# split up each line into its fields and compare the id
# number given to us by the suer against the id number of
# the current line. If it is not the same, we will add
# the entire line to a variable called $new_data (By the
# end of this, $new_data is going to hold the entire
# contents of our database).
open (DATABASE, "<$data_file_path") || &file_open_error
("$data_file_path", "Modify item", __FILE__, __LINE__);
while ()
{
$line = $_;
chop $line;
@fields = split (/\|/, $line);
if ($fields[$index_of_db_id_number] ne $form_data{'item_to_modify'})
{
$new_data .= "$line\n";
}
else
{
$old_row = "$line";
for ($i=0; $i <= (@db_user_definable_field_order-1); $i++)
{
$index = $db_user_definable_field_order[$i];
if ($form_data{$index} ne "")
{
$new_row .= "$form_data{$db_user_definable_field_order[$i]}\|";
}
else
{
$new_row .= "$fields[$i]\|";
}
} # End of for ($i=1; $i <= @db_user_definable_field_order; $i++);
$new_data .= "$new_row";
$when_modified = &get_date;
$who_modified = $session_username;
if ($session_group eq "admin")
{
$group = $fields[$index_of_group_who_modified];
$who_modified = $fields[$index_of_who_modified];
}
else
{
$group = $session_group
}
if ((($session_username eq $fields[$index_of_who_modified]) ||
(($session_group eq $fields[$index_of_group_who_modified]) &&
($session_group ne "user"))) ||
($session_group eq "admin") || ($should_i_authenticate ne "yes"))
{
$security_satisfied = "yes";
}
$new_data .= "$when_modified|$who_modified|$group|$fields[$index_of_db_id_number]\n";
$new_row .= "$when_modified|$who_modified|$group|$fields[$index_of_db_id_number]";
} # End of else
} # End of while ()
close (DATABASE);
if ($security_satisfied eq "yes")
{
&get_file_lock("$location_of_lock_file");
open (DATABASE, ">$data_file_path") || &file_open_error
("$data_file_path", "Modify Item", __FILE__, __LINE__);
print DATABASE "$new_data";
close (DATABASE);
# We will also add the modification information to the log
# file.
open (LOG_FILE, ">>$location_of_log_file") || &file_open_error
("$location_of_log_file", "Modify Item", __FILE__, __LINE__);
print LOG_FILE "MODIFY_NEW\|$new_row|MODIFIED BY $session_username\n";
print LOG_FILE "MODIFY_OLD\|$old_row\n";
close (LOG_FILE);
&release_file_lock("$location_of_lock_file");
&successful_modification_message;
}
else
{
&unsuccessful_modification_message;
}
}
#######################################################################
# Submit a Deletion #
#######################################################################
sub submit_deletion
{
if ($form_data{'item_to_delete'} eq "")
{
&no_item_submitted_for_modification;
exit;
}
@items_to_delete = &SplitParam($form_data{'item_to_delete'});
open (DATABASE, "<$data_file_path") || &file_open_error
("$data_file_path", "Delete Item", __FILE__, __LINE__);
while ()
{
$line = $_;
chop $line;
@fields = split (/\|/, $line);
$already_deleted = "no";
foreach $item (@items_to_delete)
{
if ($fields[$index_of_db_id_number] eq $item)
{
$deleted_row .= "$line";
$already_deleted = "yes";
if ((($session_username eq $fields[$index_of_who_modified]) ||
(($session_group eq $fields[$index_of_group_who_modified]) &&
($session_group ne "user"))) ||
($session_group eq "admin") || ($should_i_authenticate ne "yes"))
{
$security_satisfied = "yes";
}
}
} # End of foreach $item (@items_to_delete)
if ($already_deleted ne "yes")
{
$new_data .= "$line\n";
}
} # End of while ()
close (DATABASE);
if ($security_satisfied eq "yes")
{
&get_file_lock("$location_of_lock_file");
open (DATABASE, ">$data_file_path") || &file_open_error
("$data_file_path", "Delet Item", __FILE__, __LINE__);
print DATABASE "$new_data";
close (DATABASE);
$who_deleted = $session_username;
# And as before, we will append the info to the log file.
open (LOG_FILE, ">>$location_of_log_file") || &file_open_error
("$location_of_log_file", "Delete Item", __FILE__, __LINE__);
print LOG_FILE "DELETE\|$deleted_row\|DELETED BY $who_deleted\n";
close (LOG_FILE);
&release_file_lock("$location_of_lock_file");
&successful_deletion_message
}
else
{
&unsuccessful_modification_message;
}
}
#######################################################################
# Search and Display the Database #
#######################################################################
sub search_and_display_db
{
&generic_header("Search & Display");
if ($form_data{'sort_by'} ne "")
{
$index_of_field_to_be_sorted_by = $form_data{'sort_by'};
}
($total_row_count) = &submit_query(*database_rows);
foreach $row (@database_rows)
{
@row = split (/\|/, $row);
$sortable_field = $row[$index_of_field_to_be_sorted_by];
unshift (@row, $sortable_field);
$new_row = join ("\|", @row);
push (@new_rows, $new_row);
}
@database_rows = ();
@sorted_rows = sort (@new_rows);
foreach $sorted_row (@sorted_rows)
{
@row = split (/\|/, $sorted_row);
$sorted_field = shift (@row);
$old_but_sorted_row = join ("\|", @row);
push (@database_rows, $old_but_sorted_row);
}
if ($total_row_count < 1)
{
&no_hits_message;
exit;
}
$hits_seen = $form_data{'new_hits_seen'};
for ($i = 1;$i <= $hits_seen;$i++)
{
$seen_row = shift (@database_rows);
}
$length_of_database_rows = @database_rows;
for ($i = $length_of_database_rows-1;$i >= $max_rows_returned;$i--)
{
$extra_row = pop (@database_rows);
}
$new_hits_seen = $hits_seen + @database_rows;
&search_results_body;
&search_results_footer;
}
#######################################################################
# Search and Display Next Hits #
#######################################################################
sub search_and_display_db_next
{
&generic_header("Search & Display");
if ($form_data{'sort_by'} ne "")
{
$index_of_field_to_be_sorted_by = $form_data{'sort_by'};
}
&generic_form_header;
($total_row_count) = &submit_query(*database_rows);
foreach $row (@database_rows)
{
@row = split (/\|/, $row);
$sortable_field = $row[$index_of_field_to_be_sorted_by];
unshift (@row, $sortable_field);
$new_row = join ("\|", @row);
push (@new_rows, $new_row);
}
@database_rows = ();
# Then we are ready to sort...guess what the result is:
#
# Birznieks|Gunther|Birznieks|birzniek@hlsun.redcross.org
# Sol|Selena|Sol|selena@eff.org
# Tachibana|Eric|Tachibana|erict@eff.org
@sorted_rows = sort (@new_rows);
foreach $sorted_row (@sorted_rows)
{
@row = split (/\|/, $sorted_row);
$sorted_field = shift (@row);
$old_but_sorted_row = join ("\|", @row);
push (@database_rows, $old_but_sorted_row);
}
if ($total_row_count < 1)
{
&no_hits_message;
exit;
}
$hits_seen = $form_data{'new_hits_seen'};
for ($i = 1;$i <= $hits_seen;$i++)
{
$seen_row = shift (@database_rows);
}
$length_of_database_rows = @database_rows;
for ($i = $length_of_database_rows-1;$i >= $max_rows_returned;$i--)
{
$extra_row = pop (@database_rows);
}
$new_hits_seen = $hits_seen + @database_rows;
&search_results_body;
&search_results_footer;
}
sub search_and_display_db_modify
{
if ($form_data{'sort_by'} ne "")
{
$index_of_field_to_be_sorted_by = $form_data{'sort_by'};
}
($total_row_count) = &submit_query(*database_rows);
foreach $row (@database_rows)
{
@row = split (/\|/, $row);
$sortable_field = $row[$index_of_field_to_be_sorted_by];
unshift (@row, $sortable_field);
$new_row = join ("\|", @row);
push (@new_rows, $new_row);
}
@database_rows = ();
@sorted_rows = sort (@new_rows);
foreach $sorted_row (@sorted_rows)
{
@row = split (/\|/, $sorted_row);
$sorted_field = shift (@row);
$old_but_sorted_row = join ("\|", @row);
push (@database_rows, $old_but_sorted_row);
}
if ($total_row_count < 1)
{
&no_hits_message;
exit;
}
$hits_seen = $form_data{'new_hits_seen'};
for ($i = 1;$i <= $hits_seen;$i++)
{
$seen_row = shift (@database_rows);
}
$length_of_database_rows = @database_rows;
for ($i = $length_of_database_rows-1;$i >= $max_rows_returned;$i--)
{
$extra_row = pop (@database_rows);
}
$new_hits_seen = $hits_seen + @database_rows;
#added option to view data the way it should be viewed for modification
&search_modify_results_body;
}
#################################################################
# get_date Subroutine #
#################################################################
sub get_date
{
# The subroutine begins by defining some local working
# variables
local ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst,$date);
local (@days, @months);
@days = ('Sunday','Monday','Tuesday','Wednesday','Thursday',
'Friday','Saturday');
@months = ('January','February','March','April','May','June','July',
'August','September','October','November','December');
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
if ($hour < 10)
{
$hour = "0$hour";
}
if ($min < 10)
{
$min = "0$min";
}
if ($sec < 10)
{ $sec = "0$sec";
}
$mon++;
#$year = ($current_century-1) . "$year";
if ($year < 99)
{
$year += 2000;
}
else
{
$year += 1900;
}
$date = "$mon/$mday/$year at $hour\:$min\:$sec";
return $date;
}
sub get_short_date {
local ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst,$date);
local (@days, @months);
@days = ('Sunday','Monday','Tuesday','Wednesday','Thursday',
'Friday','Saturday');
@months = ('January','February','March','April','May','June','July',
'August','September','October','November','December');
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
if ($hour < 10)
{
$hour = "0$hour";
}
if ($min < 10)
{
$min = "0$min";
}
if ($sec < 10)
{ $sec = "0$sec";
}
$mon++;
#$year = ($current_century-1) . "$year";
if ($year < 99)
{
$year += 2000;
}
else
{
$year += 1900;
}
$date = "$mon/$mday/$year at $hour\:$min\:$sec";
$short_date = "$mon/$mday/$year";
return $short_date;
}
#######################################################################
# get_file_lock #
#######################################################################
sub get_file_lock
{
local ($lock_file) = @_;
local ($endtime);
$endtime = 20;
$endtime = time + $endtime;
while (-e $lock_file && time < $endtime)
{
sleep(1);
}
open(LOCK_FILE, ">$lock_file") || &file_open_error ("$lock_file",
"Lock File Routine",
__FILE__, __LINE__);
# flock(LOCK_FILE, 2); # 2 exclusively locks the file
}
#######################################################################
# release_file_lock #
#######################################################################
sub release_file_lock
{
local ($lock_file) = @_;
# flock(LOCK_FILE, 8); # 8 unlocks the file
close(LOCK_FILE);
unlink($lock_file);
}
#######################################################################
# file_open_error Subroutine #
#######################################################################
sub file_open_error
{
local ($bad_file, $script_section, $this_file, $line_number) = @_;
print "Content-type: text/html\n\n";
&CgiDie ("I am sorry, but I was not able to access $bad_file in the
$script_section routine of $this_file at line number $line_number.
Would you please make sure the path is correctly defined in
web_store.setup and that the permissions are correct.")
}