#!/usr/bin/perl #!perl ############################################################################## # ============================================= # SEC 2.0 - Comments # ============================================= ############################################################################## # gbook.pl - Guestbook that appends guestbook form Data as JavaScript Functions # # gbook.pl or guestbook.pl or gbookSpecial.pl # # It is adapted from a guestbook cgi script on BTinternet in 1997 # # Most guestbook appended guestbook entries to an HTML file # I wanted a format I could process the data before display. # I can use javascript to load the guestbook data. # # It appends the form data in javascript gbF() to "gbookF.js" # # Your web page can process and display the data as required. # # Take the form fields and output them wrapped in the format: # # gbF( # "name","email"," sun 23/Jun/2002 at 20: 52: 0 ","127.0.0.1", # "userfield1", # "userfield2", # "userfield3", # "userfield4", # "comments" # ); # # control form fields: # guestbook used to select "gbookF.js" filename # or edit script as required. # # loadnextpage if defined use URL in nextpage to replace this page. # nextpage URL to replace # # The script can reload the Web page using: # Location: and $ENV{'HTTP_REFERER'} and add "?ok" or "?error:code" # # ($fromURL, $fromQuerystring) = split(/\?/,$ENV{'HTTP_REFERER'} ); # $qs = "?ok"; # # print "Location: $fromURL$qs \n\n"; # # The query string for the page can be used to pass error messages # back to the original page with the form. # # http://127.0.0.1/form.htm?ok # or # http://127.0.0.1/form.htm?Error=File:/var/www/html/gb/gbookFXXX.js # # It was adapted from a guestbook cgi script on BTinternet in 1997 # # Instead of an HTML file, I wanted a format I could process the data. # # The data is in a file that I can include. # I use gbF(). # # You can process it as you want. # # The data is wrapped in gbF() function calls # appended to a javascript include file. # # Your web page can include this file. # # Your definition of gbF() can unpack the data, format and use it. # # The data is stored in a guestbook "gbookF.js" or "gbookFXXX.js" # # It is possible to specify XXX using $FORMJS{'guestbook'} # # or modify this script to add anti-spam code. # # nextpage URL to replace # # # ============================================= # SEC 2.0 - Comments - What to set ip in your HTML file # ============================================= # It was adapted from a guestbook cgi script on BTinternet in 1997 # Instead of an HTML file, I wanted a format I could process the data. # # The data is in a javascript include file. # # The data is wrapped in gbF() function calls # # appended to a javascript include file. # # Your web page can includes this file. # # The data is stored in a guestbook "gbookF.js" or "gbookFXXX.js" # You can process it as you want. # # # # # set $FORMJS{'guestbook'} to select guestbook XXX # # # # # You may need to refesh as javascript may be cached. # # # ============================================= # SEC 2.0 - Comments # ============================================= # # To install this code. Copy this into a file called gbook.pl # FTP up to your Web server from your PC as a TEXT file. # NOTE: I have found that AUTO sometimes does not work, # as the .pl extenstion causes it to be thought of as BINARY # and some CGI perl imterpreters do not like CRLF # # Now ensure that the file permissions are set to execute # NOTE: Don't forget to set the file permissions to execute (-rwxr-xr-x) # NOTE: Upload as TEXT or ASCII. Auto sometimes does not work if perl is installed on the PC. # NOTE: If you get Internal server error, check that your path to perl above is correct. # NOTE: If you get Internal server error, check that your FTP up script as TEXT # NOTE: If you get Internal Server error, check if your file paths are correct. #Doug Rice, Copyright 2002,2003 ############################################################################## # If you are getting Internal server error messages, # use the code below to pipe script errors to the browser # # uncomment line below to view compiler errors # #BEGIN { #$| = 1; #open (STDERR, ">&STDOUT"); #print "Content-type: text/html\n\n
\n"; 
#} 
#
# =============================================
# SEC 2.0 - INIT inline code
# =============================================
#
#
# uncomment line below to view compiler errors 
use CGI::Carp ( fatalsToBrowser)

# Use Socket to reverse DNS IP address 
use Socket;

#
# Try and reverse lookup IP address.
#
($name, $aliases, $addrtype, $length, @addrs) = gethostbyaddr( inet_aton( $ENV{'REMOTE_ADDR'} ), PF_INET );

# specify  the path to the guestbook file  gbookFXXXX.js
# XXXX is value of hidden form field:  guestbook 
#
# Ensure that gbookFXXXX.js has write permissions
#
# if the directory has execute permissions, this script will create gbookFXXXX.js

