#!/usr/bin/perl # Name: db_manager.cgi # Version: 5.0 # Last Modified: 01-31-97 # # 02-03-98 (RVB): Change dir path where perl is from #!/usr/local/bin/perl to #!/usr/bin/perl # 05-04-98 (WHB): changed title of displayed HTML page to use $db_title variable # + added code to require csee-lib.pl # 05-08-98 (RVB): Have two copies of the same elsif (except for the ".x",) # in the Perform Management Functions code area. # This is do we can use an image as a button as well as the browser made button # 05-12-98 (RVB): Change so the words "Database Manager" are not in every title # of html pages. Around line 526 # # Copyright Information: This application was written by Selena Sol # (selena@eff.org, http://www.eff.org/~erict) 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. # ####################################################################### # The script begins by telling the Perl interpreter that # it should continuously flush its buffer so that text # from this script is sent directly to the Web Browser. # We do this to streamline debugging and make sure that # the script operates with the flow we want it to. $| = 1; ####################################################################### # Send out the http Header # ####################################################################### # Next, the script sends out the http header so that we # can debug more easily and so that the browser won't time # the script out if it take too long to process. print "Content-type: text/html\n\n"; ####################################################################### # Read and Parse Form Data # ####################################################################### # Then, the script loads some supporting files # using the subroutine, require_supporting_libraries # documented at the end of this script. cgi-lib.pl is # used to read and parse form data. auth-lib.pl is used to # authenticate users of the database management system. # db-lib.pl is used to search through the database for # matches to the users search criteria. &require_supporting_libraries (__FILE__, __LINE__, "./Library/cgi-lib.pl", "./Library/auth-lib.pl", "./Library/db-lib.pl", "../cgi-bin/csee-lib.pl" ); # Now that cgi-lib.pl has been loaded, we can take # advantage of its subroutines. In particular, we will use # the ReadParse to read the incoming form data. However, # the subroutine is sent "form_data" as a parameter so # that the associative array of form keys/values comes # back with a descriptive name rather than just %in. # # In a nutshell, if we have two input fields on our HTML # form such as the follwoing: # # # # # Then the ReadParse routine will create an associative # array like: # # %form_data = ("id_number", "1", # "setup_file", "data.setup"); # # Throught this script, we will be able to access those # dynamically assigned values when we need them as we # would for an associtive array which was hard coded into # the setup file. We access elemetns in an associative # array using key notation. For example, to assign the # value of "setup_file" to $sf, we'll use: # # $sf = $form_data{'setup_file'}. # # In other words, $sf = "data.setup"; &ReadParse(*form_data); ####################################################################### # Load Supporting Files # ####################################################################### # Once it has read the incoming form data, the script # will be able to determine which setup file it should # use to process the incoming form data. # # Perhaps a bit of explanation is in order. # # Whenever you run this application, you MUST pass to it # the name of the setup file which it will use to process # the management request. # # This variable will provide the name of the file which # this script will use to define all of the customizable # aspects of its operation. For example, the setup file # defines what is contained in the database and which # fields should be displayed to the user. # # The reason for this is that this one script can handle # an infinite amount of databases. # # Each database has a corresponding setup file which defines # how the script performs. The logic (and programming) # remains the same for all db's. All that changes are # the variables and subroutines in the setup files. This # makes it very easy for you to quickly generate diverse # databases with the one backend. # # The script first takes the value of "setup_file" # coming in from the form (which cgi-lib.pl has already # parsed into the %form_data associative array) and # assigns it to the variable $setup_file. # # So how do you get this information to the script? # # There are two ways to do that. Firstly, you can encode # the information into the URL if you are executing this # script directly from a hyperlink. # # For example, you might use the following hyperlink to # direct the script to access address_book.setup: # # http://www.you.com/cgi/db_manager.cgi?setup_file=address_book.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'}; &require_supporting_libraries (__FILE__, __LINE__, "./Setup_files/$setup_file"); ####################################################################### # Authenticate User # ####################################################################### # Next the script must make sure that if the admin has # instructed it to authenticate all users through the # setup file variable $should_i_authenticate, that it # provides a level of authentication. Authentication is # handled by the authentication subroutine which is # documented later in this script. if ($should_i_authenticate eq "yes") { &authentication; } ####################################################################### # Perform Management Functions # ####################################################################### # After the user has been authenticated (if necessary), it # is time for the script to perform any or all of the # management functions. # # There are 5 general functions that this script must # provide. The script must be able to 1) add a new item # to the database, 2) modify an item in the database, # 3) delete an item in the database, 4) provide the user # with a view of the database and finally 5) present # the user with a frontpage to give the user the previous # four options. # # These five general functions are broken down into # several other steps each. For example, the general step # of modifying an item in the database can be broken down # into three sub-steps. 1) The user must choose to # "Modify an Item" from a submit button on the frontpage # 2) they must be taken to a screen on which they can # enter search criteria so that the script can dynamically # generate a list of matches from which they can then # choose a specific item to modify and 3) they user must # be able to choose an item from that list, describe the # changes she wants made and then submit the changes to # the database. # # When all is said and done, there are 11 general and # sub-functions that make up the main body of logic of # this application. We will go over each as they appear # in the code below. # # The logic is broken down into a series of "if" tests. # # Specifically, the script checks the values of incoming # administrative form variables (mainly supplied from # the SUBMIT buttons on dynamically generated HTML forms) # and will perform its operations depending on whether # those administrative variables have values associated # with them or not. # # The basic format for such an "if" test follows the # syntax: # # if (the value of some submit button ne "") # { # process that type of request; # exit; # } # # For example, consider the first case in which the # customer has clicked on the "Add an Item" submit # button denoted with the NAME value of # "add_item_button". # # if ($form_data{'add_item_button'} ne "") # { # &generic_header("Add an Item to the Database Form"); # &generic_form_header; # &add_form_header; # &add_modify_data_entry_form; # &add_form_footer; # &generic_form_footer; # exit; # } # # Because the submit button will have some value # like "Add this new item", when the script reaches # this statement block, it will answer true to the test. # # Since the customer can only click on one submit button # at a time, we can be assured that only one operation # will answer true. # # The beauty of using the not equal (ne) test is that # regardless of what the submit button actually says # (it might say "Add a weiner dog to the chopping block") # the if test will still be satisfied if they have clicked # the button, since whatever the VALUE is, it will # certainly not be equal to "nothing". Of course, this # assumes that you do not rename the NAME argument of the # submit buttons. If you do so, you must harmonize the # variable you use on the input forms, with the variables # used here to test. # # Similarly, if you wish to have graphical submit buttons # instead of the ugly default buttons supplied by the # browser, you will have to modify the if tests so that # they follow the standard image map test: # # if ($form_data{'some_button.x'} ne "") # { # do something # } # # where the HTML code looks like the following: # # # # Thus, if the button actually has an X-dimension value, # it means that the button had been clicked. # # Finally, note that every if test is concluded with an # exit statement. This is because once the script is done # executing the routine specified in the submit button, it # is done with its work and should exit immediately. # # Get used to the idea that this script is "self-referencing". # The application itself contains many mini-routines # which all refer back to the routine community. Every # instance of the script need only execute maybe 1/11th of # the routines in the whole file, but in the lifetime of # the application, most, if not all, routines are # executed. # # Okay, so now let's look at each of the routines which # this applicaiton must execute. # # 1. If the user clicks the "add an item" button on the # frontpage, they must be presented with an HTML form with # input fields for each field in the database which they # have access to define. The user can then fill in the # input fields and submit the info to be added to the # database. # # The generation of this add form is handled by # several subroutines which are all defined in the setup # file. generic_header will print out the basic HTML # header with the passed parameter placed between the #