#!/usr/bin/perl -w
# showtoken - decode SM tokens
# Olaf Titz, 1999. Marco d'Itri, 2000. Public domain.
# Takes tokens on stdin and write them along with a decoded form on stdout.

use strict;

my ($pathspool, %NG);

my @types = ('trash', '', 'timehash', 'cnfs', 'timecaf', 'tradspool');

if ($ARGV[0]) {
	$pathspool = $ARGV[0];
	if (open(MAP, "$pathspool/tradspool.map")) {
		while (<MAP>) {
			my ($ng, $gnum) = split;
			$NG{$gnum} = $ng;
		}
		close MAP;
	}
}

$| = 1;
while (<STDIN>) {
	chomp;
	next if not /^@.+@/;
	print "$_ ";
	splittoken($_);
}

sub splittoken {
	my $t = shift;

	$t =~ tr/@//d;
	$t = pack('H*', $t);
	my ($type, $class, $token, $index, $offset, $overlen, $cancelled) =
		unpack('C C a16 CLnc', $t);

	if (not $types[$type]) {
		print "type=$type unknown!\n";
		next;
	}
	print "type=$types[$type] class=$class ";

	if ($type == 0) {		# trash
	} elsif ($type == 2) {	# timehash
		my ($time, $seq) = unpack('Nn', $token);
		my ($a, $b, $c, $d) = unpack('CCCC', $token);
		printf 'time=%08lX seq=%04X file=time-%02x/%02x/%02x/%04x-%02x%02x',
			$time, $seq, $class, $b, $c, $seq, $a, $d;
	} elsif ($type == 3) {	# cnfs
		my ($buffn, $offset, $cnum) = unpack('A8NN', $token);
		printf 'buffer=%s offset=%x cycnum=%x', $buffn, $offset * 512, $cnum;
	} elsif ($type == 4) {	# timecaf
		my ($time, $seq) = unpack('Nn', $token);
		my (undef, $b, $c, $d) = unpack('CCCC', $token);
		printf 'time=%06lX seq=%04X caf=timecaf-%02x/%02x/%02x%02x.CF',
			$time, $seq, $class, $c, $b, $d;
	} elsif ($type == 5) {	# tradspool
		my ($gnum, $art) = unpack('NN', $token);
		printf 'ng=%08X art=%d', $gnum, $art;
		print "file=articles/$NG{$gnum}/$art" if $NG{$gnum};
	} else {
		die "invalid type $type";
	}
	print " over=$index offset=$offset overlen=$overlen cancelled=$cancelled"
		if length $t > 36;
	print "\n";
}
__END__
# Format of a token:
#  1   type
#  1   class
# 16   token
#  1   index
#  4   offset
#  2   overlen
#  2   cancelled
# The fields "index" and following are not available with OV3 (INN 2.3 up)
#
# the "token" field is:
# for type=0 (trash) ignored
# for type=2 (timehash)
#  4   time
#  2   seqnum
# for type=3 (cnfs)
#  8   cycbuffname
#  4   offset/512
#  4   cycnum
# for type=4 (timecaf)
#  4   time
#  2   seqnum
# for type=5 (tradspool)
#  4   ngnum
#  4   artnum
