#!/usr/local/bin/perl
# 
# LPRng authorization test program
# 
#   - used to receive and decode remote authenticated
#     information
#   command line:
#   /filter -S -P printer -n server_id -A authtype -R remote_id -Ttempfile
#   The server_id and remote_id are URL escaped values
#   tempfile is a path to a tempfile for working information
# 
#    FD Options Purpose
#    0  R/W     socket connection to remote host (R/W)
#    1  W       for status report about authentication
#    2  W       error log
#    3  R       for server status to be sent to client
# 
#   Actions:
# 1. read a single line from FD 0.  This will be the number
#    of bytes to transfer.
# 2. read the specified number of bytes into tempfile
# 3. Run whatever consistency checks are needed,  and then
#    decode the transferred file.
# 4. The transferred file has a header, blank line, and body.
#    write the authentication information to FD 1.
#    The ID of the sender (from) is sent as:
#    from=xxxx   where xxx is the appropriate value.
# 5. close FD 1,  and read information from FD 3 into the tempfile.
# 6. encode the tempfile,  and then transfer to the remote
#    host over FD 0.
# 

use Getopt::Std;
use FileHandle;
use Shell;
use URI::Escape;

my($debug, %args,$key,$value,$v, $tempfile, $temp, $socket,
	$buf, $done, $line, $len, $n, $r, $test, @lines, $from,
	$user, $dir, $pwfile );

$|= 1;
$debug = 0;
$test = 0;

getopts("CFSD:P:n:A:R:T:",\%args);

if( defined($line = $args{'D'}) ){
	$debug = 1 if( $line =~ /debug/ );
	$test = 1 if( $line =~ /test/ );
}

if( $debug ){
	$v = "$0";
	foreach $key (sort keys %args){
		$v .= " $key=$args{$key}"
	}
	print STDERR $v . "\n";
	print STDERR "ARGV @ARGV\n";
	for $i (sort keys %ENV ){
		print STDERR "ENV $i=$ENV{$i}\n";
	}
}

$temp = new FileHandle;
$socket = new FileHandle;

$tempfile = $args{'T'};
if( not $tempfile ){
	warn "missing tempfile\n";
	exit(1);
}

$user = uri_unescape($args{'n'});
if( not $user ){
	warn "missing user\n";
	exit(1);
}

goto done if( $test );

$temp->open(">$tempfile") or die "cannot open '$tempfile'";
$socket->open("<&0") or die "cannot open fd 0";
defined( $len = <$socket> ) or die "cannot read from fd 0";

while( $len > 0 ){
	$n = $len;
	$n = 10240 if( $n > 10240 );
	$r = read( $socket, $buf, $n );
	$r == $n or die "failed read from fd 0";
	print STDERR "FILE '$buf'\n" if $debug;
	print $temp $buf;
	$len -= $n;
}

$temp->close();
$socket->close();

print STDERR "finished transfer\n" if( $debug );

done:

##  The following illustrates how you can use pgp to decode the
##  transferred file.  Replace with your own stuff
##  Note: the PGPPASSFD is a safe way to give PGP the passphrase
#
#$dir = (getpwnam($user))[7];
#if( not defined($dir) ){
#	warn "user does not have home dir\n";
#	exit(1);
#}
#$pwfile = "$dir/.pgp/serverkey";
#$temp ->open("<$pwfile") or die "cannot open '$pwfile'";
#
#print STDERR "server key '" . `cat $pwfile ` . "\n" if $debug;
#$ENV{'PGPPASSFD'} = 5;
#$line = "pgp +force +batch $tempfile -u $args{'n'} -o $tempfile 2>&1 5<$pwfile";
#
#print STDERR "$line\n" if $debug;
#eval{ @lines = `$line`; };
#if( $@ ){
#	print STDERR "eval error '$@'\n";
#	exit(1);
#} elsif( $? ){
#	$line = join( '', @lines);
#	chomp($line);
#	$i = $? >> 8;
#	print STDERR "pgp error '$line'\n";
#	exit(1);
#}
#
#for( $i = 0; $i <@lines; ++$i ){
#	$line = $lines[$i];
#	chomp $line;
#	print STDERR " [$i] = '$line'\n" if $debug;
#	if( $line =~ /^Good signature[^"]*"([^"]*)"/ ){
#		$from = $1;
#	}
#}

$temp->open("<$tempfile") or die "cannot open '$tempfile'";

$done = 0;
while( not $done and defined( $line = <$temp> ) ){
	chomp($line);
	if( $line ){
		print STDERR "HEADER '$line'\n" if( $debug );
		print "$line\n";
		if( $from == "" && $line =~ /client=(.*)/ ){
			print STDERR "HEADER FROM '$from'\n" if( $debug );
			$from = $1;
		}
	} else {
		if( $from ){
			print STDERR "HEADER SENDING FROM '$from'\n" if( $debug );
			print "from=$from\n";
		}
		close(STDOUT);
		$done = 1;
	}
}

print STDERR "finished header\n" if( $debug );
$temp->close();

exit(0) if $test;

$temp->open("<&3") or die "cannot open fd 3";
$socket->open(">&0") or die "cannot open fd 0";
$socket->autoflush(1);

while( defined ($line = <$temp>) ){
	print STDERR "RETURN '$line'\n" if( $debug );
	print $socket $line;
}
