#!/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.") }