#!/usr/local/bin/perl # FEATURES # # Automates the link submission and link editing processes by creating a datafile on your web site's server that is read # by Zeus. Zeus saves each submission into the ThemeSite database to be approved by you. # Sends email message to submitting webmaster # Optional - Require reciprocal link before accepting submission # ANTI-SPAM FEATURES # # Uses anti-spam word check to prevent spam submissions. Simple, but effective. # No complicated modifications to your web server # Tests for proper domain before submission # No email addresses embedded in HTML code for email harvesters to suck up # EMAIL FEATURES # # Validates the format of the submitted email address # Email options for SendMail, SMTP or None # Sends email notifications to an unlimited amount of email addresses # Optional - History Log # Can use separate optional Header and Footer files for HTML status and Thank You messages # Can use optional html Thank You page # Can use optional html error page ################################################################### ### SCRIPT CONFIGURATION VARIABLES ################################################################### $title_link_directory = "YourWebSite.com Link Directory"; # Recipients to receive email @all_recipients = ( "links\@yourwebsite.com", # Delete this line if you only need to send to one email address "directory\@yourwebsite.com" # the last email in the array does not have a trailing comma ); $links_directory = "/var/www/vhosts/yourwebsite.com/httpdocs/links"; $link_submission_file = "submission.dat"; # DO NOT change this name as Zeus will not be able to find it to read # Prevents calling the script from other sites. Use only lower case letters. Need each domain with and without 'www' @okaydomains=("yourwebsite.com","www.yourwebsite.com"); # Email Settings # # SMTP_SERVER: indicates the name of the host acting as the e-mail # gateway. "localhost" should work on most systems. # OR IF SMTP IS UNAVAILABLE TO YOU, USE SEND_MAIL - BUT NOT BOTH! # # To disable email sending, leave both = "" # #$SMTP_SERVER="localhost"; $SEND_MAIL="/bin/sendmail -t"; # Email Defaults $default_From = "links\@yourwebsite.com"; $default_Reply = "links\@yourwebsite.com"; $anti_spam_wrong_answer = "The anti-spam word is 'cat'. Please click your Back button to correct.\n"; $anti_spam_answer = "cat"; # To change the spam question, you must also change the actual question and form field value in the HTML code. # Creates activity log if $log_directory and $log_filename are not "". If log not desired set these to "" $log_directory = "/var/www/vhosts/yourwebsite.com/httpdocs/links"; $log_filename = "LinkSubmission.Log"; $log_add_date = 1; # 1 - Add Date and Time, 0 - No Date and Time $backgroundimage = "http://www.yourwebsite.com/images/graphics/background.jpg"; # If the files exist, they will be used as Header and Footer, otherwise default HTML is used. Set to "" if not used. $header_footer_directory = "/var/www/vhosts/yourwebsite.com/httpdocs/links"; # $header_filename = "headerinfo.txt"; # $footer_filename = "footerinfo.txt"; $header_filename = ""; $footer_filename = ""; # Always require a reciprocal link address before submission is allowed $require_link = 1; # 1 - Require Reciprocal link, 0 - Reciprocal link not required ################################################################# # SPECIAL HTML FORM VARIABLES ################################################################# ### REQUIRED IN HTML FORM # subject name of form for e-mail subject # required comma delimited list of required entry fields # If "all", then every form field in data_order will be required # If "none", then no form field will be required # data_order comma delimited list indicating what fields to actually # print and in what order. ### OPTIONAL # ok_url URL to go to if successful # not_ok_url URL to go to if unsuccessful ### CODE FOR HTML CONFIGURATION ############################## #
# # # # # # # ################################################################### # MAIN PROGRAM - Nothing to set after this ################################################################### use Socket; # &test; # Takes off trailing '/' from directory variables $links_directory =~ /(.*)\/?$/; $links_directory = $1; $log_directory =~ /(.*)\/?$/; $log_directory = $1; $header_footer_directory =~ /(.*)\/?$/; $header_footer_directory = $1; $system_date = &sys_date; $system_time = &sys_time; &decode_vars; if ($fields{"action"} eq "save") { # Substitute '|' for '' in the sorted order foreach $to_print (@sortlist) { $fields{$to_print} =~ s/\|//ge; } &validate_data; if ($require_link==1) { &validate_reciprocal_link; } &validate_anti_spam_word; if (&validate_email_address ($fields{'email'}) == 0) { exit; } &print_to_file; &send_recipient_email; &thank_you_email; if ($fields{'ok_url'} ne ""){ print "Location: $fields{'ok_url'}\n\n"; exit; } else { &thank_you; } } elsif ($fields{"action"} eq "reset") { unlink("$links_directory/$link_submission_file"); &header("Reset"); print "Submission file reset"; &footer; exit; } else { &header("Action variable not set"); print "Action variable not set"; &footer; exit; } ################################################################## sub print_to_file { #What,Title,Description,HomePageURL,ReciprocalLinkURL,ThemeCategory,Name,email,BannerURL # Create the Record string $record = ""; foreach $to_print (@sortlist) { $record .= $fields{$to_print} . "|"; } $record .= "http://" . $ENV{"HTTP_HOST"} . $ENV{"SCRIPT_NAME"}; # Save to file &file_append_string ($links_directory, $link_submission_file, $record, 0); # Create log &file_append_string ($log_directory, $log_filename, $record, $log_add_date); } ################################################################## sub validate_anti_spam_word { if ($fields{'abc'} ne '') { if ($fields{'abc'} ne $anti_spam_answer) { &header("Wrong"); print $anti_spam_wrong_answer; &footer; exit; } } } ################################################################## sub validate_reciprocal_link { if (($fields{'ReciprocalLinkURL'} eq '') || ($fields{'ReciprocalLinkURL'} eq 'http://')) { &header("Need Reciprocal Link"); print "Before submitting your web site, you must have a link on your web site to our web site."; &footer; exit; } } ################################################################## sub send_recipient_email { ### Compose Email Message if ($fields{'recipient'} ne "") { $msgtext=""; $msgtext .= "'$fields{'subject'}'\n"; } # Print in a sorted order foreach $to_print (@sortlist) { if ($fields{'recipient'} ne "") { $msgtext .= "$to_print = $fields{$to_print}\n"; } } $msgtext .= "\n\n"; $msgtext .= "This information was submitted from Host: $ENV{'REMOTE_ADDR'} at $system_time ET on $system_date\n"; # Add all recipients to bottom of message $msgtext .= "This information was emailed to:\n"; $msgtext .= "-----------------------------------------------------\n"; foreach $each_one (@all_recipients) { $msgtext .= "$each_one\n"; } # Add Env variables $msgtext .= "\n"; $msgtext .= "Path to form . : $ENV{\"SCRIPT_FILENAME\"}\n"; $msgtext .= "Web Location : $ENV{\"HTTP_REFERER\"}\n"; ### Send to all recipients if ($fields{'email'} ne "") { $from = $fields{'email'}; $reply = $fields{'email'}; } else { $from = $default_From; $reply = $default_Reply; } foreach $each_one (@all_recipients) { $send_to = $each_one; $mailresult=&sendmail($from, $reply, $send_to, $SMTP_SERVER, $fields{'subject'}, $msgtext); if ($mailresult ne "1") { &header("Mail Error"); print "MAIL NOT SENT. SMTP ERROR: $mailcodes{'$mailresult'}\n"; &footer; exit; } } } ################################################################## sub decode_vars { $i=0; read(STDIN,$temp,$ENV{'CONTENT_LENGTH'}); @pairs=split(/&/,$temp); foreach $item(@pairs) { ($key,$content)=split(/=/,$item,2); $content=~tr/+/ /; $content=~s/%(..)/pack("c",hex($1))/ge; $content=~s/\t/ /g; $content=~s/\0//g; #strip nulls $content =~ s/\n/\s/g; # strip newlines $content =~ s/\t/ /g; # strip tabs $content =~ s/\0//g; # strip nulls $content =~ s///g; # strip greater than $content =~ s/\'//g; # strip apostrophe $content =~ s/\"//g; # strip quote $content =~ s/\(//g; # strip open parenthesis $content =~ s/\)//g; # strip close parenthesis #### Add to Classifieds Delete Line 11/24/06 # $content =~ s/classifieds_remove/TL.classifieds_remove/ig; $fields{$key}=$content; if ($key eq "data_order") { $content=~s/\012//g; $content=~s/\015//g; $content=~s/ //g; $content=~s/ //g; @sortlist=split(/,/,$content); } if ($key eq "required") { $content=~s/\012//g; $content=~s/\015//g; $content=~s/ //g; @mandatory=split(/,/,$content); } } } ################################################################## sub validate_data { ### Test data_order fields if ($fields{'data_order'} eq "") { &header("NO Data Order List Variable"); print <<__W1__;

