#!/usr/bin/perl -w

# Skrypt do dekompresji artykuw do spoola leafnode
#
# Andrzej Radecki <radecki@wpk.p.lodz.pl>
#
# Ostatnie zmiany: 14.08.2001r.

use strict;
use Feeder::feeder;


my $n		= 0;
my $hostname	= scalar(gethostent);#"localhost.localdomain";
my (@paczki, %args);
my %nowe_numery;
my %history;
my %grouplist; #leafnode'owy plik 'active'+'newsgroups'

my $spooldir	= $Feeder::feeder::spooldir;
my $paczka	= $Feeder::feeder::paczka;
#my %numery	= %Feeder::feeder::numery;
my $groupinfo = "$spooldir/leaf.node/groupinfo";

die "Can't find file $paczka\n" unless (-f $paczka);

read_groupinfo(\%grouplist);
read_history(\%history); #z owerwiuw

print "Decompressing file \"$paczka\"\n";
local $/="\r\n\r\n";			#tylko naglowki
open (PACZKA, "$Feeder::feeder::uncompr") or die "! $paczka: $!";
while (my $head = <PACZKA>) {
	$n++;
	$head =~ s#\r\n#\n#g; #potrzebne czy nie?
	$head =~ s#\n\s+# #g;

	$head =~ /^Xref: (.+)$/m or do {warn "Can't find \"Xref\" header in article $n\n"; next};
	my $xref = $1;
	$head =~ /^Message-ID: (.+)$/m or do {warn "Can't find \"Message-ID\" header in article $n\n"; next};
	my $msgid = $1;
	
	if (defined($history{$msgid})) { # ten artyku juz mamy
		print "rejecting: $msgid\n";
		local $/="\r\n.\r\n";
		<PACZKA>;
		local $/="\r\n\r\n";
		next; #czytamy nastpny post
	}
	
#	print $xref, "\n";
#	print $msgid, "\n";

	my @xref = split(' ', $xref);
	shift(@xref);
#	print @xref, "\n";
	%nowe_numery = ();
	foreach (@xref) {
		my ($gr, $nr) = split (':', $_);
		$grouplist{$gr}[0]++;
		$nowe_numery{$gr} = $grouplist{$gr}[0];
#		print "$msgid -> $gr:$nowe_numery{$gr}\n";
		$Feeder::feeder::numery{$gr}=$nr if (defined($Feeder::feeder::numery{$gr}) && $Feeder::feeder::numery{$gr} < $nr);
	}
#	print %nowe_numery,"\n";

	local $/="\r\n.\r\n";			#reszta postu
	my $body = <PACZKA>;
	$body =~ s#\r\n#\n#g; $body =~ s/\.\n$//;
	$body =~ s#^\.(.*)$#$1#gm;	#mafia kropkowa dziaa!
	local $/="\r\n\r\n";			#tylko naglowki

	store($msgid, \$head, \$body, \%nowe_numery);
	
	my ($subject, $from, $date, $references, $lines);
	$head =~ /^Subject: (.*)$/m;
	if (defined($1)) {$subject = $1} else {$subject = ''};
	$head =~ /^From: (.*)$/m;
	if (defined($1)) {$from = $1} else {$from = ''};
	$head =~ /^Date: (.*)$/m;
	if (defined($1)) {$date = $1} else {$date = ''};
	$head =~ /^References: (.*)$/m;
	if (defined($1)) {$references = $1} else {$references = ''};
	$head =~ /^Lines: (.*)$/m;
	if (defined($1)) {$lines = $1} else {$lines = ''};
	
	#zapisujemy .overview
	foreach my $group (keys(%nowe_numery)) {
		my $tmp = $group;
		$tmp =~ s#\.#/#g;
		my $overview = "$spooldir/$tmp/.overview";
		mkdirhier ("$spooldir/$tmp");
		open (OV, ">>$overview") or die "Can't open file $overview: $!\n";
			print OV "$nowe_numery{$group}\t$subject\t$from\t$date\t$msgid\t$references\t\t$lines\t";
			print OV "Xref: $hostname";
			foreach (keys(%nowe_numery)) {print OV " $_:$nowe_numery{$_}"}
			print OV "\n";
			
		close OV or warn "Can't close file $overview: $!\n";
	}
}

close PACZKA or warn "Nie moge zamknac $paczka: $!";
print "\t", $n, "\t$paczka\n";


