Codebase list jetring / debian/0.06 jetring-review
debian/0.06

Tree @debian/0.06 (Download .tar.gz)

jetring-review @debian/0.06raw · history · blame

#!/usr/bin/perl
# Given a keyring and a changeset, shows what gpg would do if it
# applied the changeset to the keyring. The keyring is not modified.
use warnings;
use strict;
use File::Temp;
use Cwd q{abs_path};

my @allowed_actions=qw(import edit-key delete-key);
my @gpgopts=qw(--command-fd 0 --no-auto-check-trustdb --options /dev/null
	--no-default-keyring);

my $diff=0;
if (@ARGV && $ARGV[0] eq '-d') {
	$diff=1;
	shift;
}
my $keyring=shift || usage();
my $changeset=shift || usage();

$keyring=abs_path($keyring); # gpg works better with an absolute path

my $testring=$keyring.".tmp.$$";
if (-e $testring) {
	die "$testring exists";
}
system("cp", $keyring, $testring) == 0 || die "copy failed";
push @gpgopts, "--keyring", $testring;

my $secring="secret-dummy.$$";
sub END {
	unlink $secring if defined $secring;
	if (defined $testring) {
		unlink $testring;
		unlink $testring."~";# gpg backup file
		unlink $testring.".cache"; # generated by jetring-diff
	}
}
open (SECRET_DUMMY, ">$secring") || die "$secring: $!";
close SECRET_DUMMY;
push @gpgopts, "--secret-keyring", abs_path($secring);

my %fields;
my $field;
open(CHANGESET, "<", $changeset) || die "$changeset: $!";
while (<CHANGESET>) {
	chomp;
	if ($_ eq "-----BEGIN PGP SIGNED MESSAGE-----") {
		<CHANGESET> for 1..2;
		next;
	}
	elsif ($_ eq "-----BEGIN PGP SIGNATURE-----") {
		last;
	}
	if (/^([^\s]+):(?:\s+(.*))?/) {
		$field=lc $1;
		if (defined $2) {
			$fields{$field}=$2;
		}
		else {
			$fields{$field}='';
		}
	}
	elsif (/^\s+(.*)/ && defined $field) {
		$fields{$field}.="\n" if length $fields{$field};
		$fields{$field}.=$1;
	}
	elsif ($_ eq "") {
		process() if defined $field;
		%fields=();
		$field=undef;
	}
	else {
		die "parse error on line $. of $changeset";
	}
}
close CHANGESET;
process() if defined $field;

if ($diff) {
	system("jetring-diff", $keyring, $testring) == 0 ||
		die "jetring-diff exited nonzero";
}

sub process {
	if (! exists $fields{action}) {
		die "$changeset missing action field";
	}
	my @action=split(' ', $fields{action});
	my $command=shift @action;
	if (! grep { $_ eq $command } @allowed_actions) {
		die "$changeset contains disallowed action \"$command\"";
	}
	if (! exists $fields{data}) {
		die "$changeset missing data field";
	}

	print "gpg --$command @action\n";
	my $pid = open(GPG, "|-");
	$SIG{PIPE} = 'IGNORE';
	if (! $pid) {
		exec("gpg", @gpgopts, "--$command", @action) ||
			die("failed to run gpg");
	}
	$|=1;
	GPG->autoflush(1);
	foreach my $line (split("\n", $fields{data})) {
		print ">> $line\n" if $command ne 'import';
		print GPG "$line\n" || die "failed talking to gpg";
		sleep 1 if $command ne 'import';  # makes output clearer
	}
	close GPG || die "gpg exited nonzero";
	print "gpg operation complete\n\n";
}

sub usage {
	die "Usage: jetring-review [-d] keyring changeset\n"; 
}