NO data_order list SPECIFIED!

__W1__ &footer; exit; } ### Test all Required fields # If 'required=""', use the data_order array to check for "" in a field. # This will require all fields specified in the data_order to be required if ($fields{'required'} eq "all") { # Use the 'data_order' array, bail on 1st bad foreach $to_check (@sortlist) { if ($fields{$to_check} eq "") { if ($fields{'not_ok_url'} ne "") { print "Location: $fields{'not_ok_url'}\n\n"; exit; } else { $missing_data .= "Missing - $to_check
\n"; } } } } elsif ($fields{'required'} eq "none") { # Do nothing } else { # Use the 'mandatory' array to check for "", bail on 1st bad field foreach $to_check (@mandatory) { if ($fields{$to_check} eq "") { if ($fields{'not_ok_url'} ne "") { print "Location: $fields{'not_ok_url'}\n\n"; exit; } else { $missing_data .= "Missing - $to_check
\n"; } } } } if ($missing_data ne "") { &try_again; } } ################################################################## sub thank_you { &header("Thank You"); print <<__W2__;

Thank you!

Your information has been sent.

Here is the information you provided:

__W2__ foreach $itm (@sortlist) { print <<__W2A__; $itm: $fields{$itm}

__W2A__ } # print "$record"; print <<__W2B__;