# use to save in your web site's root webdirectory
# On appache this is normally ./HTDOCS/

#
# Find out where the documents are stored. 
# One should work.
#
$doc_root = $ENV{'DOCUMENT_ROOT'}.$ENV{'C_DOCUMENT_ROOT'};

# On plus.net CGI server I had to use: $ENV{'C_DOCUMENT_ROOT'}
#
# You cannot include the file from the cgi-bin directory 
# so save in an adjacent branch
# or the relative path to a directory called gb 
# add gbookF prefix to prevent overwriting any file attack
# by crafted settings of  $FORMJS{'guestbook'}
#
$guestbookjsf  = './../gb/gbookF';
$guestbookjsf  = $doc_root.'/gb/gbookF';

#
# make files RW 
#
# print `chmod 666 $guestbookjsf*.js`
#$unlockcmd = "chmod 666 $guestbookjsf*.js"
#$lockcmd   = "chmod 444 $guestbookjsf*.js"

$unlockcmd = "chmod 666 " ;
$lockcmd   = "chmod 444 " ;

#
#
# =============================================
# SEC 2.0 - process FORM fields sent using POST
# =============================================
#
# Get the input, i.e the form fields pushed up to the CGI script. 
#
# If POST read STDIN
# If GET  decode QUERY_STRING
#
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

#Combine the query string and form fields

# Split the name-value pairs sent via GET and POST
@pairs = split(/&/, $ENV{'QUERY_STRING'}."&".$buffer );


