#!/usr/bin/perl

sub usage;
sub verbose;
sub error;
sub bad;
sub read;
sub write;
sub html;

use Getopt::Std;

use vars qw ($opt_c,$opt_h,$opt_v);

getopts('c:vh');

$maxparams = 46;

if(!$opt_c || !opt_h)
{
	&usage;
}

if($opt_c eq "")
{
	&usage;
}
else
{
	$file = $opt_c;
}

if($opt_v)
{
	$vb = 1;
}

if($UID != 0)
{
	print "You must be root!\n";
	exit(-1);
}
if($UID eq $>)
{
	print "san.check must run under a different UID than root!\n";
	print "The owner must be the UID of your mailserver and it\n";
	print "must be set to suid permissions!\n";
	print "Example: -rwsr-s---   1 daemon daemon     san.check\n";
	exit(-1);
}


&verbose( "Effective UID:  $>");

%option = (	"SENDERsmtp" 	=> "",
		"ADMIN"      	=> "",
		"TOsmtp"	=> "",
		"CCsmtp"	=> "",
		"Allow_From"	=> "",
		"AUTH_CODE"	=> "",
		"TEMPLATE"	=> "",
		"OUTPUT"	=> "",
		"STORE"		=> "",
		"UseHTML"	=> "",
		"CRLF"		=> "",
		"ITEM_HEAD"	=> "",
		"ITEM_FOOT" 	=> "",
		"Field1"	=> "",
		"Field2"	=> "",
		"Field3"	=> "",
		"Field4"	=> "",
		"Mailto"	=> "",
		"Date_HEAD"	=> "",
		"Date_FOOT"	=> "",
		"Subject_HEAD"	=> "",
		"Subject_FOOT"	=> "",
		"From_HEAD"	=> "",
		"From_FOOT"	=> "",
		"Text_HEAD"	=> "",
		"Text_FOOT"	=> "",
		"SPAMPROTECT"	=> "",
		"ARCHIV"	=> "",
		"Archiv_Output"	=> "",
		"Archiv_Template" => "",
		"Archiv_Store"	=> "",
		"Archiv_MAXITEMS" => "",
		"Cron_TEMPL"	=> "",
		"Cron_OUTPATH"	=> "",
		"Cron_Hist"	=> "",
		"Cron_HEAD"	=> "",
		"Cron_FOOT"	=> "",
		"Archiv_Title_Head" => "",
		"Archiv_Title_Foot" => "",
		"LookDetail" 	=> "",
		"Detail_TEMPL"	=> "",
		"Detail_PATH"	=> "",
		"Detail_LINK"	=> "",
		"Detail_HEAD"	=> "",
		"Detail_FOOT"	=> "");

$countparams = 0;

