#!/usr/bin/perl -- ############################################################################ # Soupermail Install Helper # # Internal build version: # $Id: souperinstall.pl,v 1.19 2001/02/07 08:31:30 aithalv Exp $ # # Something to take the pain out of installing Soupermail # Copyright (C) 2000, 2001 # Vittal Aithal # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See # the GNU General Public License for more details. You should have received # a copy of the GNU General Public License along with this program; if not, # write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, # MA 02139, USA. # ############################################################################ use CGI qw(:standard); use CGI::Carp qw(); #fatalsToBrowser); use FileHandle; use Config; use Socket; use strict; my $site = "http://soupermail.sourceforge.net/"; my $faq = "${site}faq.html"; my $targ = ' target="faq"'; my $make = param('make') ? 1 : 0; my $scrName = "soupermail.pl"; $| = 1; print ($make ? header(-Content_type =>"text/plain;name=$scrName", -Content_disposition=>"file;filename=$scrName") : header()); my @dirList = (); # where to look for the finder file my $dirCount = 0; # how many directories we've looked in my $cf = {}; # things to look for $cf->{'perl'} = $Config{'perlpath'}; # perl binary my $maxDirs = 100; # the maximum number of directories to look in my $maxBinDirs = 400; # the maximum number of bin directories to look in my @path = (); # common paths for binaries my $srv = ""; # web server type my $os = ""; # operating system my $fhBug = "0"; # file handle bug my @tmpList = (); # common temp directories my $dirCmd = ""; # how to find out the current directory my $srvRoot = ""; # the $serverRoot my $pvtRoot = ""; # the $privateRoot my $cgiPath = ""; # Where the CGI program is installed my $mimeOk = 0; # is MIME::Lite available my $dbiOk = 0; # is DBI available my $binFiles = {}; # what binaries to look for my $findfile = param('findfile') ? param('findfile') : "souperfinder.htm"; my $findFilePath = ""; # if the find file is in a sub directory if ($findfile =~ s#^(.*/)([^/]+)$#$2#) { $findFilePath = $1; } my $forkable = $Config{'d_fork'} eq "define"; # whether we can fork my $mailUser = ""; my $paranoid = param('paranoid') ? 1 : 0; if ($make) { $cgiPath = param('cgi'); my $sr = param('srvroot'); my $pr = param('pvtroot'); $cf->{'mprog'} = param('mailprog'); $cf->{'mhost'} = param('mailserver'); $cf->{'gpg'} = param('gpg'); $cf->{'pgp5'} = param('pgp5'); $cf->{'pgp2'} = param('pgp2'); $cf->{'lout'} = param('lout'); $cf->{'ps2pdf'} = param('ps2pdf'); $cf->{'tmp'} = param('temp'); $cf->{'email'} = param('email'); $cf->{'perl'} = param('perl'); $forkable = param('forkable'); $fhBug = param('fhbug'); my $soupermail = ""; if (-f "${cgiPath}/$scrName" && -r "${cgiPath}/$scrName") { $soupermail = "${cgiPath}/$scrName"; } elsif (!-f "${cgiPath}/$scrName") { die "Couldn't find $scrName in $cgiPath"; } elsif (!-r "${cgiPath}/$scrName") { die "Couldn't read $scrName in $cgiPath"; } $| = 1; my $line = 0; my $done = 0; open (SOUP, "<$soupermail") || die "Couldn't open $soupermail: $!"; while () { if (!$line && $os eq "unix") { s/#!.*/#!$cf->{perl} --/; } unless ($done) { s/^\s*use\s+lib\s+qw\(\.\)/use lib qw\(\. $cgiPath\)/; s/^\s*\$serverRoot\s*=.*/\$serverRoot = '${sr}';/; s/^\s*\$privateRoot\s*=.*/\$privateRoot = '${pr}';/; s/^\s*\$mailprog\s*=.*/\$mailprog = '$cf->{mprog}';/; s/^\s*\$mailhost\s*=.*/\$mailhost = '$cf->{mhost}';/; s/^\s*'gpg'\s*=>.*/'gpg' => '$cf->{gpg}',/; s/^\s*'pgp2'\s*=>.*/'pgp2' => '$cf->{pgp2}',/; s/^\s*'pgp5'\s*=>.*/'pgp5' => '$cf->{pgp5}',/; s/^\s*\$lout\s*=.*/\$lout = '$cf->{lout}';/; s/^\s*\$ps2pdf\s*=.*/\$ps2pdf = '$cf->{ps2pdf}';/; s/^\s*\$tempDir\s*=.*/\$tempDir = '$cf->{tmp}\/';/; s/^\s*\$fhBug\s*=.*/\$fhBug = '$fhBug';/; s/^\s*\$forkable\s*=.*/\$forkable = '$forkable';/; s/^\s*\$soupermailAdmin\s*=.*/\$soupermailAdmin = '$cf->{email}';/; s/^\s*\$paranoid\s*=.*/\$paranoid = $paranoid;/; (/#\s+Other\s+global/) && ($done = 1); } print; } close(SOUP); exit; } # Try and determine the server software $_ = $ENV{"SERVER_SOFTWARE"}; unless ($make) { print<<"END_OF_HEADER"; Soupermail Installer Results