__W2B__ &footer; exit; } ################################################################## sub thank_you_email { ### Compose Email Message $msgtext=""; $msgtext .= "Your Link Directory Submission to $title_link_directory\n"; $msgtext .= "\n"; $msgtext .= "Thank you for submitting your web site to $title_link_directory"; $msgtext .= "\n"; $msgtext .= "Your link submission will be reviewed and you will be notified by email.\n"; $msgtext .= "Thank you for your interest to list in our directory.\n"; $msgtext .= "\n"; # Print in a sorted order foreach $to_print (@sortlist) { if ($fields{'recipient'} ne "") { $msgtext .= "$to_print = $fields{$to_print}\n"; } } $msgtext .= "\n"; $msgtext .= "This information was submitted from Host: $ENV{'REMOTE_ADDR'} at $system_time ET on $system_date\n"; foreach $itm (@sortlist) { $msgtext .= "$itm: - $fields{$itm}\n"; } $from = $default_From; $reply = $default_Reply; $send_to = $fields{'email'}; $subject = "Your Link Directory Submission to $title_link_directory"; $mailresult=&sendmail($from, $reply, $send_to, $SMTP_SERVER, $subject, $msgtext); if ($mailresult ne "1") { &header("Mail Error"); print "MAIL NOT SENT. SMTP ERROR: $mailcodes{'$mailresult'}\n"; &footer; exit; } } ################################################################## sub try_again { &header("Try Again"); print "

Missing Data!Please press the back button and fill in required fields!

\n"; print "

