#!/usr/bin/perl -w
#
# gpg-key2ps: convert a PGP/GnuPG key into paper slips.
+# Copyright (C) 2001-2005 Simon Richter
+# Copyright (C) 2005 Thijs Kinkhorst
+# Copyright (C) 2005 Christoph Berg <cb@df7cb.de>
+# Licenced under the GNU General Public License,
+# version 2 or later.
#
# $Id$
use strict;
-use Getopt::Std;
+use Getopt::Long;
my $version = '$Rev$';
$version =~ s/\$Rev:\s*(\d+)\s*\$/$1/;
-my $usage = "Usage: $0 [-p papersize] [-r revoked-style] keyid-or-name\n";
-my $keyids = "";
-my $revokestyle="hide";
+my $revokestyle = "hide";
+my $creationdate = scalar(localtime);
-if ( $#ARGV < 0 ) {
- print $usage;
- exit 1;
+sub version($) {
+ my $fd = shift;
+ print $fd "gpg-key2ps $version - (c) 2001-2005 Simon Richter, Thijs Kinkhorst, Christoph Berg\n";
+}
+
+sub usage($$) {
+ my ($fd, $exitcode) = @_;
+ version ($fd);
+ print $fd <<EOF;
+Usage: $0 [-p papersize] [-r revoked-style] keyid-or-name ...
+Options:
+ -p --paper-size
+ -r --revoked-style
+ hide - Don't show revoked uids (default)
+ grey - Print text in grey
+ note - Add "[revoked]"
+ show - List revoked uids normally
+ strike - Strike through lines
+ -h --help
+ -v --version
+EOF
+ exit $exitcode;
+}
+
+# fetch command line parameters
+my $opts;
+Getopt::Long::config('bundling');
+if (!GetOptions (
+ '-h' => \$opts->{help},
+ '--help' => \$opts->{help},
+ '-v' => \$opts->{version},
+ '--version' => \$opts->{version},
+ '-p=s' => \$opts->{papersize},
+ '--paper-size=s' => \$opts->{papersize},
+ '-r=s' => \$opts->{revokestyle},
+ '--revoked-style=s' => \$opts->{revokestyle},
+)) {
+ usage(\*STDERR, 1);
+}
+
+if ($opts->{help}) {
+ usage (\*STDOUT, 0);
+}
+
+if ($opts->{version}) {
+ version (\*STDOUT);
+ exit 0;
}
-my %opts;
-getopt('pr', \%opts);
-if ( $opts{r} ) { $revokestyle = $opts{'r'}; }
-if ( $opts{p} ) { $ENV{'PAPERSIZE'} = $opts{'p'}; }
-foreach (@ARGV) { $keyids .= $_ . " "; }
+if ( $opts->{revokestyle} ) { $revokestyle = $opts->{revokestyle}; }
+if ( $opts->{papersize} ) { $ENV{'PAPERSIZE'} = $opts->{papersize}; }
if ( $revokestyle !~ /^(grey|hide|note|show|strike)$/ ) {
- print STDERR "Unknown style \"$revokestyle\". Please use one of\n";
- print STDERR " grey - Print text in grey\n";
- print STDERR " hide - Don't show revoked uids\n";
- print STDERR " note - Add \"(revoked)\"\n";
- print STDERR " show - List revoked uids normally\n";
- print STDERR " strike - Strike through lines\n";
- exit 1;
+ print STDERR "Unknown revoked-style \"$revokestyle\".\n";
+ usage (\*STDERR, 1);
}
+usage(\*STDERR, 1) unless scalar @ARGV >= 1;
+
+# determine the paper size through the paperconf tool
my $w; my $h;
if ( -x "/usr/bin/paperconf" ) {
$w=`paperconf -w`;
chomp($h);
} else {
# Default to A4.
+ print STDERR "Warning: libpaper-utils is not installed, defaulting to A4.\n";
$w=596;
$h=842;
}
-if ( system( "gpg --fingerprint $keyids >/dev/null" ) != 0 ) {
- print STDERR "Key not found. Try 'gpg --list-keys'\n";
- exit 1;
-}
-
-open(GPG, "gpg --fingerprint --with-colons $keyids |");
+# open a gpg process we'll be reading from below
+map { s/'/'\\''/g; } @ARGV; # quote single quotes
+open(GPG, "gpg --fingerprint --with-colons '". (join "' '", @ARGV) ."' |");
+sub start_postscript {
+# start the PostScript output
print <<EOF;
%!PS-Adobe-3.0
%%BoundingBox: 0 0 $w $h
%%Title:
%%Creator: gpg-key2ps $version
-EOF
-print "%%CreationDate: " . scalar(localtime) . "\n";
-print <<EOF;
+%%CreationDate: $creationdate
%%Pages: 1
%%EndComments
EOF
+# output the desired display for revoked uids
if ( $revokestyle eq "grey" ) {
print "/revuid {\n";
print " .5 setgray\n";
print " uid\n";
print " 0 setgray\n";
print "} def\n";
-} elsif ( $revokestyle eq "hide" ) {
- print "/revuid {} def\n";
} elsif ( $revokestyle eq "note" ) {
print "/revuid {\n";
print " 50 y moveto (uid) show\n";
- print " 200 y moveto show ([revoked]) show\n";
+ print " 200 y moveto show ( [revoked]) show\n";
print " newline\n";
print "} def\n";
} elsif ( $revokestyle eq "show" ) {
/key {
noneedhline
EOF
+} # sub start_postscript
+# walk the output of gpg line by line
+# $numlines has the total number of lines so we'll know how many to put on page
my $numlines = 0;
+my $started = 0;
while(<GPG>) {
+ # we don't use these
if ( /^(tru|uat):/ ) { next; }
- if ( /^pub:/ ) { $numlines++; }
+ # every primary uid causes an extra line because of the separator
+ if ( /^pub:/ ) {
+ start_postscript() unless $started;
+ $started = 1;
+ $numlines++;
+ }
+ # primary uid
s/^pub:[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:([^:]*):[^:]*:[^:]*:.*/ ($5) ($4) ($3) $2 ($1) pub/;
+ # fingerprint, format it nicely with spaces
if ( /^fpr:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ) {
my $fpr = $1;
# v4 key
$fpr =~ s/(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})(\w{2})/$1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16/g;
$_ = " ($fpr) fpr\n";
}
+ # user ids
s/^uid:[^:r]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) uid/;
- s/^uid:[^:r]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) uid/;
- s/^uid:r[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) revuid/;
+ # revoked user id
+ if (s/^uid:r[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) revuid/) {
+ next if $revokestyle eq "hide";
+ }
+ # subkey
s/^sub:[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:.*/ ($4) ($3) $2 ($1) sbk/;
$numlines++;
+ # print this line
print;
}
close(GPG);
+unless ($started) {
+ print STDERR "No public key found.\n";
+ exit 1;
+}
+
+# output the remaining postscript
print <<EOF;
} def
-EOF
-print "/numlines $numlines def\n";
-print <<EOF;
+/numlines $numlines def
/num w 16 sub 10 div numlines div def
/column {
%%EOF
EOF
+# done!
exit 0;
+
+__END__
+
+=head1 NAME
+
+B<gpg-key2ps> - generates a PS file from a GnuPG keyring
+
+=head1 SYNOPSIS
+
+B<gpg-key2ps> [B<-r> I<revoked-style>] [B<-p> I<papersize>] I<keyid-or-name> [ I<...> ]
+
+=head1 DESCRIPTION
+
+gpg-key2ps generates a PostScript file with your OpenPGP key fingerprint (repeated
+as often as it fits) useful for keysigning parties. The only argument is the same
+as you would pass to GPG's list-keys command, either a key-id or a (partial) name.
+The PS data is written to stdout.
+
+=head1 OPTIONS
+
+=over
+
+=item B<-p> B<--paper-size> I<paper-size>
+
+Select the output paper size. Default is to look into /etc/papersize or A4 if
+libpaper isn't installed.
+
+=item B<-r> B<--revoked-style> I<revoked-style>
+
+Select how to mark revoked UIDs. Five styles are available:
+ B<hide> don't show at all (default),
+ B<show> show normally,
+ B<grey> display in 50% grey,
+ B<note> add "[revoked]", and
+ B<strike> strike through.
+
+=item I<keyid>
+
+Keyids to print. Multiple can be separated by spaces.
+
+=item B<-h> B<--help>
+
+Print usage and exit.
+
+=item B<-v> B<--version>
+
+Print version and exit.
+
+=back
+
+
+=head1 SEE ALSO
+
+gpg(1)
+
+http://pgp-tools.alioth.debian.org/
+
+=head1 AUTHORS AND COPYRIGHT
+
+(c) 2001 - 2005 Simon Richter <sjr@debian.org>
+
+(c) 2005 Thijs Kinkhorst <thijs@kinkhorst.com>
+
+(c) 2005 Christoph Berg <cb@df7cb.de>
+