#!/usr/bin/perl

use warnings;
use strict;

# Version: 1.1
# Date:    2001.01.07
# Revised: 2004.04.06
# Author:  V. Alex Brennen <vab@cryptnet.net>
#          http://www.cryptnet.net/people/vab/
# Author:  Gerfried Fuchs <alfie@ist.org>
#          http://alfie.ist.org/alfie/
# License: Public Domain
# Description:
#          This script was written as part of the gpg keysigning
#          party howto.  It generates a checklist for individuals
#          participating in a keysigning party. The keysigning
#          howto lives at:
#               http://www.cryptnet.net/fdp/crypto/gpg-party.html


die "usage: $0 <keyring>\n" if (@ARGV != 1);

my $keyring = $ARGV[0];

my $gpgopts = "--quiet --no-options --no-default-keyring --keyring $keyring "
            . "--homedir . --no-auto-check-trustdb 2>/dev/null";

my @fps = `gpg --fingerprint --with-colons $gpgopts | egrep '^(pub|fpr):'`;

# see include/cipher.h in the gnupg source
my %keytypes = (
    1   => "RSA",
    2   => "RSA",       # encrypt only
    3   => "RSA",       # sign only
    16  => "Elgamal",   # encrypt only
    17  => "DSA",
    20  => "Elgamal",
);

my %keys;
while(my $line = shift(@fps)) {
    if($line =~ /^pub/) {
        # get the key information
        my ($size,$type,$longid,$owner) = (split /:/, $line)[2,3,4,9];
        my $id = substr($longid, 8);
        my $fingerprint = (split /:/, shift(@fps))[9];

        # get all user id's
        my $uids;
        for (`gpg --list-key --with-colons $gpgopts $longid | egrep '^(pub|uid)'`) {
            chomp;
            next if (split /:/)[1] =~ /r/;
            $uids .= "\n        " . tohtml((split /:/)[9]) . "<BR>";
        }

        # convert numeric type to a nice string
        $type = $keytypes{$type} if (exists($keytypes{$type}));

        # split the fingerprint for better readability
        if(length($fingerprint) == 40) {
            for my $i (36,32,28,24,20,16,12,8,4) {
                my $char = ($i == 20) ? "\n" : " ";
                substr($fingerprint, $i, 0, $char);
            }
        }
        elsif (length($fingerprint) == 32) {
            for my $i (30,28,26,24,22,20,18,16,14,12,10,8,6,4,2) {
                my $char = ($i == 16) ? "\n" : " ";
                substr($fingerprint, $i, 0, $char);
            }
        }

        # convert some strings into proper HTML
        $owner = tohtml($owner);
        $fingerprint = tohtml($fingerprint);

        # add the key info to a hash which we can sort on
        $keys{$owner} = {
            id          => $id,
            owner       => $uids,
            fingerprint => $fingerprint,
            size        => $size,
            type        => $type,
        };
    }
}

# spit out the HTML
print << "EOH";
<HTML>
<HEAD>
    <TITLE>CPLUG Keysigning Party Keys</TITLE>
    <STYLE TYPE=text/css>
        body    { font-family: monospace; }
        table   { empty-cells:show; }
        td      { padding: 5; }
    </STYLE>
</HEAD>

<BODY>

<TABLE BORDER=1>
<TR>
    <TH>Key ID</TH>
    <TH>Owner</TH>
    <TH>Fingerprint</TH>
    <TH>Size</TH>
    <TH>Type</TH>
    <TH>Key Info Matches?</TH>
    <TH>Owner ID Matches?</TH>
</TR>

EOH

for my $key (sort keys %keys) {
    print << "EOR";
<TR>
    <TD>$keys{$key}{"id"}</TD>
    <TD>$keys{$key}{"owner"}
    </TD>
    <TD NOWRAP>$keys{$key}{"fingerprint"}</TD>
    <TD>$keys{$key}{"size"}</TD>
    <TD>$keys{$key}{"type"}</TD>
    <TD></TD>
    <TD></TD>
</TR>

EOR
}

print << "EOF";
</TABLE>
</BODY></HTML>
EOF

# convert some string to proper html entities
sub tohtml {
    my $str = shift;
    $str =~ s/&/&amp;/;
    $str =~ s/</&lt\;/;
    $str =~ s/>/&gt\;/;
    $str =~ s/\n/<BR>/m;
    return $str;
}