\n"; print "$missing_data\n"; print "
\n"; &footer; exit; } ################################################################### # SENDMAIL ################################################################### # # error codes below for those who bother to check result codes # # 1 success # -1 $smtphost unknown # -2 socket() failed # -3 connect() failed # -4 service not available # -5 unspecified communication error # -6 local user $to unknown on host $smtp # -7 transmission of message failed # -8 argument $to empty # # Sample call: # # &sendmail($from, $reply, $to, $smtp, $subject, $message ); # # Note that there are several commands for cleaning up possible bad inputs - if you # are hard coding things from a library file, so many of those are unnecesssary # sub sendmail { my ($fromaddr, $replyaddr, $to, $smtp, $subject, $message) = @_; $to =~ s/[ \t]+/, /g; # pack spaces and add comma $fromaddr =~ s/.*<([^\s]*?)>/$1/; # get from email address $replyaddr =~ s/.*<([^\s]*?)>/$1/; # get reply email address $replyaddr =~ s/^([^\s]+).*/$1/; # use first address $message =~ s/^\./\.\./gm; # handle . as first character $message =~ s/\r\n/\n/g; # handle line ending $message =~ s/\n/\r\n/g; $smtp =~ s/^\s+//g; # remove spaces around $smtp $smtp =~ s/\s+$//g; if (!$to) { return(-8); } if ($SMTP_SERVER ne "") { my($proto) = (getprotobyname('tcp'))[2]; my($port) = (getservbyname('smtp', 'tcp'))[2]; my($smtpaddr) = ($smtp =~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) ? pack('C4',$1,$2,$3,$4) : (gethostbyname($smtp))[4]; if (!defined($smtpaddr)) { return(-1); } if (!socket(MAIL, AF_INET, SOCK_STREAM, $proto)) { return(-2); } if (!connect(MAIL, pack('Sna4x8', AF_INET, $port, $smtpaddr))) { return(-3); } my($oldfh) = select(MAIL); $| = 1; select($oldfh); $_ = ; if (/^[45]/) { close(MAIL); return(-4); } print MAIL "helo $SMTP_SERVER\r\n"; $_ = ; if (/^[45]/) { close(MAIL); return(-5); } print MAIL "mail from: <$fromaddr>\r\n"; $_ = ; if (/^[45]/) { close(MAIL); return(-5); } foreach (split(/, /, $to)) { print MAIL "rcpt to: <$_>\r\n"; $_ = ; if (/^[45]/) { close(MAIL); return(-6); } } print MAIL "data\r\n"; $_ = ; if (/^[45]/) { close MAIL; return(-5); } } if ($SEND_MAIL ne "") { open (MAIL,"| $SEND_MAIL"); } print MAIL "To: $to\n"; print MAIL "From: $fromaddr\n"; print MAIL "Reply-to: $replyaddr\n" if $replyaddr; print MAIL "X-Mailer: Perl Powered Socket Mailer\n"; print MAIL "Subject: $subject\n\n"; print MAIL "$message"; print MAIL "\n.\n"; if ($SMTP_SERVER ne "") { $_ = ; if (/^[45]/) { close(MAIL); return(-7); } print MAIL "quit\r\n"; $_ = ; } close(MAIL); return(1); } ################################################################## # CHECKING FOR A BAD EMAIL ADDRESS ################################################################## # # if (&validate_email_address($fields{'email'}) == 0 { # exit; # } sub validate_email_address { my ($testmail) = @_; if ($testmail ne "") { if ($testmail =~/ /) { $bad_email = 1; } if ($testmail =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/ || $testmail !~ /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/) { $bad_email = 1; } else { # It's OK so do nothing return 1; } } else { # It's not there so do nothing. It will be caught in validate_data sub return 1; } if ($bad_email == 1) { &header("e-mail address is improperly formatted"); print "\n"; print "\n"; print "Your e-mail address is improperly formatted.\n"; print "

