#!/usr/bin/perl # Remember to change the above line if it's different on # your system. ############################################################### # THIS SECTION OF THE SCRIPT CONTAINS VARIABLES THAT YOU # # *MUST* CUSTOMIZE FOR YOUR OWN SITE! # # # # This variable is the *full* URL of the guest book file: # $guest_book_url = "http://YOURSITE.COM/CGI-BIN/guests.html"; # This one tells the script which file to modify; since all # # the files are in the same directory, a simple file name # # will suffice. If you want to put the Guest Book elsewhere, # # you'll need a relative or absolute path: # $guest_book_file = "guests.html"; # This is the name of the current script. You need to define # # it here so that the script can generate a new form that # # refers to $guest_book_script. # $guest_book_script = "guestbk.cgi"; # # ############################################################### # Convert the form input to a usable form, using the # 'ReadParse' subroutine from "cgi-lib.pl": require "cgi-lib.pl"; &ReadParse; # Run the 'CurrentTime' subroutine, which formats the current # date and time and puts them into the $datetime variable: &CurrentTime; # Let them know if they forgot to enter their name or comments. # In English, the first line says, "run the 'Missing' sub- # routine unless the $in{'comments'} variable exists." The # second line says the same thing for the $in{'name'} variable. # If both variables are there, 'Missing' is not called at all. &Missing unless $in{'comments'}; &Missing unless $in{'name'}; # This is the trickiest part of this script; we'll take it one # piece at a time. First, open a new *filehandle* named FILE, # and fill it with the contents of the file named by the # $guest_book_file variable. A filehandle is like a nickname # for a pile of data. It's similar to an ordinary file name, # but it only exists within the program. open (FILE,"$guest_book_file"); # Create an array called @LINES (arrays start with a @ symbol), # and set it equal to FILE. When you dump a filehandle into # an array like this, each element in the array is one complete # *line* of the filehandle. At this point, @LINES now holds # the complete contents of the Guest Book file. @LINES = ; # Close the FILE filehandle. Since you've read all of its # data into the @LINES array, you don't need it anymore. close(FILE); # Open a new filehandle called GUESTBOOK. Rather than read # another file *into* this filehandle, you're going to # redirect everything that comes into GUESTBOOK into the file # named $guest_book_file, replacing the old contents of the # $guest_book_file. This is done by placing a 'greater than' # sign (>) in front of the file name. open (GUESTBOOK,">$guest_book_file"); # Start a 'foreach' loop. A foreach loop says, in English, # "repeat everything within my curly brackets as long as there # continues to be input." In this case, it will go through the # entire @LINES array and stop after it has evaluated the last # line in the array. foreach ( @LINES ) { # Now you're within the 'foreach' loop. If the current # input (one line of the GUESTBOOK file, read as an element # of the @LINES array) contains , execute the # statements between the curly brackets. (The first few lines # of the file will *not* contain , so nothing in # the 'if' statement will take place; the program will skip # to the 'else' down below.) if (//) { # If the program has made it here, inside the 'if' # statement's curly brackets, it must have found the # "begin" marker. It will spit out a new # line, and then the new guest book entry. Because you # are outputting to a filehandle rather than to the # "standard" output, the 'print' statements all begin # with 'print GUESTBOOK' rather than just 'print'. print GUESTBOOK "\n"; print GUESTBOOK "$datetime:
\n"; print GUESTBOOK "$in{'comments'}
\n"; print GUESTBOOK "- $in{'name'}"; # Everything up to this point was straightforward: the # "begin" marker, the $datetime variable, the comments, # and the person's name, with some line breaks and HTML # tags thrown in. # But we didn't *require* them to write down their e-mail # address, city, state, or country, so we have to create # 'if' statements to decide whether to print them. This # is easy. Look at the first one: "if the $in{'email'} # variable exists, then output it to GUESTBOOK, with some # parentheses around it." The rest are all very similar. # # The last line in this section simply finishes up the # new entry with a line break and a horizontal rule line, # and the curly bracket closes off the 'if' statement that # looked for the "begin" marker. if ( $in{'email'} ) { print GUESTBOOK " ($in{'email'})"; } if ( $in{'city'} ) { print GUESTBOOK ", $in{'city'}"; } if ( $in{'state'} ) { print GUESTBOOK ", $in{'state'}"; } if ( $in{'country'} ) { print GUESTBOOK ", $in{'country'}"; } print GUESTBOOK "
\n
\n"; } # If the current line does NOT contain , print # out the current input ($_) again, unchanged. ($_ is a # special, predefined variable.) This ensures that whatever # was in the Guest Book before will still be there: else { print GUESTBOOK "$_"; } # This bracket simply finishes off the 'foreach' loop: } # Close the Guest Book filehandle, thus ending any output # to the file named by $guest_book_file: close (GUESTBOOK); # Send the user to the Guest Book HTML file so they can see # what they wrote. This is just a simple HTTP header, which # you should know all about by now: print "Location: $guest_book_url\n\n"; # [END OF MAIN PROGRAM] # Earlier, we promised that we'd tell you how to make the # new entries show up at the bottom of the list rather than # the top. Here's how: in the 'print GUESTBOOK' statements # where the new entry is placed into the Guest Book, move the # 'print GUESTBOOK "\n"' statement to the *end* # of the output -- right before the curly bracket that finishes # the 'if (//)' statement) -- rather than at the # beginning. It's as simple as that! ############################################################## # The "Missing" subroutine takes care of situations where the # user leaves either the Name or Comments field blank. sub Missing { # Print the HTTP header and the start of a new form that # tells people to supply whichever information was missing. # These will be ordinary print statements, as opposed to the # ones in the main program that sent output to a filehandle: print "Content-type: text/html\n\n"; print "\n"; print "Need more information\n"; print "\n"; # You need to figure whether it was the Name or Comments field # that was left blank. By default, you will say that the # missing information was BOTH fields; if information is found # in either one of those, the $missing_info variable will be # changed later. $missing_info = "both the Name AND the Comments fields!"; # But if the Name field exists, then it was only the Comments # which were left blank. Nothing is output at this stage; you # are just filling in variables. if ( $in{'name'} ) { $missing_info = "the Comments field."; } # If there are Comments, then the Name must be missing. if ( $in{'comments'} ) { $missing_info = "the Name field."; } # Now you simply tell them which information they forgot to # to write, using the $missing_info variable: print "You forgot to fill in $missing_info"; # Now you just have to give them a new form to fill in. It # will look much like the original Guest Book entry form, but # the original information will be placed into the form boxes # by using the 'value' attribute of the tags. You can # use the good old 'ENDOFTEXT' trick. print<
Your Name:
E-Mail:
City: State: Country:

Comments:

(Comments will be formatted as HTML, so you'll need to include your own <BR> tags if you want line breaks.)


Return to the guest book. ENDOFTEXT # The 'exit' statement makes the script stop right here in the # subroutine, rather than returning to the main program. The # curly bracket officially finishes off the subroutine. exit; } ############################################################## # The "CurrentTime" subroutine converts Perl's localtime(time) # variable to a more readable format. sub CurrentTime { # Perl's 'time' function counts the number of seconds since # a certain date in the past. The 'localtime' function # converts this number to a list of nine elements. You can # dump this list into nine meaningful scalar variables with # the following statement ($isdst tells whether it's Daylight # Saving Time or not): ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time); # 'Localtime(time)' thinks January is 0 and December is 11, so # you need to add 1 to the $month variable. Also, set a new # variable called $ampm to "AM" by default. $month = $month + 1; $ampm = "AM"; # The hour will be in 24-hour time, so 0 is really 12. Also, # hours greater than 12 will be reduced by 12, and the $ampm # variable will become "PM". Finally, minutes less than 10 # need to have a leading zero added. if ($hour == 0) { $hour = 12; } if ($hour > 12) { $hour = $hour - 12; $ampm = "PM" } if ($min < 10) { $min = "0$min"; } # This statement just strings all the date & time pieces # together and puts them in a variable called $datetime. This # subroutine does *not* have an 'exit' statement, because it # *should* return to the main program when it's done. $datetime = "$month/$mday/$year, $hour:$min $ampm"; }