Add a changelog
[pgp-tools.git] / keylookup / keylookup
index 0b46a69ae234696d7c564e4b0d28fc45415fee82..a69f888ec8857a0eea50a2f0e9c3c14abd194b80 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl -w
 
-# (c) 2000, 2002 Christian Kurz <shorty@debian.org>,
-#                Peter Palfrader <peter@palfrader.org>
+# Copyright (c) 2000, 2002 Christian Kurz <shorty@debian.org>,
+# Copyright (c) 2000, 2002, 2005 Peter Palfrader <peter@palfrader.org>
 #
 # $Id$
 #
 #
 #   You should have received a copy of the GNU General Public License
 #   along with this program; if not, write to the Free Software Foundation,
-#   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#   Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 #
-# Keylookup homepage: http://www.palfrader.org/keylookup/
-#           CVS, BTS: http://savannah.gnu.org/projects/keylookup/
+# Keylookup is part of pgp-tools:
+#           http://pgp-tools.alioth.debian.org/
+#           svn://svn.debian.org/pgp-tools/trunk/
+#           http://svn.debian.org/wsvn/pgp-tools/trunk/
 
-delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV', 'PATH'};
+delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
 $|=1; # Always flush buffers
 
 
@@ -33,11 +35,6 @@ use Getopt::Long;
 
 my $version = '3.0 ($Id$)';
 
-# Where to find GnuPG's options file.
-# Full path to the dialog and whiptail executeable.
-my $Dialog = '/usr/bin/dialog';
-my $Whiptail = '/usr/bin/whiptail';
-
 # Strings to use in the dialog|whiptail frontend
 my $TITLE = 'Import Keys';
 my $BACKTITLE = 'KeyLookup $Revision$';
@@ -93,7 +90,7 @@ sub getHits($) {
                push @ops, '--with-colons';
                push @ops, '--fixed-list-mode';
                push @ops, '--search';
-               push @ops, $options->{'search'};
+               push @ops, @{$options->{'search'}};
                exec(@ops);
                die ("Cannot exec GnuPG: $!\n");
        };
