#!/s/std/bin/perl -w

# This script tries to "catch" an incoming bookmark file from procmail
# and put it in the links file location.

use strict;

my($Header) = '/var/usr3/chaos/public_html/links.head.html';
my($Footer) = '/var/usr3/chaos/public_html/links.tail.html';
my($TargetFile) = '/var/usr3/chaos/public_html/links.html';
my($TargetFileNoMangle) = '/var/usr3/chaos/public_html/bookmark.htm';
my($TempDir) = '/tmp';

my($Toucher) = '/usr/bin/touch';

# DOS attack detectoin
my($MaxLinesInput) = 1024;
my($MaxLineLength) = 2048;

main();

exit;

sub main()
{
	my($TempFileName) = "$TempDir/FileCatcher.$$.$>.$<.temp";
	open(TEMP, ">$TempFileName")
		or die "Unable to open temp file because of $!\n";

	my($Line);
	my($LineCount) = 0;

	while(defined ($Line = <STDIN>))
	{
		$LineCount++;
		if($LineCount > $MaxLinesInput or
			length($Line) > $MaxLineLength)
		{
			close(TEMP);
			unlink $TempFileName;
			die "Looks like DOS attack!\n";
		}
		print TEMP $Line;
	}
	close(TEMP);

	my($TempFileName2) = "$TempDir/FileCatcher2.$$.$>.$<.temp";

	PGPVerify($TempFileName, $TempFileName2);

	# Success
	CopyFileTranslate($TempFileName2, $TargetFile);
	chmod 0644, $TargetFile;

	CopyFile($TempFileName2, $TargetFileNoMangle);
	chmod 0644, $TargetFileNoMangle;

	unlink $TempFileName;
	unlink $TempFileName2;
}

#======================================================================
sub CopyFile($, $)
{
	my($From, $To) = @_;
	my($Line);

	if(-e $To) { unlink $To; }

	open(FROM, "$From") or die "Unable to copy from '$From' because of '$!'\n";
	open(TO, ">$To") or die "Unable to copy to '$To' because of '$!'\n";

	while(defined ($Line = <FROM>))
	{
		print TO $Line;
	}

	close(TO);
	close(FROM);
}

#======================================================================
sub CopyFileTranslate($, $)
{
	my($From, $To) = @_;
	my($Line);

	my($LocaltimeStr);
	$LocaltimeStr = localtime;

	if(-e $To) { unlink $To; }

	my($InHeader) = 1;

	open(FROM, "$From") or die "Unable to copy from '$From' because of '$!'\n";
	open(TO, ">$To") or die "Unable to copy to '$To' because of '$!'\n";


	open(HEADER, "$Header") or die "Unable to open header '$Header' because of '$!'\n";
	while(defined ($Line = <HEADER>))
	{
		$Line =~ s/TIME_DATE_STAMP_HERE/$LocaltimeStr/;
		print TO "$Line";
	}
	close(HEADER);


	while(defined ($Line = <FROM>))
	{
		if($InHeader)	# skip the header.
		{
			if($Line =~ /<DL>/) { $InHeader = 0; }
			else				{ next; }
		}
		print TO TranslateNetscape($Line);
	}

	open(FOOTER, "$Footer") or die "Unable to open footer '$Footer' because of '$!'\n";
	while(defined ($Line = <FOOTER>)) { print TO "$Line"; }
	close(FOOTER);

	close(TO);
	close(FROM);

#Netscape seems to have problems detecting newer versions if
# it grabs a copy mid-update.  Maybe this will fix it....
	system("$Toucher $To");
}


#======================================================================
sub PGPVerify($, $)
{
	my($TempFileName, $TempFileName2) = @_;

	# We need to capture STDERR to suppress unneeded procmail log messages.
    open(OLDERR, ">&STDERR");
	open(STDERR, ">&STDOUT") or die "Cannot duplicate STDOUT!\n";

	my(@PGPOut) = `/s/std/bin/pgpv +OutputInformationFD=1 +BatchMode=1 -o $TempFileName2 $TempFileName`;

	open(STDERR, ">&OLDERR");

	if(0) { close(OLDERR); } # Suppress warning.

	my($LineNum) = 0;
	my($InSig) = 0;

	while($LineNum < $#PGPOut)
	{
		my($Line) = $PGPOut[$LineNum];
		if($InSig)
		{
			if($InSig == 1)
			{
				if(!($Line =~ /Key ID KEYID/)) { BadSigDie(@PGPOut); }
			}
			elsif($InSig == 2)
			{
				if(!($Line =~ /"KEY NAME HERE <USERNAME@ADDRESS>"/))
					{ BadSigDie(@PGPOut); }
				$LineNum = $#PGPOut;
			}
			$InSig++;
		}
		else
		{
			if($Line =~ /Good signature made .+ by key:/)
				{ $InSig++; }
		}
		$LineNum++;
	}

	if(!$InSig)
	{
		BadSigDie(@PGPOut);
	}

}

#======================================================================
sub BadSigDie
{
	print STDERR <<_EOERROR;
An error occured while verifying a signature.  Info:
@_
_EOERROR
	die;
}


sub TranslateNetscape($)
{
	$_ = $_[0];
	s/<H3 (FOLDED )?(NEWITEMHEADER )?ADD_DATE="\d+">//o;
	s/<\/H3>//o;
	s/<DD>/ -- /o;
	s/<DL><p>/<DL>/o;
	s/<\/DL><p>/<\/DL>/o;
	s/<DL>/<UL>/o;
	s/<\/DL>/<\/UL>/o;
	s/<DT>/<LI>/o;
	return $_;
}