foreach $pair (@pairs) {

   ($name, $value) = split(/=/, $pair);

   # Un-Webify plus signs and %-encoding
   $value =~ tr/+/ /;
   # Leave the value mostly escaped as JavaScript can unescape easily.

   # Convert CR LF and LF to 
\ at the end of the line $value =~ s/%0D//g; $value =~ s/%0A/
\\\n/g; # Convert \ " and '' $value =~ s/%5C/\\\\/g; $value =~ s/%22/\\"/g; $value =~ s/%27/\\'/g; # convert escaped characters to C character $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORMJS{$name} = $value; } # # Use email to validate user and filter spam # $unlock = 'lock'; if ( $FORMJS{'email'} eq 'dem0@dem0' ){ $unlock = 'unlock'; # blank off email to hide what worked $FORMJS{'email'} = ''; # force to one guest book # $FORMJS{'guestbook'} = 'Bookings'; } if ( $FORMJS{'email'} eq 'env' ){ print "\n" . '========== @ENV - foreach =========='."\n"; foreach $key (sort(keys %ENV)) { print "\n$key," . '=' . $ENV{ $key } ; } } # ============================================= # SEC 2.0 - Validate a field to prevent spam # ============================================= #HTTP_ORIGIN, =http://127.0.0.1 #HTTP_REFERER,=http://127.0.0.1/form.htm?edit # # Validation of guestbook # # if ( $FORMJS{'guestbook'} ne 'Bookings' ){ # $unlock = 'lock'; # } if ( $unlock eq 'unlock' ){ # If unlock make guestbook files RW # #print `chmod 660 ../public/gb/gbook*.js` ; #print `chmod 660 /var/www/html/gb/gbook*.js` ; # run chmod on server to make files read write print `$unlockcmd $guestbookjsf$FORMJS{'guestbook'}.js` ; } $date ="26 oct 2002 09:00;"; # date formatted so that JavaScript can parse it &setDate(); # ============================================= # SEC 2.0 - Write data to file # ============================================= # take form fields and wrap them in the JavaScript Function call and append it onto the end of "gbookF$FORMJS{'guestbook'}.js" # Take the form fields and output them wrapped in the format: #gbF( #"name","email"," sun 23/Jun/2002 at 20: 52: 0 ","127.0.0.1", #"userfield1", #"userfield2", #"userfield3", #"userfield4", #"comments" #); # # Lock file tile end of perl script. # # This has not been a big problem # # Buffering also makes file appends very quick. # #open my $file, ">", "app.lock" or die $!; #flock $file, 2 or die "Unable to lock file $!"; # we have the lock # &setDate(); $N = $FORMJS{'guestbook'}; open (GUESTFJS,">>$guestbookjsf$N.js") || &file_error( GUESTJS, "$guestbookjsf$N.js" ); # this blocks if file is locked flock GUESTFJS, 2 || &file_error( GUESTJS, "lock: $guestbookjsf$N.js" ); HTTP_USER_AGENT # get time stamp &setDate(); print GUESTFJS "// Added by gbook.pl $ENV{'HTTP_REFERER'} \n"; print GUESTFJS "// HTTP_USER_AGENT: $ENV{'HTTP_USER_AGENT'} \n"; print GUESTFJS "gbF( \n"; print GUESTFJS "\"$FORMJS{'name'}\","; print GUESTFJS "\"$FORMJS{'email'}\","; print GUESTFJS "\"$date\","; # print GUESTFJS "\"$ENV{'REMOTE_ADDR'}\",\n"; print GUESTFJS "\"$ENV{'REMOTE_ADDR'} $ENV{'HTTP_X_FORWARDED_FOR'} | $name $aliases \",\n"; print GUESTFJS "\"$FORMJS{'userfield1'}\",\n"; print GUESTFJS "\"$FORMJS{'userfield2'}\",\n"; print GUESTFJS "\"$FORMJS{'userfield3'}\",\n"; print GUESTFJS "\"$FORMJS{'userfield4'}\",\n"; print GUESTFJS "\"$FORMJS{'comments'}\"\n"; print GUESTFJS ");\n\n"; close (GUESTFJS); ###################### # # Lock down the guestbook directory # Should really unlock file a # ###################### #set files to read only # #$lockcmd = "chmod 444 $guestbookjsf*.js" #print `$lockcmd $guestbookjsf*.js` ; print `$lockcmd $guestbookjsf$FORMJS{'guestbook'}.js` ; if ( $FORMJS{'loadnextpage'} ){ # # Print Out Initial Output Location Heading # print "Location: $FORMJS{'nextpage'}\n\n"; exit; } # ============================================= # SEC 2.0 - Exit inline code # ============================================= # # Exit script and reload page submitting form # # remove ?query string and send a new one which can indicate problems # if URL ends # ?ok - successfull # ($fromURL, $fromQuerystring) = split(/\?/,$ENV{'HTTP_REFERER'} ); $qs = "?ok"; print "Location: $fromURL$qs \n\n"; exit; # else print a page to thank form submission. # Print Beginning of HTML print "Content-Type: text/html\n\n"; print "Thank You\n"; print "

Thank You For your submission

\n"; print "

return...

"; print ''; exit; # ============================================= # SEC 2.0 - Subroutines # ============================================= # file_error - call if problems opening files sub file_error { local($FH, $fileName) = @_; ###################### # # Lock down the guestbook directory # Should really unlock file a # ###################### # # set files to read only # # lock all files to read only # print `chmod 444 $guestbookjsf*.js` # print `$lockcmd $guestbookjsf*.js` ; # not sure what happens if flock # lock specified guestbook to read only # print `$lockcmd $guestbookjsf$FORMJS{'guestbook'}.js` ; # print `ls -l $guestbookjsf*.js` ; # # Exit script and reload page submitting form # # remove ?query string and send Error # # ($fromURL, $fromQuerystring) = split(/\?/,$ENV{'HTTP_REFERER'} ); $qs = "?Error=File:$fileName"; print "Location: $fromURL$qs \n\n"; exit; # # Print Beginning of HTML # print "Content-Type: text/html\n\n"; print "Thank You\n"; print "

Error Opening File $fileName:, press back

\n"; print "Your data has not been added, press back

\n"; print "If you can log into the server, check file permissions\n"; print ''; exit; } ################################################################ # setDate setup $date to string that javascript can parse using: now= new Date( postedOn ) # sub setDate { # Get the Date for Entry # output date so that the web pages can be use the javascript: now= new Date( postedOn ) #IE 5 formats toUTCString(): Tue, 25 Jun 2002 05:47:32 UTC #Netscape Navigator toUTCString(): Tue, 25 Jun 2002 05:49:59 GMT #($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # 0 1 2 3 4 5 6 7 8 @t = localtime(); @days= ('Sun','Mon','Tue','Wed','Thu','Fri','Sat','Sun'); @months=('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); $fullYear=1900+$t[5]; #toUTCString(): #Tue, 25 Jun 2002 05:47:32 UTC $date = "$days[$t[6]], $t[3] $months[$t[4]] $fullYear ".substr("0".$t[2],-2,2).":".substr("0".$t[1],-2,2).":".substr("0".$t[0],-2,2)." UTC+0100"; } # ============================================= # SEC 2.0 - End # =============================================