Soupermail Installer Helper

Below is some diagnostic information that can be used to help install Soupermail.

Text displayed in GREY is diagnostic information, which you can ignore (even if it says software error).

Text written in BLUE contains information messages that you should read. However they are NOT critical.

Text written in RED is critical, and contains information you MUST act on.


END_OF_HEADER print "Webserver $_\n"; } if (/\bapache\b/i) { $srv = "apache"; } elsif (/\biis\d/i) { $srv = "iis"; } elsif (/\b(netscape|iplanet)\d/i) { $srv = "ns"; } # try and determine the OS $_ =$^O; if (/\bmswin/i) { $os = "win"; } elsif (/bsd/i) { $os = "unix"; $fhBug = 1; } elsif (/\b(.in.x|\w+ix|sunos|solaris)/i) { $os = "unix"; } (!$make) && print "
Perl $]\n"; if ($os eq "unix") { (!$make) && print "
Operating system UNIX ($^O)\n"; @path = qw(/usr/local/bin /usr/bin /bin /usr/local/share/bin); @tmpList = qw(/var/tmp /tmp /usr/tmp); $dirCmd = "/bin/pwd"; $mailUser = "root"; my @smDirs = qw(/usr/lib /var/lib /usr/local/lib /usr/local/bin /usr/sbin /sbin); while (!$cf->{'mprog'} && ($_ = shift (@smDirs))) { if (-f "$_/sendmail" && -x "$_/sendmail") { $cf->{'mprog'} = "$_/sendmail"; } } $binFiles = { 'pgp' => 'pgp2', 'pgpe' => 'pgp5', 'gpg' => 'gpg', 'ps2pdf' => 'ps2pdf', 'lout' => 'lout' }; } elsif ($os eq "win") { (!$make) && print "
Operating system Windows ($^O)\n"; @path = ("c:/program files", "d:/program files", "c:/", "d:/", "e:/", "f:/"); @tmpList = qw(c:/temp d:/temp c:/tmp d:/tmp c:/winnt/temp c:/windows/temp c:/winnt40/temp); $dirCmd = "cd"; $mailUser = "administrator"; $binFiles = { 'pgp.exe' => 'pgp2', 'pgpe.exe' => 'pgp5', 'gpg.exe' => 'gpg', 'ps2pdf.bat' => 'ps2pdf', 'lout.exe' => 'lout' }; } # find the temp directory while ($_ = shift @tmpList) { if (-d $_ && -w $_) { $cf->{'tmp'} = $_; last; } } # try and figure out where we're being called from if ($0) { my $cgi = $0; (!$make) && print "
Found \$0 $cgi\n"; $cgi =~ s#\\#/#g; if ($cgi =~ m#/#) { $cgi =~ s#/([^/]*)$##; $cgiPath = $cgi; my @cgi = split(m#/#, $cgi); my $buildPath = ""; $buildPath = shift(@cgi); if ($os ne "win") { $buildPath .= "/" . shift(@cgi); } while (my $p = shift(@cgi)) { $buildPath .= "/$p"; unshift(@dirList, $buildPath); } } } else { (!$make) && print "
Didn't find \$0\n"; } # see if we can find the document root if ($dirCmd) { my $startDir = ""; open(DC, "$dirCmd |"); $_ = ; chomp; $startDir = $_; close (DC); $startDir =~ s#\\#/#g; (!$make) && print "
Found starting directory $startDir\n"; my $startPath = $startDir; my @cgi = split(m#/#, $startDir); my $depth = ($startDir =~ tr#/#/#); my $buildPath = ""; if ($depth > 2) { $buildPath = shift(@cgi); $buildPath .= "/" . shift(@cgi); } my $p; foreach $p (@cgi) { $buildPath .= "/$p"; $buildPath =~ s#/+#/#g; (!$make) && print "
paths... $buildPath\n"; unshift(@dirList, $buildPath); } (!$make) && print "
Environment DOCUMENT_ROOT is: $ENV{DOCUMENT_ROOT}\n"; push(@dirList, $ENV{'DOCUMENT_ROOT'}); (!$make) && print "
Installer searching these paths... " . join(", ", @dirList); searchForPage(); if ($srvRoot) { $srvRoot =~ /^(.*[\/\\])/; $pvtRoot = "${1}private"; } } my $soupermail = "$cgiPath/$scrName"; if (-f "$soupermail") { (!$make) && print "
Found $scrName $soupermail\n"; } # Stop local errors being sent to the browser (???) $SIG{__WARN__} = sub { }; # Look for MIME::Lite (!$make) && print "
Looking for the required perl module MIME::Lite\n"; eval("use lib qw(. $cgiPath);\nuse MIME::Lite;"); if ($@) { print<<"EOT";