#aktualizujemy groupinfo
print "Updating groupinfo & groups file\n";
mkdirhier("$spooldir/leaf.node");
open (GI, ">$groupinfo") or die "Can't open file $groupinfo: $!\n";
foreach my $grupa (sort(keys(%grouplist))) {
	print GI "$grupa ";
	if (defined($nowe_numery{$grupa})) {print GI $nowe_numery{$grupa}}
	else {print GI @{$grouplist{$grupa}}[0]}
	my @tmp = ('1', '0', '-x-');
	for my $i (1..3) {
		if (defined(@{$grouplist{$grupa}}[$i])) {print GI " @{$grouplist{$grupa}}[$i]"}
		else {print GI " $tmp[$i-1]"};
	}
	print GI "\n";
}
close GI or warn "Can't close file $groupinfo: $!\n";


movepack();
updategroups();


####	END


sub store { # $msgid, \@headers, \$body, \%nowe_numery
	my $msgid = $_[0];
	my %groups = %{$_[3]};
	my @groups = keys(%groups);

	my $group = shift @groups;
#	print %groups, "\n";
	my $tmp = $group;
	my $xref;
	
	$xref = "Xref: $hostname";
	foreach (keys(%groups)) {$xref .= " $_:$groups{$_}"}
	$xref .= "\n";

	#zapisujemy artykul
	$tmp =~ s#\.#/#g;
	
	
	my $origfile = "$spooldir/$tmp/$groups{$group}";
#	print join':', @groups, "\n";
	mkdirhier ("$spooldir/$tmp");
	open (FILE, ">$origfile") or die "Can't create file $origfile: $!\n";
	
	${$_[1]} =~ s/^Xref: .+$/$xref/m;
	print FILE ${$_[1]}; #head

	print FILE "\n${$_[2]}"; #body
	close FILE or warn "Can't close file $origfile: $!\n";

	#tworzymy hardlinki dla crosspostow
	foreach my $group (@groups) {
		my $tmp = $group;
		$tmp =~ s#\.#/#g;
		my $linkname = "$spooldir/$tmp/$groups{$group}";
		mkdirhier ("$spooldir/$tmp");
		link ($origfile, $linkname) or warn "Can't create link $linkname: $!\n";
	}
	
	#tworzymy hardlink w katalogu indeksowym
	my ($path, $linkname) = msgid2hash($msgid);
#	print "$path / $linkname\n";
	mkdirhier($path);
	link ($origfile, "$path/$linkname") or warn "Can't create link $linkname: $!\n";

}


sub msgid2hash { # @_[0] - msg_id, zwraca katalog i nazw hardlinku
	$_[0] =~ s#/#\@#g;
	my $i = length($spooldir."/message.id/000/");
	my @kody = unpack("C*", $_[0]);

	my $sum = 0;
	foreach (@kody) {
		$sum += $_;
		$sum += ++$i;
	}
	$sum %= 999;
	$sum++;
	(sprintf ("%s/message.id/%03d", $spooldir, $sum), $_[0]);
}

sub read_groupinfo { # $_[0] - ref do hash'a
	my $grouplist = %{$_[0]};
	my ($group, $last, $first, $flag, $desc);
	print "Reading groupinfo file\n";
	mkdirhier("$spooldir/leaf.node");
	open (GI, $groupinfo) or die "Can't open file $groupinfo: $!\n";
	while (<GI>) {
		chomp;
		($group, $last, $first, $flag, $desc) = split(/ /, $_, 5);
		$grouplist{$group} = [$last, $first, $flag, $desc];
	}
	close GI or warn "Can't close file $groupinfo: $!\n";
}

sub read_history { # \%history
	my $history = $_[0];
	my ($tmp, $msgid);
	print "Reading history/overview files (newsgroup/.overview)\n";
	foreach my $grupa (keys(%Feeder::feeder::numery)) {
		$grupa =~ s#\.#/#g;
		my $overview = "$spooldir/$grupa/.overview";

		open (OV, $overview) or do {warn "Can't open file $overview: $!\n"; next;};
		while (<OV>) {
			chomp;
			(undef, undef, undef, undef, $msgid, undef) = split(/\t/, $_, 6);
#			print $msgid, "\n";
			$history->{$msgid} = 1;
		}
		close OV or warn "Can't close file $overview: $!\n";
	}
	
}
