#!/usr/bin/perl -w

# $Id: ca-createsendout 160 2005-01-05 10:16:17Z lfousse $

# Copyright (c) 2001, 2003, 2004 Peter Palfrader
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Privacy Guard; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
#
$|=1;

use strict;
use IO::Handle;
use English;
use File::Path;
use Cabot qw(%CONFIG makekeydir mkfds ask readwritegpg);

my $config = $ENV{'HOME'} . '/.cabotrc';
-f $config or die "No file $config present.  See ca-config(5).\n";
my $confblurb = '';
open CONFIG, $config;
{
    local $/;
    $confblurb = <CONFIG>;
}
close CONFIG;

unless (scalar eval $confblurb) {
	die "Couldn't parse $config: $EVAL_ERROR\n" if $EVAL_ERROR
};

unless (scalar @ARGV) {
	print STDERR "Usage: $PROGRAM_NAME <keyid> [<keyid> ...]\n";
	exit 1;
};

KEYS:
for my $keyid (@ARGV) {
	$keyid =~ tr/a-f/A-F/;
	if (length($keyid) > 8) {
		my $kid = substr $keyid, -8, 8;
		print "Warning: assuming $keyid is a fingerprint. Using " . $kid;
		print " as keyid.\n";
		$keyid = $kid;

	}
	for my $keyserver ( @{$CONFIG{'keyservers'}} ) {
		print "Getting key from $keyserver...\n";

		my $gpg = GnuPG::Interface->new();
		$gpg->options->hash_init( 'extra_args' => '--keyserver='.$keyserver );
		my ($inputfd, $stdoutfd, $stderrfd, $statusfd, $handles) = mkfds();
		my $pid = $gpg->recv_keys(handles => $handles, command_args => [ $keyid ]);
		my ($stdout, $stderr, $status) = readwritegpg('', $inputfd, $stdoutfd, $stderrfd, $statusfd);
		waitpid $pid, 0;

		($status =~ /NODATA/) and
			warn("Could not import $keyid\n"),
			next;
		print "done.\n";
	};


	# Find UIDs and if the key is useable at all.
	# also check whether we already signed any of the UIDs.

	my $gpg = GnuPG::Interface->new();
	$gpg->options->hash_init( 'extra_args' => [ '--with-colons', '--fixed-list-mode', '--fingerprint' ] );
	my ($inputfd, $stdoutfd, $stderrfd, $statusfd, $handles) = mkfds();
	my $pid = $gpg->list_sigs(handles => $handles, command_args => [ $keyid ]);
	my ($stdout, $stderr, $status) = readwritegpg('', $inputfd, $stdoutfd, $stderrfd, $statusfd);
	waitpid $pid, 0;

	if (length($stdout) == 0) {
		print ("Warn: Key $keyid apparently not found\n");
		next;
	};

	my @uids;
	for my $line (split /\n/, $stdout) {
		my ($type, $trust, $length, $algo, $longkeyid, $created, $expires,
		    $serial, $ownertrust, $uid, $sigclass, $caps, $issuer, $flag) = split /:/, $line;

		if ($type eq 'pub' && $trust eq 'r') {
			print ("Warn: Key $keyid is revoked! Skipping.\n");
			next KEYS;
		};
		if ($type eq 'pub' && $caps !~ 'E') {
			print ("Note: Key $keyid has no encryption capabilities! This CA-Bot cannot handle this.\n");
			next KEYS;
		};
		if ($type eq 'fpr') {
			$uid =~ s/([0-9A-F]{4})/$1 /gi;
			print "Fingerprint: $uid\n";
		}
		unshift @uids, { uid => $uid,
		                 revoked => ($trust eq 'r'),
		                 email => ($uid =~ /@/) ? 1 : 0 } if ($type eq 'uid');

		$uids[0]->{'signed'}++ if (($type eq 'sig') && ($longkeyid =~ /$CONFIG{'keyid'}$/i));
	};

	for my $uid (reverse @uids) {
		if ($uid->{'revoked'}) {
			print "UID $keyid/$uid->{'uid'} is revoked, skipping.\n";
			next;
		};
		unless ($uid->{'email'}) {
			print "UID $keyid/$uid->{'uid'} apparently has no email address, skipping.\n";
			next;
		};
		if ($uid->{'signed'}) {
			print "UID $keyid/$uid->{'uid'} is already signed by your key, skipping.\n";
			next;
		};

		my $add = ask("Add $keyid/$uid->{'uid'} to the sendout spool?", 1);
		makekeydir('sendoutdir', $keyid, $uid->{'uid'}) if $add;
	};
};

__END__

=pod

=head1 NAME

ca-createsendout - download public GPG/PGP keys

=head1 SYNOPSIS

B<ca-createsendout> I<keyid> B<[>I<keyid>...B<]>

=head1 DESCRIPTION

B<ca-createsendout> fetches public keys from a keyserver, specified in the
keyservers ca-bot config setting.  gpg(1) stores these in ~/.gnupg/pubring.gpg.
B<ca-createsendout> then asks wether it should create per-uid directories for
the keys, under the keyspecific C<sendoutdir> directory.  These directories look
like e.g.

 ~/sendout/12345678/John Doe <john@example.com>/

.

B<ca-createsendout> bootstraps the ca-bot(7) process.

=head1 SEE ALSO

ca-bot(7), ca-config(5)

=head1 VERSION

$Id: ca-createsendout 160 2005-01-05 10:16:17Z lfousse $

=head1 AUTHOR

Peter Palfrader

=cut