Trouble, the MIME::Lite module doesn't seem to be installed. Install it on the webserver before proceeding. See the MIME::Lite section of install.txt included with Soupermail and read ${faq}#mimelite, the MIME::Lite section of the FAQ, for instructions.
EOT } else { (!$make) && print "
Found the MIME::Lite module\n"; $mimeOk = 1; } # Look for DBI (!$make) && print "
Looking for the optional perl module DBI\n"; eval("use lib qw(. $cgiPath);\nuse DBI;"); if ($@) { print<<"EOT";

It doesn't look like DBI is available on your server. This means that you won't be able to use Soupermail's database features. Please read ${faq}#dbi, the DBI section of the FAQ, for more information. If you are not going to use Soupermail's database features, you can safely ignore this message.
EOT } else { (!$make) && print "
Found the DBI module\n"; $dbiOk = 1; } (!$make) && print "
Looking for a mailserver\n"; eval("use lib qw(. $cgiPath);\nuse Net::SMTP;"); if ($@ && !$cf->{'mprog'}) { print<<"EOT";
Trouble, the Net::SMTP module doesn't seem to be installed. Install it on the webserver before proceeding. See the last section of install.txt included with Soupermail and read ${faq}#libnet, the Net::SMTP section of the FAQ, for instructions. EOT } elsif (!$@) { (!$make) && print "
Found the Net::SMTP module\n"; my @hosts = qw(localhost mail-fwd relay smtp mail mailhost relay1 smtp-relay mail-relay imap); (param('mailserver')) && unshift(@hosts, param('mailserver')); (!$make) && print "
Looking through these mailservers " . join(", ", @hosts) . "\n"; while (my $mhost = shift(@hosts)) { if ($mhost =~ /^[\w\d\-]+(\.[\w\d\-]+)*$/) { if (checkMailHost($mhost)) { $cf->{mhost} = $mhost; (!$make) && print "
Found mail server $mhost\n"; last; } } else { $mhost =~ s//>/g; print "
Trouble, the mail server name $mhost doesn't look valid.\n"; } } } (!$make && $cf->{'mprog'}) && print "
Found mail program $cf->{mprog}\n"; searchForBins(); my $fh = new FileHandle; if ($soupermail && -f $soupermail && -r $soupermail) { if ($fh->open("< $soupermail")) { $fhBug = ! (eval("-T \$fh")); } $fh->close(); } elsif ($cf->{'tmp'}) { my $tmpFile = "$cf->{tmp}/itmp$$" . time; $fh->open("> $tmpFile"); $fhBug = ! (eval("-T \$fh")); $fh->close(); unlink $tmpFile; } else { print "
Cannot determine \$fhBug: setting to 1 for safety\n"; $fhBug = 1; } if (param('email')) { my $e = param('email'); my $goodCh = '\w\d\-\.\,\/\xc0-\xd6\xd8-\xf6\xf8-\xff'; if ($e =~ /^[${goodCh}]+\@[$goodCh]+(\.[${goodCh}]+)*$/) { $cf->{'email'} = $e; } else { if (server_name()) { makeMail(); } } } elsif (server_name()) { makeMail(); } unless ($make) { print "
Server name " . server_name() . "\n"; print "
Server IP $ENV{SERVER_ADDR}\n"; print "
Server Port $ENV{SERVER_PORT}\n"; print "
Called From $ENV{HTTP_REFERER}\n"; print "
Path Info $ENV{PATH_INFO}\n"; print "
Path Translated $ENV{PATH_TRANSLATED}\n"; print "
Install Script $0\n"; print "
Postscript to PDF " . $cf->{'ps2pdf'} . "\n"; print "
Lout " . $cf->{'lout'} . "\n"; print "
Temp area " . $cf->{'tmp'} . "\n"; print "
Perl " . $cf->{'perl'} . "\n"; print "
GPG " . $cf->{'gpg'} . "\n"; print "
PGP2 " . $cf->{'pgp2'} . "\n"; print "
PGP5 " . $cf->{'pgp5'} . "\n"; print "
Server Root $srvRoot\n"; print "
Expanded Server Root " . expandSymlinks($srvRoot) . "\n"; print "
Assumed Private Root $pvtRoot\n"; print "
FileHandle bug $fhBug\n"; print "
Admin email $cf->{email}\n"; print "\n

Done\n"; if ($srvRoot && $soupermail && $cf->{'tmp'} && $mimeOk && ($os eq "win" ||($os eq "unix" && $cf->{'perl'})) && ($cf->{'mprog'} || $cf->{'mhost'})) { if (-f "${cgiPath}/$scrName" && -r "${cgiPath}/$scrName") { print "


Excellent! Your settings are OK to make a custom install. " . "Press the button below to generate a copy of Soupermail for " . "your server. The customised script will be returned to your " . "browser and you should Save it to file once its downloaded. " . "
\n" . "\n" . "\n" . "\n" . "{mhost}\">\n" . "{mprog}\">\n" . "{email}\">\n" . "{perl}\">\n" . "{gpg}\">\n" . "{pgp2}\">\n" . "{pgp5}\">\n" . "\n" . "{tmp}\">\n" . "{ps2pdf}\">\n" . "{lout}\">\n" . "\n" . "\n" . "\n" . "\n" . "
\n" . "If you would like to edit $scrName yourself, these are the " . "values to use:

"; } else { print "


The installer cannot fully read the copy " . "of $scrName installed on your server, so use the " . "values below to finish your installation.

\n"; } printValues(); print "

Once you have successfully installed " . "soupermail, remove the installer files (script and HTML file). ". "THIS IS IMPORTANT as it will stop people from seeing " . "your server configuration and you won't interfere with other " . "people installing Soupermail.

\n"; } else { print <<"END_OF_WARNING";


There was not enough information to make a custom installation of Soupermail. See if there are any errors reported above and try and correct them.

However, I did determine the following information:

END_OF_WARNING printValues(); } print "


