#!/dcs/bin/perl # The previous line needs to be changed to the path for your system's perl. # zd.pl 1.01 # Copyright (c) 1994,1995 Regents of the University of California # This code may be distributed and used freely as long as the above copyright # notice is kept intact. # Written by Leonard Megliola III # January 13, 1995 # This version includes e-mail address chopping and alias file searching. # This version also includes case-insensitivity of all Zot-Dispatch variables. # There are no guaranties/warranties about the performance of this program. Any # errors discovered should be e-mailed to Leonard Megliola (lmegliol@uci.edu) # Revisions: # 11/14/97: Fixed one known incompatibility with the Perl5 binary. ############################################################# # Almost everything that needs to be configured follows: # (The first line of the program needs to be configured too.) ############################################################# $date = "/usr/bin/date"; # Just check the paths of these two programs. $mailer = "/dcs/bin/mhmail"; # $Chop_Address = 0; # If this variable is set to 1, then all e-mail addresses # will have everything after the "@" removed (including # the "@", and only one e-mail address can be entered # in each individual input variable. If more than one # e-mail address is desired, enter them into additional # input variables of the same name. If more than one # e-mail address is entered in one input variable only # the first will be used. This makes it impossible to # e-mail outside of the server machine. $Alias_File = ""; # This variable must either be the empty string or contain # the name of an alias file readable by the server. If a # file is named here, then zot-dispatch will look up each # alias in the file. If the alias is present, it will # be substituted by the e-mail address, if not, the alias # will remain as the address being sent to. Normal alias # files MIGHT not work with zot-dispatch. The alias file # should have on each line an alias immediately followed # by a colon, followed by the e-mail address. # $Chop_Address must be set to 1 for this to work. $Separator = "\;"; # Character(s) that separate fields in method variable # Be careful when changing this. Test to make sure # your separator works if you change it. # Define where the library can be found (What directory.) $cgilib = "/Web/doc/indiv/lmegliol/www/cgi-bin"; push(@INC,$cgilib); require 'cgi-lib.pl'; # Change "cgi-lib.pl" to whatever you named it if you # changed its name. ############################################################# # Everything that needs to be configured is above. ############################################################# # These variables define the Zot-Dispatch variables that are used in the HTML # form. $ZDV_Method = "zd-method"; $REFLECT = "zd-reflect"; $MAIL = "zd-mail"; $APPEND = "zd-append"; $ZOT_ENVARS = "zd-environment"; $ZD_DATE_FORMAT = "zd-date-format"; $ZD_DATE = "zd-date"; $DATE_ELEMENT = "ZD-Date"; $ZD_Owner = "zd-owner"; $DEFAULT_SUBJECT = "Results from Zot-Dispatch"; # Constants defined for identifying states $BODY = 1; $FILE = 0; # Global variable $ERRORS = ""; $REFLECT_STORAGE = ""; $ZOT_SUBJECT = ""; # The following associative array is used as a table to look up variable names # to see if they are Zot-Dispatch variables or not. %elements = ($ZDV_Method,'',$REFLECT,'',$MAIL,'',$APPEND,'',$ZOT_ENVARS,'', $ZD_DATE_FORMAT,'',$ZD_DATE,'',$ZD_Owner,''); # Create the initial table of name/value pairs from data retrieved # either from the STDIN or the command line. &ReadParse; print &PrintHeader; # Print the content-type # Take every variable returned, convert it to lower case, check to see if # is a Zot-Dispatch variable, if so, keep it lower case and insert it into # a new associative array containing the name value pairs. If it isn't a # Zot-Dispatch variable, then put the variable name into the second associative # array as it is found in the first. foreach $key (keys %in) { $key_orig = $key; ($temp_key = $key) =~ tr/A-Z/a-z/; $key = $temp_key if (defined($elements{$temp_key})); $temp{$key} .= '\0' if (defined($temp{$key})); $temp{$key} .= $in{$key_orig}; } %in2 = %temp; # First, if a date format variable is present, then insert the # date (with the specified format) into our table so that # it can be substituted into a body. If the format is empty # then the format of the date will be the default for that program if (defined $in2{$ZD_DATE_FORMAT}) { @DATE_ARRAY = split(/\\0/,$in2{$ZD_DATE_FORMAT}); $DATE_FORMAT = $DATE_ARRAY[$#DATE_ARRAY]; if ($DATE_FORMAT eq "") { chop ($in{$DATE_ELEMENT} = `$date`); $in2{$ZD_DATE} = $in{$DATE_ELEMENT}; } else { chop ($in{$DATE_ELEMENT} = `$date +\"$DATE_FORMAT\"`); $in2{$ZD_DATE} = $in{$DATE_ELEMENT}; } } # For each environment variable named in ZOT_ENVARS put the # environment variable's name and that variable's value into the # table. if (defined $in2{$ZOT_ENVARS}) { @envars = split(/\\0/,$in2{$ZOT_ENVARS}); foreach $var (@envars) { $in{$var} = $ENV{$var} if (!defined($in{$var})); $in2{$var} = $in{$var} if (!defined($in2{$var})); } } # Global variables that contain the two default responses. $RDEFAULT = &Build_Reflect_Default; $DEFAULT = &Build_Default; # If there are multiple methods, they will all be stored in the same # variable separated by \0. (See ReadParse subroutine in cgilib.pl) # Here I split the list into the separate methods........ @METHOD = split(/\\0/,$in2{$ZDV_Method}); foreach $METHOD (@METHOD) { ($DISPATCH_METHOD,$DESTINATION,$FORMAT) = split(/$Separator/,$METHOD,3); $DISPATCH_METHOD =~ tr/A-Z/a-z/; $DISPATCH_COPY = $DISPATCH_METHOD; $DESTINATION_COPY = $DESTINATION; $FORMAT_COPY = $FORMAT; # Substitute the value of the variables if any of the method # fields were defined indirectly. (Substitute the variable name # with the value of the variable, and take only the last value # of the variable if it is Method or Template and has # more than one variable......... if ($DISPATCH_COPY =~ /\s*\$(.*)#\s*/) { $DISPATCH_METHOD = $in{$1} if (defined $in{$1}); @DM = split(/\\0/,$in{$1}); $DISPATCH_METHOD = $DM[$#DM] if ($#DM > 0); } if ($DESTINATION_COPY =~ /\s*\$(.*)#\s*/) { $DESTINATION = $in{$1} if (defined $in{$1}); } if ($FORMAT_COPY =~ /^\s*\$(.*)#\s*/) { $FORMAT = $in{$1} if (defined $in{$1}); @F = split(/\\0/,$in{$1}); $FORMAT = $F[$#F] if ($#F > 0); } # Check to see if the template is a file, body, or default and then # call Substitute_Into_Template() to do the substitution...... $_ = $FORMAT; if ($_ =~ /^\s*file:(.*)\s*/i) { $DATA = &Substitute_Into_Template($FILE,$1); $RDATA = $DATA; } elsif ($_ =~ /^\s*body:(.*)\s*/i) { $FORMAT =~ s/body:/body:/i; #Had to do the following because Perl has a hard #time recognizing multi-line expressions. $temp_body = substr($FORMAT,index($FORMAT,"body:")+5); $DATA = &Substitute_Into_Template($BODY,$temp_body); $RDATA = $DATA; } else { $RDATA = $RDEFAULT; $DATA = $DEFAULT; } # Below, depending on what the method is, Call the subroutine that # does it. One problem though. I want to make it so that only # the last method of type reflect is executed. It would be more # simple to have the first execute, but possibly better for the last. # This is what I did. For every method of type reflect, append the # data that would have been reflected to a variable separated from the # other reflect data by "\0". After we have finished going through # all the methods, take the last reflect data in the variable and output # that. if ($DISPATCH_METHOD eq $REFLECT) { $REFLECT_STORAGE .= $RDATA . "\\0"; } elsif ($DISPATCH_METHOD eq $MAIL) { &Mail_Response($DATA,$DESTINATION); } elsif ($DISPATCH_METHOD eq $APPEND) { &Append_Response($DATA,$DESTINATION); } } # We haven't performed our reflect yet, so take off the last data in our # Reflect storage variable and return in. @REFLECTS = split(/\\0/,$REFLECT_STORAGE); &Reflect_Response($REFLECTS[$#REFLECTS]); # Mail off any errors that occurred to the address in ZD-Owner if it is # defined. if ($ERRORS ne "") { &Mail_Errors($DEFAULT) if (defined $in2{$ZD_Owner}); } ############################################ # End of Main Program Subroutines Follow # ############################################ sub Reflect_Response { local($RDATA) = @_; print($RDATA); } sub Mail_Response { local($DATA,$To) = @_; $Addresses = ""; # If there was more than one variable with the same name that had # addresses in it, then there are some addresses separated by \0. # Split them up and separate them by spaces. foreach $value (split(/\\0/,$To)) { if ($Chop_Address == 1) { $value =~ s/@.*/ /g; if ($Alias_File ne "") { $value =~ /\s*([a-zA-Z0-9_\-]*)\s*/; $value = &search($1); } } $Addresses .= ", " . $value; } $Addresses =~ s/'//g; # If subject line is empty, make subject default. $ZOT_SUBJECT = $DEFAULT_SUBJECT if ($ZOT_SUBJECT eq ""); if (!open(MAIL, "| $mailer '$Addresses' -subject \"$ZOT_SUBJECT\"")) { $ERRORS .= "Mailer $mailer could not be successfully opened.\n"; } print(MAIL "\r\n"); print(MAIL $DATA); print(MAIL "\n\n"); if (!close(MAIL)) { $ERRORS .= "Mailer $mailer reported completing unsuccessfully"; $ERRORS .= "to: " . $Addresses . "\n"; } } sub Append_Response { local($DATA,$FILENAME) = @_; # If there was more than one variable with the same name that contained # filenames, then split up the filenames and apend to each file. @FILENAMES = split(/\\0/,$FILENAME); foreach $FILE (@FILENAMES) { if (-w $FILE) { if (open(HANDLE,">> $FILE")) { print(HANDLE $DATA); if (!close HANDLE) { $ERRORS .= "Closing file $FILE returned error code.\n"; } } else { $ERRORS .= "File $FILE could not be opened.\n"; } } else { $ERRORS .= "File $FILE could not be written to.\n"; } } } sub Mail_Errors { local($DATA) = @_; # This subroutine is almost exactly like the first mail subroutine except # it sends out the errors and the name/value pairs. There is also no # error messages generated when something goes wrong. Think about it. $Addresses = ""; foreach $value (split(/\\0/,$in2{$ZD_Owner})) { if ($Chop_Address == 1) { $value =~ s/@.*/ /g; if ($Alias_File ne "") { $value =~ /\s*([a-zA-Z0-9_\-]*)\s*/; $value = &search($1); } } $Addresses .= ", " . $value; } $Addresses =~ s/'//g; open(MAIL, "| $mailer '$Addresses' -subject \"Errors in Zot-Dispatch\""); print(MAIL "\r\n"); print(MAIL "The following errors occurred when running Zot-Dispatch:\n\n"); print(MAIL $ERRORS); print(MAIL "\n*******************************************************\n\n"); print(MAIL $DATA); print(MAIL "\n\n"); close(MAIL); } sub Build_Default { # Builds up the default name/value pairs in plain text. $DEFAULT = "Submittal Results\n"; $DEFAULT .= "The following name/value pairs were submitted:\n\n"; foreach (keys %in) { @VALUES = split(/\\0/,$in{$_}); $DEFAULT .= "
$_ = \n" if (($n = @VALUES) == 0);
foreach $VALUE (@VALUES) {
$DEFAULT .= "$_ = $VALUE\n";
}
}
$DEFAULT;
}
sub Build_Reflect_Default {
# Builds up the name value pairs in HTML
$RDEFAULT = "\n\n";
$RDEFAULT .= "\n\n$_ = \n" if (($n = @VALUES) == 0);
foreach $VALUE (@VALUES) {
$RDEFAULT .= "$_ = $VALUE \n";
}
}
$RDEFAULT .= "