@@ -102,16 +99,14 @@ sub getHits($) {
 
        while (<KID>) {
                chomp;
+               if ( $_ eq "" ) { next; }
                my ($type, undef) = split /:/;
                if ($type eq 'pub') {
                        my ($type, $keyid, $algo, $bits, $created, undef, $revoked) = split /:/;
-                       my (undef,undef,undef,$mday,$mon,$year,undef,undef,undef) = localtime ($created);
                        $currentKey = { 'bits' => $bits,
                                        'type' => (defined $ALGOS{$algo} ? $ALGOS{$algo} : '#'.$algo),
                                        'keyid' => $keyid,
-                                       'year' => $year+1900,
-                                       'month' => $mon+1,
-                                       'day' => $mday,
+                                       'created' => $created,
                                        'revoked' => $revoked,
                                        'uid' => []
                                      };
@@ -169,13 +164,15 @@ sub prepareForDialog {
        my $keys = shift;
        my @keyargs = ();
 
-       for my $keyid (keys %$keys) {
+       for my $keyid (sort {- ($keys->{$a}->{'created'} <=> $keys->{$b}->{'created'})} keys %$keys) {
                for (@{ $keys->{$keyid}->{'uid'} }) {
                        push @keyargs,
                                $keys->{$keyid}->{'keyid'},
                                length() <= $MAX_UID_FIELD_LEN ? $_ : substr($_, 0, $MAX_UID_FIELD_LEN-2) . '..',
                                'off';
                };
+               my (undef,undef,undef,$mday,$mon,$year,undef,undef,undef) = localtime ($keys->{$keyid}->{'created'});
+               push @keyargs, $keys->{$keyid}->{'keyid'}, sprintf( "[created: %s-%s-%s]", $year+1900, $mon+1, $mday ), 'off';
                push @keyargs, '-'x8, '-'x40, 'off';
        };
        pop @keyargs;
@@ -189,14 +186,13 @@ sub prepareForTXT {
        my $keys = shift;
        my @lines = ();
 
-       for my $keyid (keys %$keys) {
+       for my $keyid (sort {- ($keys->{$a}->{'created'} <=> $keys->{$b}->{'created'})} keys %$keys) {
+               my (undef,undef,undef,$mday,$mon,$year,undef,undef,undef) = localtime ($keys->{$keyid}->{'created'});
                push @lines, sprintf( "%s%s/%s %s-%s-%s\n",
                                      $keys->{$keyid}->{'bits'},
                                      $keys->{$keyid}->{'type'},
                                      $keys->{$keyid}->{'keyid'},
-                                     $keys->{$keyid}->{'year'},
-                                     $keys->{$keyid}->{'month'},
-                                     $keys->{$keyid}->{'day'} );
+                                     $year+1900, $mon+1, $mday );
                push @lines, map { ' 'x26 . $_ . "\n" } @{ $keys->{$keyid}->{'uid'} };
                push @lines, "\n";
        };
@@ -214,7 +210,8 @@ sub callDialog {
        
        my %unique;
        my @keys = grep { !$unique{$_}++ }
-               grep { /^[0-9A-Fa-f]{8}$/ }
+               # get the keyID; can be 8, 16 or 40 nibbles
+               grep { /^((([a-zA-Z0-9]{24})?[a-zA-Z0-9]{8})?[a-zA-Z0-9]{8})$/ }
                map { s/\s//g; $_ } <ERRFH>;
        wait;
 
@@ -232,14 +229,14 @@ sub selectKeys {
        $frontend = 'dialog' unless (defined $frontend);
 
        if ($frontend eq 'dialog') {
-               unless (-x $Dialog) {
-                       warn("Dialog ($Dialog) not executeable/installed. Falling back to Whiptail\n");
+               unless (`which dialog` && $? == 0) {
+                       warn("Dialog not executeable/installed. Falling back to Whiptail\n");
                        $frontend = 'whiptail';
                }
        };
        if ($frontend eq 'whiptail') {
-               unless (-x $Whiptail ) {
-                       warn("Whiptail ($Whiptail) not executeable/installed. Falling back to plain\n");
+               unless (`which whiptail` && $? == 0 ) {
+                       warn("Whiptail not executeable/installed. Falling back to plain\n");
                        $frontend = 'plain';
                }
        };
@@ -247,7 +244,7 @@ sub selectKeys {
        if ( $frontend eq 'dialog' ) {
                calcDialogSize;
                my @ARGS = (
-                       $Dialog,
+                       'dialog',
                        '--backtitle',
                        $BACKTITLE,
                        '--separate-output',
@@ -261,7 +258,7 @@ sub selectKeys {
        } elsif ( $frontend eq 'whiptail' ) {
                calcDialogSize;
                my @ARGS = (
-                       $Whiptail,
+                       'whiptail',
                        '--backtitle',
                        $BACKTITLE,
                        '--separate-output',
@@ -300,7 +297,7 @@ sub importKeys {
        push @args,  '--recv-keys';
        for my $keyid (@$keyids) {
                # untaint keyids
-               my ($cleanid) = $keyid =~ /^([a-zA-Z0-9]{8})$/;
+               my ($cleanid) = $keyid =~ /^((([a-zA-Z0-9]{24})?[a-zA-Z0-9]{8})?[a-zA-Z0-9]{8})$/;
                warn ("keyid '$keyid' has unexpected format - skipping\n"), next
                        unless defined $cleanid;
                push @args, $cleanid;
@@ -345,13 +342,14 @@ sub version {
 
        ## Take all additional arguments to the program as a search target,
        ## escape the string for use in URLs.
-       $options{'search'} = join ' ', @ARGV;
-       $options{'search'} =~ s/ ( [^A-Za-z0-9] )
-                              / '%' . unpack("H2", $1)
-                              /xeg;
+       $options{'search'} = \@ARGV;
        my $keys = getHits( \%options );
        my $keyids;
 
+       if (scalar keys %$keys == 0) {
+               print "GnuPG did not find any keys matching your search string.\n";
+               exit 0;
+       };
        if ($options{'importall'}) {
                my @allkeys = keys %$keys;
                $keyids = \@allkeys;