\n\n" . "
(c) Vittal Aithal <" . "" . "vittal.aithal\@bigfoot.com> 2000, 2001\n" . "" . "" . "${site}
\n" . "In case of trouble, you MUST read this -> " . "". "${faq}
"; } exit; sub searchForPage() { my $d; my %dirCache; OUTER: while ($d = shift(@dirList)) { next if $dirCache{$d}; last if ($dirCount > $maxDirs); $dirCache{$d} = 1; opendir (D, $d); $dirCount++; my @dirs = (); if ($os eq "win") { @dirs = grep { /^[^\.]/ && ((-f "$d/$_" && /^${findfile}$/i) || (-d "$d/$_")) } readdir(D); } else { @dirs = grep { /^[^\.]/ && ((-f "$d/$_" && /^${findfile}$/) || (-d "$d/$_")) } readdir(D); } while ($_ = shift(@dirs)) { if (-f "$d/$_") { $srvRoot = "$d"; if (open (F, "$d/$_")) { (!$make) && print "
Can open $d/$_"; close(F); if ($findFilePath) { $srvRoot =~ s#${findFilePath}$##; } } else { (!$make) && print "
Can not open $d/$_, checking for symlinks..."; my $sd = expandSymlinks("$d/$_"); (!$make) && print "
Expanded symlinks to $sd"; if (open (F, "$sd")) { (!$make) && print "
Can open $sd"; close(F); if ($findFilePath) { $srvRoot =~ s#${findFilePath}$##; $srvRoot = expandSymlinks($srvRoot); } } } last OUTER; } elsif (!$dirCache{"$d/$_"} && -r "$d/$_") { push(@dirList, "$d/$_"); } } } } # Some systems don't like us reading down symlinks, so should expand them sub expandSymlinks { my $origPath = shift; return $origPath if ($os ne "unix"); my @pathList = split(m!/!, $origPath); my $newPath = ""; while (@pathList) { my $part = shift(@pathList); $newPath .= "/" . $part; # See if the path we're now at is a symlink if (my $lnk = readlink($newPath)) { if ($lnk =~ m!^/!) { $newPath = $lnk; } else { $newPath .= "/../$lnk"; } } } $newPath =~ s!/+!/!g; while ($newPath =~ s![^/]+/\.\./!!) {} return $newPath; } sub searchForBins() { $| = 1; my $d; my %dirCache; my %fileCache = (); my $bins = join("|", keys %$binFiles); my $binCnt = 0; my $maxBin = scalar(keys %$binFiles); $bins =~ s/([\.\[\]\(\)\-\?\*\+])/\\$1/g; $dirCount = 0; OUTER: while ($d = shift(@path)) { next if $dirCache{$d}; last if ($dirCount > $maxBinDirs); $dirCache{$d} = 1; opendir (D, $d); $dirCount++; my @dirs = (); if ($os eq "win") { @dirs = grep { /^[^\.]/ && ((-f "$d/$_" && /^${bins}$/i) || (-d "$d/$_")) } readdir(D); } else { @dirs = grep { /^[^\.]/ && ((-f "$d/$_" && /^${bins}$/) || (-d "$d/$_")) } readdir(D); } while ($_ = shift(@dirs) ) { if (-f "$d/$_" && !$fileCache{$_}) { $fileCache{$_} = 1; $cf->{$binFiles->{$_}} = "$d/$_"; $binCnt++; if ($binCnt >= $maxBin) { last OUTER; } } elsif (!$dirCache{"$d/$_"} && -r "$d/$_") { push(@path, "$d/$_"); } } } } sub checkMailHost { my $mhost = shift; my $proto = getprotobyname('tcp'); socket(Socket_Handle, PF_INET, SOCK_STREAM, $proto); my $port = getservbyname('smtp', 'tcp'); my $iaddr = $mhost; if ($iaddr =~ /[^\d\.]/) { my @iaddrs = gethostbyname($mhost); $iaddr = join(".", unpack("CCCC", $iaddrs[4])); } elsif ($iaddr !~ /^\d+\.\d+\.\d+\.\d+$/) { return 0; } return 0 unless ($iaddr); print "\n
Got address $iaddr\n"; my $sin = sockaddr_in($port,inet_aton($iaddr)); my $smtpCon = new Net::SMTP($iaddr, Debug=>10); if ($smtpCon) { print "
Made SMTP connection to $iaddr" . $smtpCon->banner() . "\n"; $smtpCon->quit(); return 1; } else { return 0; } } sub makeMail { if ($ENV{'SERVER_ADMIN'} && $ENV{'SERVER_ADMIN'} !~ /\@localhost$/i) { $cf->{'email'} = $ENV{'SERVER_ADMIN'}; return 1; } my $domain = server_name(); if ($domain =~ s/^w+(\d*)\.//i) { $cf->{'email'} = "postmaster\@$domain"; } else { $cf->{'email'} = "${mailUser}\@$domain"; } return 1; } sub printValues { if ($cf->{'perl'} && $os eq "unix") { print "Your script should start with #!$cf->{perl} --
\n"; } if ($cf->{'email'}) { print "\$soupermailAdmin = '$cf->{email}';
\n"; } if ($srvRoot) { print "\$serverRoot = '$srvRoot';
\n"; } else { print "You need to find out what \$serverRoot is
\n"; } if ($pvtRoot) { print "\$privateRoot is assumed to be '$pvtRoot' but please check
\n"; } if ($cf->{'mprog'} && $os eq "unix") { print "\$mailprog = '$cf->{mprog}';
\n"; } if ($cf->{'mhost'}) { print "\$mailhost = '$cf->{mhost}';
\n"; } if ($cf->{'gpg'}) { print " 'gpg' => '$cf->{gpg}',
\n"; } if ($cf->{'pgp2'}) { print "You should set 'pgp2' => '$cf->{pgp2}',
\n"; } if ($cf->{'pgp5'}) { print "'pgp5' => '$cf->{pgp5}',
\n"; } if ($cf->{'lout'} && $cf->{'ps2pdf'}) { print "\$lout = '$cf->{lout}';
\n"; print "\$ps2pdf = '$cf->{ps2pdf}';

\n"; } if ($cf->{'tmp'}) { print "\$tempDir = '$cf->{tmp}/';
\n"; } else { print "You need to find out what \$tempDir is
\n"; } if ($forkable) { print "\$forkable = 1;
\n"; } else { print "You should set \$forkable to 0
\n"; } if ($fhBug) { print "\$fhBug = 1;
\n"; } else { print "You should set \$fhBug to 0
\n"; } print "\$paranoid = $paranoid;
\n"; print "

Support requests to the Help Forum " . "MUST include ALL the information on this " . "page and YOU MUST HAVE READ the FAQ.

"; } # vim: ts=4