# read the config-file!
&verbose("open $file");
if(! -r $file )
{
	&error("Could not read $file!");
}
else
{
	open FILE, "< $file" or die &error("Could not read $file!");
	while(<FILE>)
	{
		chomp $_;
		$line++;
		if($_ !~ /^#/ && $_ !~ /^\s/ && $_ !~ /^\t/ && $_ ne "")
		{
			# no comment, a standard config line!
			@param = split(/\s/, $_);
			$option{$param[0]} = $param[1];	
			&verbose("Line $line: $param[0] => \"$param[1]\"");
			$countparams++;	
		}
	}
	close FILE;
}
if($countparams != $maxparams)
{
	&bad("wrong number of options: \n$maxparams expected and $countparams found.\nYou can change it in line 17 if you have an older version of htnews.");
}
else
{
	&verbose("number of options: $countparams - ok.");
}

# start checking...


&verbose("checking read permissions...");

if($option{"Allow_From"} ne "")
{
	&read($option{"Allow_From"},"Allow_From");
} 
	&read($option{"TEMPLATE"},"TEMPLATE");
if($option{"ARCHIV"} eq "YES")
{
        &read($option{"Archiv_Template"},"Archiv_Template");
}
if($option{"Cron_TEMPL"} ne "")
{
	&read($option{"Cron_TEMPL"},"Cron_TEMPL");
}
if($option{"LookDetail"} eq "YES")
{
	&read($option{"Detail_TEMPL"},"Detail_TEMPL");
}


&verbose("checking write permissions...");

&write($option{"OUTPUT"},"OUTPUT");
&write($option{"STORE"},"STORE");
if($option{"ARCHIV"} eq "YES")
{
	&write($option{"Archiv_Output"},"Archiv_Output");
	&write($option{"Archiv_Store"},"Archiv_Store");
}
if($option{"Cron_OUTPATH"} ne "")
{
	&write($option{"Cron_OUTPATH"} . "san.cron.testfile","Cron_OUTPATH");
	&write($option{"Cron_Hist"},"Cron_Hist");
}
if($option{"LookDetail"} eq "YES")
{
	if($option{"Detail_PATH"} eq "")
	{
		&bad("option Detail_PATH has no value, but is required");
	}
	else
	{
		&write($option{"Detail_PATH"} . "san.detail.testfile","Detail_PATH");
	}
}

&verbose("checking email-addresses...");
if($option{"SENDERsmtp"} !~ /[\@\.]/)
{
	if($option{"SENDERsmtp"} eq "")
	{
		&bad("option SENDERsmtp has no value, but is required");
	}
	else
	{
		&bad($option{"SENDERsmtp"} . " is not a valid email-address(option SENDERsmtp)");
	}
}
if($option{"ADMIN"} !~ /[\@\.]/)
{
	if($option{"ADMIN"} eq "")
	{
		&bad("option ADMIN has no value, but is required");
	}
	else
	{
		&bad($option{"ADMIN"} . " is not a valid email-address(option ADMIN)");
	}
}
if($option{"TOsmtp"} ne "" && $option{"TOsmtp"} !~ /[\@\.]/)
{
	if($option{"TOsmtp"} ne "/dev/null")
	{
		&bad($option{"TOsmtp"} . " is not a valid email-address(option TOsmtp)");
	}
}
if($option{"CCsmtp"} ne "" && $option{"CCsmtp"} !~ /[\@\.]/)
{
	&bad($option{"CCsmtp"} . " is not a valid email-address(option CCsmtp)");
}

&verbose("checking field order...");
if($option{"Field1"} ne "Text" && $option{"Field2"} ne "Text" && $option{"Field3"} ne "Text" && $option{"Field4"} ne "Text")
{
	&bad("option FieldX contains no value \"Text\"");
}

&verbose("checking various values...");
if($option{"ARCHIV"} eq "YES")
{
	if($option{"Archiv_MAXITEMS"} eq "")
	{
		&bad("option Archiv_MAXITEMS has no value, but is required");
	}
	elsif($option{"Archiv_MAXITEMS"} !~ /\d/)
	{
		&bad("option Archiv_MAXITEMS is not a digit");
	}
}


exit(0);


sub usage
{
print qq~
Usage: 	sanity_check [-v] {-c configfile} | {-h}
	Checks a htnews 0.6.5+ configfile for errors
	and checks permissions for the specified
	files and directories.
	Options:
	-v	Verbose output, more informative
	-c	htnews configfile to check
	-h	help message

~;
exit(-1);
}

sub verbose
{
	if($vb)
	{
		print "  san.check VERBOSE: " . $_[0] . "\n";
	}
}

sub error
{
	print "  san.check ERROR  : \"" . $_[0] . "\"\n";
	exit(-1);
}

sub bad
{
	print "  san.check PROBLEM: \"" . $_[0] . "\".\n";
}

sub read
{
	if($_[0] eq "")
	{
		&bad("option $_[1] has no value, but is required");
	}
	elsif($_[0] !~ /^\//)
	{
		&bad("$_[0] is not a valid UNIX-path(option $_[1])");
	}
	elsif($_[0] =~ /$\//)
	{
		&bad("$_[0] seems to be a directory, file expected(option $_[1])");
	}
	else
	{
		if( ! -r $_[0] )
		{
			&bad("Could not read $_[0](option $_[1])");
		}
	}
}

sub write
{
	if($_[0] eq "")
        {
                &bad("option $_[1] has no value, but is required");
        }
        elsif($_[0] !~ /^\//)
        {
                &bad("$_[0] is not a valid UNIX-path(option $_[1])");
        }
        elsif($_[0] =~ /$\//)
        {
                &bad("$_[0] seems to be a directory, file expected(option $_[1])");
        }
        else
        {
                if( ! -w $_[0] )
                {
                        &bad("Could not read $_[0](option $_[1])");
                }
        }
}


sub html
{
}
