#!/usr/local/bin/perl5 -w
#
# majordomo2
#
# This is the completion routine for signing up for a majordomo list.
# Check the variables for sanity, and then send e-mail to sign up for
# a list.
#
# Written by Dave Regan
# 24 June 1996
# This program is in the Public Domain.
# Do what you want with it.
#
# Packages which deal with the same sort of topic:
# http://iquest.com/~fitz/www/mailserv/
# http://hellfire.hare.net.au/cgi-bin/MailServ/majordomo
# http://www.vv.com.au/cgi-bin/vv/mailserv/majordomo-admin
#
###
### Configuration
###
$DefaultHost = "peak.org";
$Mail = "/usr/lib/sendmail";
$LogFile = "/info/var/log/httpd/majordomo";
$HotList = "/info/peak_info/mlists/hotlist";
###
### Main program
###
# CheckSanePost();
$Vars{'bgcolor'} = "#FFFFFF";
$Vars{'link'} = "";
ParseFormVariables();
ParseQueryParameters();
HTMLhead("Account Validation");
print "
\n";
$| = 1;
# printenv();
# printvars();
ReadHotList();
if (CheckData() == 0)
{
print "Please use the back button of your browser and correct the form.\n";
print "Once the data is corrected, resubmit the data.
\n";
}
elsif (CheckHotList())
{
print "This program has been disabled from your site. Sorry.\n";
LogAccess(0);
}
else
{
print "Your request has been sent. Expect to see results in your e-mail soon.\n";
if ($Vars{'link'} ne "")
{
print "Please continue.\n";
}
LogAccess(1);
SendMail();
}
HTMLterm();
exit 0;
###
### CheckData
###
### See if the data looks reasonable.
###
sub CheckData
{
local($retval);
$retval = 1;
# Make sure that the values exist
$Vars{'subscribe'} = "" if (!defined($Vars{'subscribe'}));
$Vars{'unsubscribe'} = "" if (!defined($Vars{'unsubscribe'}));
$Vars{'help'} = "" if (!defined($Vars{'help'}));
$Vars{'info'} = "" if (!defined($Vars{'info'}));
$Vars{'index'} = "" if (!defined($Vars{'index'}));
$Vars{'which'} = "" if (!defined($Vars{'which'}));
$Vars{'who'} = "" if (!defined($Vars{'who'}));
$Vars{'lists'} = "" if (!defined($Vars{'lists'}));
$Vars{'get'} = "" if (!defined($Vars{'get'}));
# We need an e-mail address to do anything
if ($Vars{'email'} eq "")
{
print "You must specify a valid e-mail address to do much of anything ";
print "with majordomo.
\n";
$retval = 0;
}
$Vars{'email'} = "$Vars{'email'}\@$DefaultHost" if ($Vars{'email'} !~ /\@/);
# # subscribe and unsubscribe really want a real name
# if ( ($Vars{'subscribe'} ne "" || $Vars{'unsubscribe'} ne "") && $Vars{'name'} eq "")
# {
# print "Subscriptions and unsubscriptions require your name.
\n";
# $retval = 0;
# }
# For some of the operations, a mailing list and host must be specified
if ( ($Vars{'mlist'} eq "" || $Vars{'host'} eq "") &&
($Vars{'subscribe'} ne "" ||
$Vars{'unsubscribe'} ne "" ||
$Vars{'info'} ne "" ||
$Vars{'index'} ne "" ||
$Vars{'who'} ne "" ||
$Vars{'get'} ne ""))
{
print "The options you have selected require that you specify a mailing list name\n";
print "as well as a host name.
\n";
$retval = 0;
}
# Cannot both subscribe and unsubscribe
if ($Vars{'subscribe'} ne "" && $Vars{'unsubscribe'} ne "")
{
print "Cannot subscribe and unsubscribe at the same time.
\n";
$retval = 0;
}
# Cannot specify "get" unless there is a filename
if ($Vars{'get'} ne "" && $Vars{'fname'} eq "")
{
print "Please specify a filename when using the \"GET\" option.
\n";
$retval = 0;
}
return $retval;
}
###
### CheckHotList
###
### See if either the REMOTE_HOST or REMOTE_ADDR match any
### of the hot list patterns.
###
sub CheckHotList
{
my($pat);
for $pat (@HotPattern)
{
return 1 if ($ENV{'REMOTE_HOST'} =~ /$pat/);
return 1 if ($ENV{'REMOTE_ADDR'} =~ /$pat/);
}
return 0;
}
####
#### CheckSanePost
####
#### See that this is a legitimate POST request. Die if not.
#### This assumes that the initial Content-type message has *not*
#### been sent.
####
#sub CheckSanePost
# {
# ###
# ### Ensure that the form of the request looks valid.
# ###
# if ($ENV{'REQUEST_METHOD'} ne "POST")
# {
# HTMLhead("Bad method");
# print "This script should be referenced with a METHOD of POST.\n";
# print "If you don't understand this, see this:\n";
# print "forms overview.\n";
# HTMLterm();
# exit 0;
# }
#
# if ($ENV{'CONTENT_TYPE'} ne "application/x-www-form-urlencoded")
# {
# HTMLhead("Bad encoding");
# print "This script can only be used to decode form results.\n";
# HTMLterm();
# exit 1;
# }
# }
###
### HTMLhead
###
### Put out a HTML header
###
sub HTMLhead
{
local($title) = @_;
print "Content-type: text/html\n\n";
print "
$title\n";
}
###
### HTMLterm
###
### Put out the end of an HTML body.
###
sub HTMLterm
{
print "\n";
}
###
### LogAccess
###
### Write some information out into a log file.
###
sub LogAccess
{
my($honor) = @_;
my($email, $host, $key, $mlist);
$email = $Vars{'email'};
$host = $Vars{'host'};
$host =~ s/[^-_.A-Za-z0-9]//g; # Restrict the host name.
# It may be necessary to expand this to include
# other characters. Do so if needed.
$mlist = $Vars{'mlist'};
if (!open(LOG, ">>$LogFile"))
{
# print STDERR "Cannot open $LogFile\n";
return;
}
print LOG scalar localtime;
if ($honor == 0) { $honor = " NOT"; }
else { $honor = ""; }
print LOG "\nRequest$honor honored\n";
print LOG "From: $email\n";
print LOG "To: majordomo\@$host\n";
print LOG "\n";
print LOG "subscribe $mlist $email\n" if ($Vars{'subscribe'} ne "");
print LOG "unsubscribe $mlist $email\n" if ($Vars{'unsubscribe'} ne "");
print LOG "help\n" if ($Vars{'help'} ne "");
print LOG "info $mlist\n" if ($Vars{'info'} ne "");
print LOG "index $mlist\n" if ($Vars{'index'} ne "");
print LOG "which $email\n" if ($Vars{'which'} ne "");
print LOG "who $mlist\n" if ($Vars{'who'} ne "");
print LOG "lists\n" if ($Vars{'lists'} ne "");
print LOG "get $mlist $Vars{'fname'}\n" if ($Vars{'get'} ne "");
print LOG "\nVariables passed into majordomo2\n";
for $key (sort(keys %Vars))
{
printf LOG " %-20.20s %s\n", $key, $Vars{$key};
}
print LOG "Environment variables\n";
for $key (sort(keys %ENV))
{
next if ($key =~ /^SERVER_|PATH|SCRIPT_|CONTENT_|DOCUMENT_ROOT|GATEWAY_INTERFACE/);
next if ($key =~ /^HTTP_ACCEPT|HTTP_CONNECTION|HTTP_HOST/);
printf LOG " %-20.20s %s\n", $key, $ENV{$key};
}
print LOG "\n\n";
close LOG;
}
###
### ParseInfo
###
### The work routines for parsing data.
###
sub ParseInfo
{
my($data) = @_;
my($item, $name, @table, $value);
$data =~ s/\&*\s*$//; # Remove trailing garbage
@table = split(/&/, $data); # Variables split at "&"
for $item (@table)
{
$item = unquote($item);
($name = $item) =~ s/\n//mg;
$name =~ s/=.*//m;
($value = $item) =~ s/^.*?=//;
$Vars{$name} = $value;
}
}
###
### ParseQueryParameters
###
### Read the query string and bust it up just as if it came
### from a form.
###
sub ParseQueryParameters
{
ParseInfo($ENV{'QUERY_STRING'});
}
###
### ParseFormVariables
###
### The variables from a CGI FORM come in on standard input.
### Read this string, and break it up into the Vars associative
### array.
###
sub ParseFormVariables
{
my($data, $item, $name, @tbl, $val);
$data = ;
# print STDERR "The raw data is $data
\n";
$data =~ s/query..=//g;
$data =~ s/&*\s*$//;
@tbl = split(/&/, $data); # Vars separated by &
for $item (@tbl)
{
# Process the variables. Be careful to avoid removing needed characters.
chomp($item = unquote($item));
($name, $val) = split(/=/, $item, 2);
$Vars{$name} = $val;
}
}
###
### printvars
###
### Print the contents of the Vars variable.
###
sub printvars
{
local($key);
print "Variables:
\n";
for $key (sort(keys(%Vars)))
{
print "$key = $Vars{$key}
\n";
}
}
###
### printenv
###
### Display the environment.
### This assumes that we can write on stdout. This may not
### be true if we haven't written the header line yet.
###
sub printenv
{
local(@env, $var);
@env = `printenv`;
for $var (@env)
{
print "$var
\n";
}
}
###
### ReadHotList
###
### Read in a list of Perl regular expressions to compare against the address.
###
sub ReadHotList
{
@HotPattern = ();
if (open(HOT, "<$HotList"))
{
while ()
{
chomp;
s/\s*#.*//;
next if (/^\s*$/);
s/^\s*//;
push(@HotPattern, $_);
}
close HOT;
}
}
###
### SendMail
###
### Send mail to the majordomo server.
###
### The mail needs to appear as if it is from the specified user.
### This is not as needed for the subscribe/unsubscribe, but is
### absolutely required for most commands to get information back
### to the user.
###
### The host is can be specified by the user. Make sure that it doesn't
### have any shell metacharacters.
###
sub SendMail
{
local($email, $host, $mlist);
$email = $Vars{'email'};
$host = $Vars{'host'};
$host =~ s/[^-_.A-Za-z0-9]//g; # Restrict the host name.
# It may be necessary to expand this to include
# other characters. Do so if needed.
$mlist = $Vars{'mlist'};
if (open(MAIL, "|$Mail majordomo\@$host") == 0)
{
print "Cannot start mailer\n";
return;
}
print MAIL "From: $email\n";
print MAIL "To: majordomo\@$host\n";
print MAIL "\n";
print MAIL "subscribe $mlist $email\n" if ($Vars{'subscribe'} ne "");
print MAIL "unsubscribe $mlist $email\n" if ($Vars{'unsubscribe'} ne "");
print MAIL "help\n" if ($Vars{'help'} ne "");
print MAIL "info $mlist\n" if ($Vars{'info'} ne "");
print MAIL "index $mlist\n" if ($Vars{'index'} ne "");
print MAIL "which $email\n" if ($Vars{'which'} ne "");
print MAIL "who $mlist\n" if ($Vars{'who'} ne "");
print MAIL "lists\n" if ($Vars{'lists'} ne "");
print MAIL "get $mlist $Vars{'fname'}\n" if ($Vars{'get'} ne "");
print MAIL ".\n";
close MAIL;
}
###
### unquote
###
### Unescape a CGI form variable.
###
sub unquote
{
my($raw) = @_;
my($code, @pieces, $piece);
$raw =~ s/\+/ /mg;
@pieces = split(/%/, $raw);
for ($piece = 1; $piece <= $#pieces; $piece++)
{
$pieces[$piece] =~ s/^%//;
$code = substr($pieces[$piece], 0, 2);
$code = hex($code);
$pieces[$piece] = sprintf("%c%s", $code, substr($pieces[$piece], 2));
}
return join("", @pieces);
}