Since we can't count anymore on libpaper being installed,
[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 "hide" ) {
169 print "/revuid {} def\n";
170 } elsif ( $revokestyle eq "note" ) {
171 print "/revuid {\n";
172 print " 50 y moveto (uid) show\n";
173 print " 200 y moveto show ( [revoked]) show\n";
174 print " newline\n";
175 print "} def\n";
176 } elsif ( $revokestyle eq "show" ) {
177 print "/revuid { uid } def\n";
178 } elsif ( $revokestyle eq "strike" ) {
179 print "/revuid {\n";
180 print " uid\n";
181 print " 45 y 9 add moveto h 2 div 45 sub y 18 add lineto stroke\n";
182 print "} def\n";
183 }
184
185 print <<EOF;
186
187 /sbk {
188 50 y moveto (sub) show
189 70 y moveto show showAlgorithm (/) show show
190 150 y moveto show
191 newline
192 } def
193
194 /key {
195 noneedhline
196 EOF
197 } # sub start_postscript
198
199 # walk the output of gpg line by line
200 # $numlines has the total number of lines so we'll know how many to put on page
201 my $numlines = 0;
202 my $started = 0;
203 while(<GPG>) {
204 # we don't use these
205 if ( /^(tru|uat):/ ) { next; }
206 # every primary uid causes an extra line because of the separator
207 if ( /^pub:/ ) {
208 start_postscript() unless $started;
209 $started = 1;
210 $numlines++;
211 }
212 # primary uid
213 s/^pub:[^:]*:([^:]*):([0-9]*):.{8,8}(.{8,8}):([^:]*):[^:]*:[^:]*:[^:]*:([^:]*):[^:]*:[^:]*:.*/ ($5) ($4) ($3) $2 ($1) pub/;
214 # fingerprint, format it nicely with spaces
215 if ( /^fpr:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ) {
216 my $fpr = $1;
217 # v4 key
218 $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/;
219 # v3 key
220 $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;
221 $_ = " ($fpr) fpr\n";
222 }
223 # user ids
224 s/^uid:[^:r]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) uid/;
225 # revoked user id
226 s/^uid:r[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*/ ($1) revuid/;
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 # output the remaining postscript
241 print <<EOF;
242 } def
243
244 /numlines $numlines def
245 /num w 16 sub 10 div numlines div def
246
247 /column {
248 /y w 20 sub def
249 1 1 num {
250 gsave
251 0 0 h 2 div w rectclip
252 /upper y 11 add def
253 key
254 newline
255 /lower y 11 add def
256 0 upper h 2 div upper h 2 div lower 0 lower 0 upper moveto lineto lineto lineto lineto stroke
257 grestore
258 } for
259 } def
260
261 w 0 translate
262 90 rotate
263 column
264 h 2 div 0 translate
265 column
266
267 showpage
268
269 %%Trailer
270 %%EOF
271 EOF
272
273 # done!
274 exit 0;
275
276
277 __END__
278
279 =head1 NAME
280
281 B<gpg-key2ps> - generates a PS file from a GnuPG keyring
282
283 =head1 SYNOPSIS
284
285 B<gpg-key2ps> [B<-r> I<revoked-style>] [B<-p> I<papersize>] I<keyid-or-name> [ I<...> ]
286
287 =head1 DESCRIPTION
288
289 gpg-key2ps generates a PostScript file with your OpenPGP key fingerprint (repeated
290 as often as it fits) useful for keysigning parties. The only argument is the same
291 as you would pass to GPG's list-keys command, either a key-id or a (partial) name.
292 The PS data is written to stdout.
293
294 =head1 OPTIONS
295
296 =over
297
298 =item B<-p> B<--paper-size> I<paper-size>
299
300 Select the output paper size. Default is to look into /etc/papersize or A4 if
301 libpaper isn't installed.
302
303 =item B<-r> B<--revoked-style> I<revoked-style>
304
305 Select how to mark revoked UIDs. Five styles are available:
306 B<hide> don't show at all (default),
307 B<show> show normally,
308 B<grey> display in 50% grey,
309 B<note> add "[revoked]", and
310 B<strike> strike through.
311
312 =item I<keyid>
313
314 Keyids to print. Multiple can be separated by spaces.
315
316 =item B<-h> B<--help>
317
318 Print usage and exit.
319
320 =item B<-v> B<--version>
321
322 Print version and exit.
323
324 =back
325
326
327 =head1 SEE ALSO
328
329 gpg(1)
330
331 http://pgp-tools.alioth.debian.org/
332
333 =head1 AUTHORS AND COPYRIGHT
334
335 (c) 2001 - 2005 Simon Richter <sjr@debian.org>
336
337 (c) 2005 Thijs Kinkhorst <thijs@kinkhorst.com>
338
339 (c) 2005 Christoph Berg <cb@df7cb.de>
340