#!/usr/bin/perl -T ####################################################################### # Application Information # ######################################################################## # Application Name: Extropia's WebGuestbook # Application Authors: Eric Tachibana (Selena Sol) and Gunther Birznieks # Version: 3.0 # Last Modified: 17NOV98 # # Copyright: # # You may use this code according to the terms specified in # the "Artistic License" included with this distribution. The license # can be found in the "Documentation" subdirectory as a file named # README.LICENSE. If for some reason the license is not included, you # may also find it at www.extropia.com. # # Though you are not obligated to do so, please let us know if you # have successfully installed this application. Not only do we # appreciate seeing the wonderful things you've done with it, but we # will then be able to contact you in the case of bug reports or # security announcements. To register yourself, simply send an # email to register@extropia.com. # # Finally, if you have done some cool modifications to the scripts, # please consider submitting your code back to the public domain and # getting some community recognition by submitting your modifications # to the Extropia Cool Hacks page. To do so, send email to # hacks@extropia.com # # Description: # # This guestbook script allows users to dynamically manipulate a # guestbook HTML file by adding their own entries to the document. # # Basic Usage: # # 1. Read the README.CHANGES, README.LICENSE, and README.SECURITY # files and follow any directions contained there # # 2. Change the first line of each of the scripts so that they # reference your local copy of the Perl interpreter. (ie: # #!/usr/local/bin/perl) (Make sure that you are using Perl 5.0 or # higher.) # # 3. Set the read, write and access permissions for files in the # application according to the instructions in the # README.INSTALLATION file. # # 4. Define the global variables in guestbook.setup.cgi # according to the instructions in the README.INSTALLATION file. # # 5. Point your web browser at the guestbook file # (i.e.: http://www.yourdomain.com/guestbook.html) # # More Information # # You will find more information in the Documentation sub-directory. # We recommend opening the index.html file with your web browser to # get a listing of supporting documentation files. ######################################################################## # Application Code # ######################################################################## # First, print out the HTTP header. We'll output this quickly so that we # will be able to do some of our debugging from the web and so that in # the case of a bogged down server, we won't get timed-out. Also, bypass # the Perl buffer with the first line. $| = 1; print "Content-type: text/html\n\n"; ####################################################################### # Require Libraries # ####################################################################### # First, get the customized information contained in the setup file. Then # Use cgi-lib.pl to read the incoming form data. cgi-lib.sol will be used # to lock the guestbook while we manipulate it and mail-lib.pl will be # used to send mail. require "./guestbook.setup.cgi"; require "$cgi_lib_location"; require "$cgi_sol_location"; require "$mail_lib_location"; ####################################################################### # Gather Form Data. # ####################################################################### # Use cgi-lib.pl to parse the incoming form data and tell cgi-lib to # prepare that information in the associative array %form_data &ReadParse(*form_data); ####################################################################### # Create Add Form # ####################################################################### # Now determine what the client wants. If $form_data{'action'} eq "add" # (client clicked on a button somewhere) or (||) $ENV{'REQUEST_METHOD'} # eq "post" (client is accessing this script for the first time as a # link, not as a submit button) then it means that the client is asking # to see the form to "add" an item to the guestbook. We will use the # subroutine add_form in the setup file to output the add form. if ($form_data{'action'} eq "add" || $ENV{'REQUEST_METHOD'} eq "GET") { &add_form_header; &output_add_form; exit; } ####################################################################### # Get the Date # ####################################################################### # Use the get_date subroutine at the end of this script to get the # current date and time so that we can use it in our output. $date = &get_date; ####################################################################### # Modify Incoming Form Data # ####################################################################### # Now check to see if we were asked to censor any particular words. # First, create an array of form variables by accessing the "keys" of the # associative array %form_data given to us by cgi-lib.pl. @form_variables = keys (%form_data); # For every variable sent to us from the form, and for each word in our # list of bad words, replace (=~ s/) any occurrence, case insensitively # (/gi) of the bad word ($word) with the word censored. # $form_data{$variable} should be equal to what the client filled in in # the input boxes... # # Further, if the admin has set allow_html to 0, (!= 1) it means that she # does not want the users to be able to use HTML tags...so, delete them. foreach $variable (@form_variables) { foreach $word (@bad_words) { $form_data{$variable} =~ s/\b$word\b/censored/gi; } if ($allow_html != "yes") { $form_data{$variable} =~ s/<([^>]|\n)*>//g; } } ####################################################################### # Check Required Fields for Data # ####################################################################### # For every field that was defined in our list of required fields, check # the form data to see if that variable has an empty value. If so, jump to # missing_required_field_data which is a subroutine at the end of this # script passing as a parameter, the name of the field which was not filled # out. foreach $field (@required_fields) { if ($form_data{$field} eq "" ) { &missing_required_field_data($field); } } if ($form_data{'password'} ne "36" ) { &bad_password_field_data; } if ($form_data{'url'} eq "http://") { $form_data{'url'} = ""; } ####################################################################### # Edit the Guestbook File # ####################################################################### # First open the guestbook html file. Then, read each of the lines in # the guestbook file into an array called @LINES Then close the # guestbook file. Finally, set the variable $SIZE equal to the number of # elements in the array (which is conveniently, the same number of lines in # the guestbook file) open (FILE,"<$guestbookreal") || &CgiDie ("I am sorry, but I was not able to find the HTML guestbook file defined by the variable guestbookreal in the setup file. The current value I have is $guestbookreal. please make sure the path and permissions are correct."); @LINES=; close(FILE); $SIZE=@LINES; # Now open up the guestbook file again, but this time open it for # writing...in fact we will overwrite the existing guestbook file with new # data (>). However, we will lock the file so that no other instances of # this script can manipulate the guestbook at the same time we are writing # to it. &GetFileLock ("$guestbookreal.lock"); open (GUEST,">$guestbookreal") || &CgiDie ("I am sorry, but I was not able to find the HTML guestbook file defined by the variable guestbookreal in the setup file. The current value I have is $guestbookreal. please make sure the path and permissions are correct."); # Now we are going to go through our @LINES array adding lines "back" to # out guestbook file one by one, inserting the new entry along the way. # For every line in the guestbook file (remember that $SIZE = number of # lines) we'll assign the value of the line ($LINES[$i]) to the variable $_ # We'll start with the first line in the array ($i=0) and we'll end when # we have gone through all of the lines ($i<=$SIZE) counting by one ($i++). # We reference the array in the standard form $arrayname[$element_number] for ($i=0;$i<=$SIZE;$i++) { $_=$LINES[$i]; # Now, if the line happens to be we know that we are going to # need to add a new entry. Thus, btw, it is essential that your # guestbook.html have that line, all on its own somewhere in the body when # you initialize your guestbook. if (//) { # Let's add the entry. First print again so that we will be # able to find the top of the guestbook again the next time. print GUEST "\n"; # Then begin adding the guest's information. First, let's print the Name # of the guest. However, if the guest left a URL, let's make their name # clickable top their URL. If the guest did not submit a URL, just print # the name. if ($form_data{'url'}) { print GUEST "Name:"; print GUEST " $form_data{'realname'}"; print GUEST "
\n"; } else { print GUEST "Name: $form_data{'realname'}
\n"; } if ($form_data{'married'}) { print GUEST "Married Name: $form_data{'married'}
\n"; } # Now print the email of the guest...and, if the admin has set the # $linkmail tag to one in the setup file, then make the email link clickable. if ( $form_data{'email'} ) { if ($linkmail eq "yes") { print GUEST "Email:"; print GUEST " "; print GUEST "$form_data{'email'}
\n"; } else { print GUEST " $form_data{'email'}
\n"; } } # Now print out the guest's address if they submitted the values. if ($form_data{'address'}) { print GUEST "Address: $form_data{'address'}
\n"; } if ( $form_data{'city'} ) { print GUEST "Location: $form_data{'city'},"; } if ( $form_data{'state'} ) { print GUEST " $form_data{'state'}"; } if ( $form_data{'country'} ) { print GUEST " $form_data{'country'}
\n"; } else { print GUEST "
"; } if ($form_data{'phone'}) { print GUEST "Phone: $form_data{'phone'}
\n"; } if ($form_data{'attend'}) { print GUEST "Will attend?: $form_data{'attend'}
\n"; } # Finally, print up the date and the comments. print GUEST "Date: $date
\n"; print GUEST "Comments:
$form_data{'comments'}"; print GUEST "
\n\n"; } # If the line was not however, we should make sure to print # up the line so that we retain all of the HTML that was in the guestbook # before we added the entry. Thus, the very long for loop will go # through each line...it will print the header...and get all the way down # through whatever HTML you've written until it gets to the guestbook # entries which begin with a . It will then print the new # entry and then print out all the old entries as well...When it gets to # the end of the file, it's over. else { print GUEST $_; } } # Close up the guestbook and release the lock file. close (GUEST); &ReleaseFileLock ("$guestbookreal.lock"); ####################################################################### # Send back an HTML Thank you to Guest # ####################################################################### # Now send the guest a thank you note on the web and provide her with a # way to get back to where she was before. &thank_you_html_header; # Print out a copy of their submissions. &display_entry; print qq!
Back to the Ramsey We are 50
When you get back, you may need to reload the page to see your entry.
!; ####################################################################### # Send Email Note to the Admin # ####################################################################### # Now prepare to email a note to the admin. Rename $form_data{'email'} # to $email_of_sender, and split up that email into its two components, # the username and the email server. Thus in selena@foobar.com, selena # becomes username and eff.org becomes server. We are going to need # these values later when we send our email. $email_of_guest = "$form_data{'email'}"; # Now, if the admin has set the $mail to yes (admin wants to be mailed when # someone enters a guestbook entry), then let's begin creating an email body. # We'll store the body in the variable $email_body and we will # continually append this variable by using .= if ($mail eq "yes") { $email_body .= "There is a new entry at the Rams70 web page: http://www.citilink.com/~jai/rams70/arhs.htm\n\n"; $email_body .= "------------------------------------------------------\n"; $email_body .= "Name: $form_data{'realname'}\n"; # If the guest actually submitted values, write them too. if ($form_data{'married'} ne "") { $email_body .="Married Name: $form_data{'married'}\n"; } if ($form_data{'email'} ne "") { $email_body .="Email: $form_data{'email'}\n"; } if ($form_data{'url'} ne "") { $email_body .="Home Page: $form_data{'url'}\n"; } if ($form_data{'address'} ne "") { $email_body .="Address: $form_data{'address'}\n"; } if ($form_data{'city'} ne "") { $email_body .= "Location: $form_data{'city'},"; } if ($form_data{'state'} ne "") { $email_body .= " $form_data{'state'}"; } if ($form_data{'country'} ne "") { $email_body .= " $form_data{'country'}\n"; } if ($form_data{'phone'} ne "") { $email_body .="Phone: $form_data{'phone'}\n"; } if ($form_data{'attend'} ne "") { $email_body .="Will attend?: $form_data{'attend'}\n"; } # Finish off the message body... $email_body .= "Time: $date\n\n"; $email_body .= "Comments: $form_data{'comments'}\n"; $email_body .= "------------------------------------------------------\n\n"; $email_body .= "Do not reply by clicking REPLY on your email client - it will be lost\n"; $email_body .= "REPLY ONLY and directly to the From address in the body of this email\n"; # Use the send_mail subroutine in the mail-lib.pl library file to send # the email to the admin. This routine takes 6 parameters, who is sending # the mail, the server of the sender, who it is being sent to and their # server, the subject and the body. open (FILE,"<$maillistreal") || &CgiDie ("I am sorry, but I was not able to find the HTML guestbook file defined by the variable maillistreal in the setup file. The current value I have is $maillistreal. please make sure the path and permissions are correct."); @LINES=; close(FILE); $SIZE=@LINES; foreach $addr (@LINES) { &send_mail("$email_of_guest", "$addr", "$email_subject", "$email_body"); } } ####################################################################### # Send Thank You Email to the Guest # ####################################################################### # Now, if the admin has set $remote_mail equal to yes and (&&) the guest has # actually submitted an email, we should email the guest a thank you note # also. The process is identical to the one above. if ($remote_mail eq "yes" && $form_data{'email'} ne "") { $email_body = ""; $email_body .= "$thank_you_email_text"; $email_body .= "\n"; $email_body .= " By the way, you wrote...\n\n"; $email_body .= " Name: $form_data{'realname'}\n"; if ($form_data{'married'} ne "") { $email_body .=" Married Name: $form_data{'married'}\n"; } if ($form_data{'email'} ne "") { $email_body .=" Email: $form_data{'email'}\n"; } if ($form_data{'url'} ne "") { $email_body .=" Home Page: $form_data{'url'}\n"; } if ($form_data{'address'} ne "") { $email_body .=" Address: $form_data{'address'}\n"; } if ($form_data{'city'} ne "") { $email_body .= " Location: $form_data{'city'},"; } if ($form_data{'state'} ne "") { $email_body .= " $form_data{'state'}"; } if ($form_data{'country'} ne "") { $email_body .= " $form_data{'country'}\n"; } if ($form_data{'phone'} ne "") { $email_body .=" Phone: $form_data{'phone'}\n"; } if ($form_data{'attend'} ne "") { $email_body .=" Will attend?: $form_data{'attend'}\n"; } $email_body .= " Time: $date\n\n"; $email_body .= " Comments: $form_data{'comments'}\n"; # Send off the email! &send_mail("$frompage", "$email_of_guest", "$email_subject", "$email_body"); &GetFileLock ("$maillistreal.lock"); open (MLIST,">$maillistreal") || &CgiDie ("I am sorry, but I was not able to find the HTML guestbook file defined by the variable guestbookreal in the setup file. The current value I have is $guestbookreal. please make sure the path and permissions are correct."); $flag = ""; for ($i=0;$i<=$SIZE;$i++) { $_=$LINES[$i]; if (/$email_of_guest/) { $flag = "yes"; } print MLIST $_; } if ($flag ne "yes") { print MLIST ", $email_of_guest"; } close (MLIST); &ReleaseFileLock ("$maillistreal.lock"); } exit; # Begin the subroutines... ####################################################################### # missing_required_field_data subroutine # ####################################################################### sub display_entry { if ($form_data{'url'}) { print "Name:"; print " $form_data{'realname'}"; print "
\n"; } else { print "Name: $form_data{'realname'}
\n"; } if ($form_data{'married'}) { print "Married Name: $form_data{'married'}
\n"; } # Now print the email of the guest...and, if the admin has set the # $linkmail tag to one in the setup file, then make the email link clickable. if ( $form_data{'email'} ) { if ($linkmail eq "yes") { print "Email:"; print " "; print "$form_data{'email'}
\n"; } else { print " $form_data{'email'}
\n"; } } # Now print out the guest's address if they submitted the values. if ($form_data{'address'}) { print "Address: $form_data{'address'}
\n"; } if ( $form_data{'city'} ) { print "Location: $form_data{'city'},"; } if ( $form_data{'state'} ) { print " $form_data{'state'}"; } if ( $form_data{'country'} ) { print " $form_data{'country'}
\n"; } else { print "
"; } if ($form_data{'phone'}) { print "Phone: $form_data{'phone'}
\n"; } if ($form_data{'attend'}) { print "Will attend?: $form_data{'attend'}
\n"; } # Finally, print up the date and the comments. print "Date: $date
\n"; print "Comments:
$form_data{'comments'}"; print "

\n\n"; } sub missing_required_field_data { # Assign the passed $variable parameter to the local variable $field local($field) = @_; # Now send the user an informative error message so that they can enter # the correct amount of information. &missing_required_field_note; # Now reprint out the add form with the subroutine output_add_form at the # end of this script. Then exit. exit; } sub bad_password_field_data { # Now send the user an informative error message so that they can enter # the correct amount of information. &bad_password_field_note; # Now reprint out the add form with the subroutine output_add_form at the # end of this script. Then exit. exit; } ####################################################################### # get_date # ####################################################################### sub get_date { @days = ('Sunday','Monday','Tuesday','Wednesday','Thursday', 'Friday','Saturday'); @months = ('January','February','March','April','May','June','July', 'August','September','October','November','December'); # Use the localtime command to get the current time, splitting it into # variables. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # Format the variables and assign them to the final $date variable. if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $year += 1900; $date = "$days[$wday], $months[$mon] $mday, $year at $hour\:$min\:$sec"; }