* gpg-key2ps: also accept revoked-style long option, thanks Luca Capello
[pgp-tools.git] / gpg-key2ps / gpg-key2ps
1 #!/usr/bin/perl -w
2 #
3 # gpg-key2ps: convert a PGP/GnuPG key into paper slips.
4 # Copyright (C) 2001-2005 Simon Richter
5 # Copyright (C) 2005-2007 Thijs Kinkhorst
6 # Copyright (C) 2005-2007 Christoph Berg <cb@df7cb.de>
7 # Licenced under the GNU General Public License,
8 # version 2 or later.
9 #
10 # $Id$
11
12 use strict;
13 use Getopt::Long;
14
15 my $version = '$Rev$';
16 $version =~ s/\$Rev:\s*(\d+)\s*\$/$1/;
17 my $revokestyle = "hide";
18 my $columns = 2;
19 my $creationdate = scalar(localtime);
20
21 sub version($) {
22 my $fd = shift;
23 print $fd "gpg-key2ps $version - (c) 2001-2007 Simon Richter, Thijs Kinkhorst, Christoph Berg\n";
24 }
25
26 sub usage($$) {
27 my ($fd, $exitcode) = @_;
28 version ($fd);
29 print $fd <<EOF;
30 Usage: $0 [-p papersize] [-r revoked-style] [-1] keyid-or-name ...
31 Options:
32 -p --paper-size
33 -r --revoked-style
34 hide - Don't show revoked uids (default)
35 grey - Print text in grey
36 note - Add "[revoked]"
37 show - List revoked uids normally
38 strike - Strike through lines
39 -1 Only print one column, for extra wide keys
40 -h --help
41 -v --version
42 EOF
43 exit $exitcode;
44 }
45
46 # fetch command line parameters
47 my $opts;
48 Getopt::Long::config('bundling');
49 if (!GetOptions (
50 '-h' => \$opts->{help},
51 '--help' => \$opts->{help},
52 '-v' => \$opts->{version},
53 '--version' => \$opts->{version},
54 '-p=s' => \$opts->{papersize},
55 '--paper-size=s' => \$opts->{papersize},
56 '-r=s' => \$opts->{revokestyle},
57 '--revoked-style=s' => \$opts->{revokestyle},
58 '-1' => \$opts->{1},
59 )) {
60 usage(\*STDERR, 1);
61 }
62
63 if ($opts->{help}) {
64 usage (\*STDOUT, 0);
65 }
66
67 if ($opts->{version}) {
68 version (\*STDOUT);
69 exit 0;
70 }
71
72 if ( $opts->{revokestyle} ) { $revokestyle = $opts->{revokestyle}; }
73 if ( $opts->{papersize} ) { $ENV{'PAPERSIZE'} = $opts->{papersize}; }
74
75 if ( $revokestyle !~ /^(grey|hide|note|show|strike)$/ ) {
76 print STDERR "Unknown revoked-style \"$revokestyle\".\n";
77 usage (\*STDERR, 1);
78 }
79
80 if ( $opts->{1} ) { $columns = 1; }
81
82 usage(\*STDERR, 1) unless scalar @ARGV >= 1;
83
84 # determine the paper size through the paperconf tool
85 my $w; my $h;
86 if ( `which paperconf` && $? == 0 ) {
87 $w=`paperconf -w`;
88 $h=`paperconf -h`;
89 chomp($w);
90 chomp($h);
91 } else {
92 # Default to A4.
93 print STDERR "Warning: libpaper-utils is not installed, defaulting to A4.\n";
94 $w=596;
95 $h=842;
96 }
97
98 # open a gpg process we'll be reading from below
99 map { s/'/'\\''/g; } @ARGV; # quote single quotes
100 # --list-key due to #382794
101 open(GPG, "gpg --list-key --with-fingerprint --with-colons '". (join "' '", @ARGV) ."' |");
102
103 sub start_postscript {
104 # start the PostScript output
105 print <<EOF;
106 %!PS-Adobe-3.0
107 %%BoundingBox: 0 0 $w $h
108 %%Title:
109 %%Creator: gpg-key2ps $version
110 %%CreationDate: $creationdate
111 %%Pages: 1
112 %%EndComments
113
114 %%Page: 1 1
115
116 /w $w def
117 /h $h def
118
119 /Times-Roman findfont 9 scalefont setfont
120
121 /newline {
122 /y y 10 sub def
123 } def
124
125 /hline {
126 30 y 3 add moveto
127 w $columns div 30 sub y 3 add lineto stroke
128 newline
129 } def
130
131 /needhline {
132 /condhline { hline } def
133 } def
134
135 /noneedhline {
136 /condhline { } def
137 } def
138
139 /showAlgorithm {
140 << 1 (R) 2 (r) 3 (s) 16 (g) 20 (G) 17 (D) >> exch get
141 show
142 } def
143
144 /pub {
145 condhline
146 50 y moveto (pub) show
147 70 y moveto show showAlgorithm (/) show show
148 150 y moveto show
149 200 y moveto show
150 newline
151 needhline
152 } def
153
154 /fpr {
155 70 y moveto (Key fingerprint = ) show show
156 newline
157 } def
158
159 /uid {
160 50 y moveto (uid) show
161 200 y moveto show
162 newline
163 } def
164
165 EOF
166
167 # output the desired display for revoked uids
168 if ( $revokestyle eq "grey" ) {
169 print "/revuid {\n";
170 print " .5 setgray\n";
171 print " uid\n";
172 print " 0 setgray\n";
173 print "} def\n";
174 } elsif ( $revokestyle eq "note" ) {
175 print "/revuid {\n";
176 print " 50 y moveto (uid) show\n";
177 print " 200 y moveto show ( [revoked]) show\n";
178 print " newline\n";
179 print "} def\n";
180 } elsif ( $revokestyle eq "show" ) {
181 print "/revuid { uid } def\n";
182 } elsif ( $revokestyle eq "strike" ) {
183 print "/revuid {\n";
184 print " uid\n";
185 print " 45 y 9 add moveto h 2 div 45 sub y 18 add lineto stroke\n";
186 print "} def\n";
187 }
188
189 print <<EOF;
190
191 /sbk {
192 50 y moveto (sub) show
193 70 y moveto show showAlgorithm (/) show show
194 150 y moveto show
195 newline
196 } def
197
198 /key {
199 noneedhline
200 EOF
201 } # sub start_postscript
202
203 # walk the output of gpg line by line
204 # $numlines has the total number of lines so we'll know how many to put on page
205 my $numlines = 0;
206 my $started = 0;
207 while(<GPG>) {
208 # we don't use these
209 if ( /^(tru|uat):/ ) { next; }
210 # every primary uid causes an extra line because of the separator
211 if ( /^pub:/ ) {
212 start_postscript() unless $started;
213 $started = 1;
214 $numlines++;
215 }
216 # primary uid
217 s/^pub:[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:([^:]*):[^:]*:[^:]*:.*/ ($5) ($4) ($3) $2 ($1) pub/;
218 # fingerprint, format it nicely with spaces
219 if ( /^fpr:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ) {
220 my $fpr = $1;
221 # v4 key
222 $fpr =~ s/(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})(\w{4})/$1 $2 $3 $4 $5 $6 $7 $8 $9 $10/;
223 # v3 key
224 $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;
225 $_ = " ($fpr) fpr\n";
226 }
227 # user ids
228 s/^uid:[^:r]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) uid/;
229 # revoked user id
230 if (s/^uid:r[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) revuid/) {
231 next if $revokestyle eq "hide";
232 }
233 # subkey
234 s/^sub:[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:.*/ ($4) ($3) $2 ($1) sbk/;
235 $numlines++;
236 # print this line
237 print;
238 }
239 close(GPG);
240
241 unless ($started) {
242 print STDERR "No public key found.\n";
243 exit 1;
244 }
245
246 # output the remaining postscript
247 print <<EOF;
248 } def
249
250 /numlines $numlines def
251 /num w 16 sub 10 div numlines div def
252
253 /column {
254 /y w 20 sub def
255 1 1 num {
256 gsave
257 0 0 h $columns div w rectclip
258 /upper y 11 add def
259 key
260 newline
261 /lower y 11 add def
262 0 upper h $columns div upper h $columns div lower 0 lower 0 upper moveto lineto lineto lineto lineto stroke
263 grestore
264 } for
265 } def
266
267 w 0 translate
268 90 rotate
269 column
270 EOF
271
272 if ( $columns == 2 ) {
273 print <<EOF;
274 h $columns div 0 translate
275 column
276
277 EOF
278 }
279
280 print <<EOF;
281 showpage
282
283 %%Trailer
284 %%EOF
285 EOF
286
287 # done!
288 exit 0;
289
290
291 __END__
292
293 =head1 NAME
294
295 B<gpg-key2ps> - generates a PS file from a GnuPG keyring
296
297 =head1 SYNOPSIS
298
299 B<gpg-key2ps> [B<-r> I<revoked-style>] [B<-p> I<papersize>] I<keyid-or-name> [ I<...> ]
300
301 =head1 DESCRIPTION
302
303 gpg-key2ps generates a PostScript file with your OpenPGP key fingerprint (repeated
304 as often as it fits) useful for keysigning parties. The only argument is the same
305 as you would pass to GPG's list-keys command, either a key-id or a (partial) name.
306 The PS data is written to stdout.
307
308 =head1 OPTIONS
309
310 =over
311
312 =item B<-p> B<--paper-size> I<paper-size>
313
314 Select the output paper size. Default is to look into /etc/papersize or A4 if
315 libpaper isn't installed.
316
317 =item B<-r> B<--revoked-style> I<revoked-style>
318
319 Select how to mark revoked UIDs. Five styles are available:
320 B<hide> don't show at all (default),
321 B<show> show normally,
322 B<grey> display in 50% grey,
323 B<note> add "[revoked]", and
324 B<strike> strike through.
325
326 =item I<keyid>
327
328 Keyids to print. Multiple can be separated by spaces.
329
330 =item B<-h> B<--help>
331
332 Print usage and exit.
333
334 =item B<-v> B<--version>
335
336 Print version and exit.
337
338 =back
339
340 =head1 SEE ALSO
341
342 =over
343
344 =item gpg(1)
345
346 GNU Privacy Guard.
347
348 =item http://pgp-tools.alioth.debian.org/
349
350 The homepage of B<gpg-key2ps> and the other tools bundled in B<signing-party>.
351
352 =item http://www.debian.org/events/materials/business-cards/
353
354 B<gpg-key2ps> prints plain fingerprint slips. If you are looking for something
355 more stylish, look at these latex templates for business cards that also
356 include fingerprints.
357
358 =back
359
360 =head1 AUTHORS AND COPYRIGHT
361
362 =over
363
364 =item (c) 2001-2005 Simon Richter <sjr@debian.org>
365
366 =item (c) 2005-2007 Thijs Kinkhorst <thijs@kinkhorst.com>
367
368 =item (c) 2005-2007 Christoph Berg <cb@df7cb.de>
369
370 =back