\n"; print "Please use your browser's back button to return to the form entry page.\n"; print "
\n"; print "
\n"; &footer; return 0; } } ################################################################## # VALIDATE DOMAIN # Check for Valid call from an approved domain # Prevents calling the script from other sites. ################################################################## # # @okaydomains=("yourwebsite.com","www.yourwebsite.com"); # # if (&validate_domain (@okaydomains, $ENV{'HTTP_REFERER'}) == 0) { # exit; # } sub validate_domain { # $testdomain = &validate_domain (@okaydomains, $ENV{'HTTP_REFERER'}); # if ($testdomain == 0) { # exit; # } my (@testdomains, $envstring) = @_; if (@testdomains == 0) {return 0;} $DOMAIN_OK = 0; $envstring =~ tr/A-Z/a-z/; foreach $domain (@testdomains) { if ($envstring =~ /$domain/i) { $DOMAIN_OK = 1; } } if ( $DOMAIN_OK == 0) { &header("Incorrect Domain"); print "Sorry....Cant run this script from this domain name!
\n"; print "S - $envstring $domain
\n"; print "Array - @testdomains
\n"; print "envstring - $envstring"; &footer; return 0; exit; } return 1; } ################################################################### # DATE TIME ################################################################### # # $system_date = &sys_date; # $system_time = &sys_time; sub sys_date { %mn = ('Jan','01', 'Feb','02', 'Mar','03', 'Apr','04', 'May','05', 'Jun','06', 'Jul','07', 'Aug','08', 'Sep','09', 'Oct','10', 'Nov','11', 'Dec','12' ); $sydate=localtime(time); ($day, $month, $num, $time, $year) = split(/\s+/,$sydate); $zl=length($num); if ($zl == 1){ $num = "0$num"; } $mmddyyyy="$mn{$month}\-$num\-$year"; return $mmddyyyy; } sub sys_time { $sydate=localtime(time); ($day, $month, $num, $time, $year) = split(/\s+/,$sydate); return $time; } ################################################################## # APPEND STRING TO FILE ################################################################## sub file_append_string { # Subs Needed: # sys_date # sys_time # lock_set # file_get_script_generic_name # lock_drop # file_get_script_generic_name # # Create log # # CHMOD this directory to 777. Leave empty "" if no log is wanted # $directory = "/usr/local/etc/httpd/vhosts/cyberrob/logs"; # $filename = "formprocess.txt"; # $string = "$fields{subject}, $fields{recipient}, $ENV{\"SCRIPT_FILENAME\"}, " . # "$ENV{\"HTTP_REFERER\"}, $ENV{'REMOTE_ADDR'}, $fields{email}, $fields{ok_url}"; # $file_add_date = 1; # &file_append_string ($directory, $filename, $string, $file_add_date); my ($directory, $filename, $string, $add_date) = @_; # Takes off the trailing '/' $directory =~ /(.*)\/?$/; $directory = $1; if (($directory ne "") && ($filename ne "") && ($string ne "")) { &lock_set; open(OUT_FILE,">>$directory/$filename") || die "OPEN $filename ERROR - $!"; if ($add_date == 1) { $system_date = &sys_date; $system_time = &sys_time; $string = "$system_date $system_time - $string"; } print OUT_FILE "$string\n"; close(OUT_FILE) || die "CLOSE $filename ERROR - $!"; &lock_drop; } } ################################################################## # LOCK FILES ################################################################## # Subs Needed: # file_get_script_generic_name # &lock_set; # &lock_drop; sub lock_set { local ($endtime); $endtime = 15; $endtime = time + $endtime; $lockfile = "$links_directory/&file_get_script_generic_name.lck"; while (-e $lockfile && time < $endtime) { # Do Nothing } open(LOCK_FILE, ">$lockfile"); } sub lock_drop { $lockfile = "$links_directory/&file_get_script_generic_name.lck"; close($lockfile); unlink($lockfile); } ################################################################## # GET GENERIC FILE NAME # Returns just the file name w/o the extension ################################################################## # # $filename = &file_get_script_generic_name; sub file_get_script_generic_name { $filename = $ENV{'SCRIPT_NAME'}; $filename =~ s/\//\./g; # Change '/' to '.' $filename =~ s/\\/\./g; # Change '\' to '.' $filename =~ s/\.cgi-bin\.//g; # Strip '.cgi-bin.' $filename =~ s/\.cgi//g; # Strip '.cgi' $filename =~ s/\.pl//g; # Strip '.pl' return $filename; } ################################################################## # HEADERS AND FOOTERS ################################################################## # # $backgroundimage = "http://www.yourwebsite.com/images/graphics/background.jpg"; # &header ("Title"); sub header { my ($title) = @_; print "Content-type: text/html\n\n"; print "\n\n"; print "\n"; print "$title\n"; print "\n"; print "\n"; if (-e "$header_footer_directory/$header_filename") { open (FILE_TO_OPEN, "<$header_footer_directory/$header_filename") || die "OPEN $header_filename ERROR - $!"; @strings = ; close(FILE_TO_OPEN); print @strings; } } sub footer { if (-e "$header_footer_directory/$footer_filename") { open (FILE_TO_OPEN, "<$header_footer_directory/$footer_filename") || die "OPEN $footer_filename ERROR - $!"; @strings = ; close(FILE_TO_OPEN); print @strings; } print "\n"; print "\n"; } sub test { my ($title) = @_; print "Content-type: text/html\n\n"; print "\n\n"; print "\n"; print "$title\n"; print "\n"; print "\n"; print "TEST\n"; print "\n"; print "\n"; exit; }