#!/usr/bin/perl
#	@(#) xovercheck.pl - Compare the headers of a group against xover data
#
# xovercheck.pl groupname first_article last_article

use Net::NNTP;

my $newsserver = $ENV{'NNTPSERVER'} || 'news';

sub check_article {
	my($s,$artid,$xover_ar) = @_;

	printf "%d  ", $artid;

	# Grab the header of the article
	my $headers = $s->head($artid);
	if (!defined $headers) {
		print "Expired\n";
		return;
	}

	# Save the headers which we will check
	my($subject,$from,$date,$messageid);
	foreach (@$headers) {
		chop;
		if (/^Subject: +(.*)/) {
			$subject = $1;
		} elsif (/^From: +(.*)/) {
			$from = $1;
		} elsif (/^Date: (.*)/) {
			$date = $1;
		} elsif (/^Message-ID: (.*)/) {
			$messageid = $1;
		}
#		printf "%d <%s>\n", $artid, $_;
	}

#	print "Subject: $subject From: $from Date: $date Message-ID: $messageid\n";

	my $i = 0;
	my $ok = 1;
	my $msg;

	if ($xover_ar->[$overview_from] ne $from) {
		$msg .= sprintf "From mismatch (x:%s) (h:%s) ", $xover_ar->[$overview_from], $from;
		$ok = 0;
	}

	if ($xover_ar->[$overview_subject] ne $subject) {
		$msg .= sprintf "Subject mismatch (x:%s) (h:%s) ", $xover_ar->[$overview_subject], $subject;
		$ok = 0;
	}

	if ($xover_ar->[$overview_date] ne $date) {
		$msg .= sprintf "Date mismatch (x:%s) (h:%s) ", $xover_ar->[$overview_date], $date;
		$ok = 0;
	}

	if ($xover_ar->[$overview_messageid] ne $messageid) {
		$msg .= sprintf "Message-ID mismatch (x:%s) (h:%s) ", $xover_ar->[$overview_messageid], $messageid;
		$ok = 0;
	}

#	foreach (@$xover_ar) {
#		printf "%d %s %s\n",
#			$artid, $overview_ref->[$i], $_;
#		$i++;
#	}
#	print "\n";

	if ($ok) {
		print "ok $date\n";
	} else {
		print "error $msg\n";
	}
}

# Compare xover/header information for a range of articles

sub check_range {
	my($s,$art_low,$art_high) = @_;

	# Get the xover info for these articles
	$xover_list = [$art_low, $art_high];

	my $xover_out = $s->xover($xover_list);

	foreach my $n ($art_low..$art_high) {
		if (exists $xover_out->{$n}) {
			my $r = $xover_out->{$n};
			check_article($s,$n, $r);
		} else {
			printf "%d  missing\n", $n;
		}
	}

}

my $s = new Net::NNTP($newsserver, reader=>1);
if (!defined $s) {
	print "Unable to connect to news server, sorry!\n";
	exit(4);
}

my $group = shift @ARGV;
if (!$group) {
	print "Usage: xovercheck.pl groupname first_article last_article\n";
	exit(4);
}

my $first = shift @ARGV;
my $last = shift @ARGV;

my($art_n,$art_low,$art_high,$name) = $s->group($group);

print "Group $group: $art_n articles from $art_low to $art_high\n\n";

if ($first > $art_low && $first <= $art_high) {
	$art_low = $first;
}

if ($last >= $first && $last >= $art_low && $last <= $art_high) {
	$art_high = $last;
}

# Pull out the xover format 
$overview_ref = $s->overview_fmt();
# overview_ref = [fieldname, ...]

my $index = 0;
foreach $i (@$overview_ref) {
#	print "Field: $i\n";
	if ($i eq 'Date:') {
		$overview_date = $index;
	} elsif ($i eq 'From:') {
		$overview_from = $index;
	} elsif ($i eq 'Subject:') {
		$overview_subject = $index;
	} elsif ($i eq 'Message-ID:') {
		$overview_messageid = $index;
	}
	$index++;
}
#print "\n";

# Check articles in groups of 20
while ($art_high >= $art_low) {
	my $top = $art_low + 19;
	if ($top > $art_high) {
		$top = $art_high;
	}
	print STDERR "Checking from $art_low to $top\n";
	check_range($s,$art_low,$top);
	$art_low = $top + 1;
}

$s->quit();

exit(0);
