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