# * support for multiple user keys
# * better charset conversion
# * pod documentation
+# see the Debian changelog for further changes.
my $VERSION = qq$Rev$;
+$ENV{PATH} .= ":/usr/share/signing-party";
use strict;
use warnings;
gpgsigs $VERSION- http://pgp-tools.alioth.debian.org/
(c) 2004 Uli Martens <uli\@youam.net>
(c) 2004, 2005 Peter Palfrader <peter\@palfrader.org>
- (c) 2004, 2005 Christoph Berg <cb\@df7cb.de>
+ (c) 2004, 2005, 2006, 2007 Christoph Berg <cb\@df7cb.de>
EOF
}
-r call gpg --recv-keys before proceeding
-f <charset> convert <keytxt> from charset
-t <charset> convert UIDs to charset in output
+--refresh regenerate UID lists on keys
+--latex generate LaTeX output including photo IDs
EOF
exit $error;
}
-my ($fromcharset, $charset, $recv_keys);
+my ($fromcharset, $charset, $recv_keys, $refresh, $latex);
Getopt::Long::config('bundling');
GetOptions(
'-f=s' => \$fromcharset,
'-t=s' => \$charset,
r => \$recv_keys,
+ refresh => \$refresh,
+ latex => \$latex,
help => sub { usage(*STDOUT, 0); },
version => sub { version(*STDOUT); exit 0;},
) or usage(*STDERR, 1);
# parse options
-my $mykey = uc(shift @ARGV);
+my @mykeys = split /,/, uc(shift @ARGV);
my $keytxt = (shift @ARGV) || usage(*STDERR, 1);
my $outfile = (shift @ARGV) || '-';
-my @mykeys = split /,/, $mykey;
map { s/^0x//i; } @mykeys;
+my %uids = map { $_ => [] } @mykeys;
if (!@mykeys || scalar @ARGV) {
usage(*STDERR, 1);
}
print STDERR "Running --list-sigs, this will take a while ";
-open SIGS, "gpg --fixed-list-mode --with-colons --list-sigs @keys 2>/dev/null |"
+open SIGS, "gpg --fixed-list-mode --with-colons --list-sigs @mykeys @keys 2>/dev/null |"
or die "can't get gpg listing";
-my ($key, $uid, $sigs);
+my ($key, $uid, $sigs, $photocount);
while (<SIGS>) {
if ( m/^pub:(?:.*?:){3,3}([0-9A-F]{16,16}):/ ) {
$key = $1;
print STDERR ".";
+ undef $photocount;
next;
}
- if ( m/^uid:(?:.*?:){8,8}(.*):/s ) {
- $uid = myrecode($1, "UTF-8", $charset);
+ if ( m/^uid:(.):(?:.*?:){7,7}(.*):/s ) {
+ my $uidstatus = $1;
+ $uid = $2;
+ $uid =~ s/\\x([0-9a-f][0-9a-f])/ chr(hex($1)) /gie;
+ $uid = myrecode($uid, "UTF-8", $charset);
+
+ my ($shortkey) = substr $key, -8;
+ # Remember non-revoked uids
+ next if $uidstatus eq "r";
+ push @{$uids{$shortkey}}, $uid;
+ next;
+ }
+ if ( m/^uat:(.)::::[^:]+::([0-9A-F]+)::\d+ (\d+)/ ) { # uat:-::::2006-08-03::27BAEAF742BD253C2F3F03B043DC1536880193C4::1 7993:
+ my $uidstatus = $1;
+ # $2 is hash of attribute data
+ my $size = $3 - 19; # FIXME: find a nicer way to find out picture size
+ $uid = "[jpeg image of size $size]";
+ next if $uidstatus eq "r";
+ if ($latex and not $photocount) { # call once per key
+ my ($shortkey) = substr $key, -8;
+ system "rm $shortkey.[1-9]*.eps";
+ system "gpg --photo-viewer 'gpgsigs-eps-helper $shortkey' --list-options show-photos --list-key $key > /dev/null";
+ $photocount = 1;
+ }
+ my ($shortkey) = substr $key, -8;
+ push @{$uids{$shortkey}}, $uid;
next;
}
if ( m/^sig:(?:.*?:){3,3}([0-9A-F]{8})([0-9A-F]{8}):(?:.*?:){5,5}(.*?):/ ) {
if ($before eq 'S' || $before eq 's') {
$sigs->{$key}->{$uid}->{$1.$2} = $class;
} elsif ($class eq 'S' || $class eq 's') {
- # intentionall left blank
+ # intentionally left blank
} elsif ($before < $class) {
$sigs->{$key}->{$uid}->{$1.$2} = $class;
};
$sigs->{$key}->{$uid}->{$2} = $sigs->{$key}->{$uid}->{$1.$2};
next;
}
- if ( m/^uat:/ ) {
- $uid = "Photo ID";
- next;
- }
- next if ( m/^(rev|sub|tru):/ );
+ next if ( m/^(rev|rvk|sub|tru):/ ); # revoke/revoker/subkey/trust
warn "unknown value: '$_', key: ".(defined $key ? $key :'none')."\n";
-}
+}
close SIGS;
print STDERR "\n";
# read checksums
-open MD, "gpg --print-md md5 $keytxt|" or warn "can't get gpg md5\n";
+open MD, "gpg --with-colons --print-md md5 $keytxt|" or warn "can't get gpg md5\n";
my $MD5 = <MD>;
close MD;
-open MD, "gpg --print-md sha1 $keytxt|" or warn "can't get gpg sha1\n";
+open MD, "gpg --with-colons --print-md sha1 $keytxt|" or warn "can't get gpg sha1\n";
my $SHA1 = <MD>;
close MD;
+open MD, "gpg --with-colons --print-md sha256 $keytxt|" or warn "can't get gpg sha256\n";
+my $SHA256 = <MD>;
+close MD;
+
+my @MD5 = split /:/, $MD5;
+my @SHA1 = split /:/, $SHA1;
+my @SHA256 = split /:/, $SHA256;
+$MD5 = $MD5[2];
+$SHA1 = $SHA1[2];
+$SHA256 = $SHA256[2];
+
+$MD5 =~ s/(.{16})/$1 /;
+$SHA1 =~ s/(.{20})/$1 /;
+$SHA256 =~ s/(.{32})/$1 /;
+$MD5 =~ s/([0-9A-Z]{2})/$1 /ig;
+$SHA1 =~ s/([0-9A-Z]{4})/$1 /ig;
+$SHA256 =~ s/([0-9A-Z]{4})/$1 /ig;
chomp $MD5;
chomp $SHA1;
+chomp $SHA256;
my $metatxt = quotemeta($keytxt);
$MD5 =~ s/^$metatxt:\s*//;
$SHA1 =~ s/^$metatxt:\s*//;
+$SHA256 =~ s/^$metatxt:\s*//;
# write out result
my ($key, $uid) = @_;
if (! defined $sigs->{$key}->{$uid}) {
warn "uid '$uid' not found on key $key\n";
+ #for (keys %{ $sigs->{$key} }) {
+ # print STDERR "only have $_\n";
+ #};
return '(' . (' ' x @mykeys) . ')';
}
my $r = '(';
print STDERR "Annotating $keytxt, writing into $outfile\n";
open (TXT, $keytxt) or die ("Cannot open $keytxt\n");
open (WRITE, '>'.$outfile) or die ("Cannot open $outfile for writing\n");
+
+if ($latex) {
+ print WRITE <<'EOF';
+\documentclass{article}
+\usepackage[margin=2cm]{geometry}
+\usepackage{alltt}
+\usepackage{graphicx}
+\begin{document}
+\begin{alltt}
+EOF
+}
+
while (<TXT>) {
$line++;
$_ = myrecode($_, $fromcharset, $charset);
if (/^SHA1 Checksum:/ && defined $SHA1) {
s/[_[:xdigit:]][_ [:xdigit:]]+_/$SHA1/;
}
+ if (/^SHA256 Checksum:/ && defined $SHA256) {
+ s/[_[:xdigit:]][_ [:xdigit:]]+_/$SHA256/;
+ }
if ( m/^pub +(?:\d+)[DR]\/([0-9A-F]{8}) [0-9]{4}-[0-9]{2}-[0-9]{2} *(.*)/ ) {
$key = $1;
$uid = $2;
# print WRITE print_tag($key, $uid) . " $_";
# next;
#}
+ print WRITE;
+ undef $photocount;
+ next;
+ }
+
+ if ( m/^ *Key fingerprint/ ) {
+ print WRITE;
+ my $inc = "";
+ foreach my $mykey (@mykeys) {
+ foreach my $myuid (@{$uids{$mykey}}) {
+ $inc .= defined $sigs->{$mykey}->{$myuid}->{$key} ? $sigs->{$mykey}->{$myuid}->{$key} : ' ';
+ }
+ }
+ print WRITE "[$inc] incoming signatures\n" if $inc =~ /\S/;
+ if ($refresh or $latex) {
+ foreach $uid (@{$uids{$key}}) {
+ print WRITE print_tag($key, $uid) . " $uid\n";
+ if ($latex and ($uid =~ /^\[jpeg image/)) {
+ $photocount++;
+ print WRITE "\\begin{flushright}\n";
+ print WRITE "\\includegraphics[height=3cm]{$key.$photocount.eps}\n";
+ print WRITE "\\end{flushright}\n";
+ }
+ }
+ }
+ next;
+
}
if ( m/^uid +(.*)$/ ) {
$uid = $1;
+ next if $refresh or $latex;
unless (defined $key) {
warn "key is undefined - input text is possibly malformed near line $line\n";
next;
};
- die "uid is undefined, key $key" unless defined $uid;
die "bad tag from $key | $uid" unless defined (print_tag($key, $uid));
print WRITE print_tag($key, $uid) . " $_";
next;
}
print WRITE "Legend:\n";
+my $num_myuids = 0;
foreach my $i (0 .. @mykeys - 1) {
- print WRITE '('. ' 'x$i . 'S' . ' 'x(@mykeys-$i-1) . ") signed with $mykeys[$i]\n";
+ print WRITE '(' . ' 'x$i . 'S' . ' 'x(@mykeys-$i-1) . ") signed with $mykeys[$i] $uids{$mykeys[$i]}->[0]\n";
+ $num_myuids += @{$uids{$mykeys[$i]}};
+}
+my $i = 0;
+foreach my $mykey (@mykeys) {
+ foreach my $myuid (@{$uids{$mykey}}) {
+ my $inc = defined $sigs->{$mykey}->{$myuid}->{$key} ? $sigs->{$mykey}->{$myuid}->{$key} : ' ';
+ print WRITE "[" . ' 'x$i . 'S' . ' 'x($num_myuids-$i-1) . "] has signed $mykey $myuid\n";
+ $i++;
+ }
}
close TXT;
+if ($latex) {
+ print WRITE <<'EOF';
+\end{alltt}
+\end{document}
+EOF
+}
+
+close WRITE;
+
__END__
=head1 NAME
=head1 SYNOPSIS
-B<gpgsigs> [-r] [-f I<charset>] [-t I<charset>] I<keyid>I<[>B<,>I<keyidI<[>B<,>I<...>I<]>>I<]> F<keytxt> [F<outfile>]
+B<gpgsigs> [I<options>] I<keyid>I<[>B<,>I<keyidI<[>B<,>I<...>I<]>>I<]> F<keytxt> [F<outfile>]
=head1 DESCRIPTION
=over
-=item -r
+=item B<-r>
Call I<gpg --recv-keys> before creating the output.
-=item -f I<charset>
+=item B<-f> I<charset>
Convert F<keytxt> from I<charset>. The default is ISO-8859-1.
-=item -t I<charset>
+=item B<-t> I<charset>
Convert UIDs to I<charset>. The default is derived from LC_ALL, LC_CTYPE, and
LANG, and if all these are unset, the default is ISO-8859-1.
+=item B<--refresh>
+
+Refresh the UID lists per key from gpg. Useful when UIDs were added or revoked
+since the input text was generated.
+
+=item B<--latex>
+
+Generate LaTeX output, including photo IDs. Implies B<--refresh>.
+B<Note:> This writes eps files to the current directory.
+
=item I<keyid>
Use this keyid (8 or 16 byte) for annotation. Multiple keyids can be separated
(c) 2004, 2005 Peter Palfrader <peter@palfrader.org>
-(c) 2004, 2005 Christoph Berg <cb@df7cb.de>
+(c) 2004, 2005, 2006, 2007 Christoph Berg <cb@df7cb.de>
=head1 LICENSE