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