File Coverage

blib/lib/PGP/Finger/Keyserver.pm
Criterion Covered Total %
statement 12 48 25.0
branch 0 8 0.0
condition n/a
subroutine 4 8 50.0
pod 0 1 0.0
total 16 65 24.6


line stmt bran cond sub pod time code
1             package PGP::Finger::Keyserver;
2              
3 1     1   4 use Moose;
  1         2  
  1         5  
4              
5             extends 'PGP::Finger::Source';
6              
7             # ABSTRACT: gpgfinger source to query a keyserver
8             our $VERSION = '1.1'; # VERSION
9              
10 1     1   4828 use LWP::UserAgent;
  1         29078  
  1         30  
11              
12 1     1   8 use PGP::Finger::Result;
  1         1  
  1         24  
13 1     1   4 use PGP::Finger::Key;
  1         1  
  1         394  
14              
15             has _agent => ( is => 'ro', isa => 'LWP::UserAgent', lazy => 1,
16             default => sub {
17             LWP::UserAgent->new;
18             },
19             );
20              
21             has 'exact' => ( is => 'rw', isa => 'Bool', default => 1 );
22              
23             has 'url' => ( is => 'rw', isa => 'Str',
24             default => 'http://a.keyserver.pki.scientia.net/pks/lookup',
25             );
26              
27             sub fetch {
28 0     0 0   my ( $self, $addr ) = @_;
29 0           my @ids = $self->_query_index( $addr );
30 0           my $result = PGP::Finger::Result->new( source => 'keyserver' );
31              
32 0           foreach my $id ( @ids ) {
33 0           my $armored = $self->_retrieve_keys('0x'.$id);
34 0           my $key = PGP::Finger::Key->new_armored(
35             mail => $addr,
36             data => $armored,
37             );
38 0           $key->set_attr( source => 'keyserver' );
39 0           $key->set_attr( url => $self->url );
40 0           $key->set_attr( keyid => $id );
41 0           $result->add_key( $key );
42             }
43              
44 0           return $result;
45             }
46              
47             sub _get {
48 0     0     my ( $self, %params ) = @_;
49 0           my $uri = URI->new( $self->url );
50 0           $uri->query_form( \%params );
51 0           my $request = HTTP::Request->new('GET', $uri);
52 0           my $response = $self->_agent->request( $request );
53 0 0         if( ! $response->is_success ) {
54 0           die("keylookup for $uri failed: ".$response->status_line);
55             }
56 0           return $response;
57             }
58              
59             sub _retrieve_keys {
60 0     0     my ( $self, $id ) = @_;
61 0           my $response = $self->_get(
62             search => $id,
63             op => 'get',
64             exact => $self->exact,
65             options => 'mr',
66             );
67 0 0         if( $response->content !~ /^-----BEGIN PGP PUBLIC KEY BLOCK-----/) {
68 0           die('returned content is not a PGP public key');
69             }
70 0           return $response->content;
71             }
72              
73             sub _query_index {
74 0     0     my ( $self, $addr ) = @_;
75 0           my @ids;
76 0           my $response = $self->_get(
77             search => $addr,
78             op => 'index',
79             exact => $self->exact,
80             options => 'mr',
81             );
82 0           my @lines = split(/\r?\n/, $response->content);
83             # info:<version>:<count>
84             # pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
85             # ...
86 0           shift(@lines);
87 0           while( my $line = shift(@lines) ) {
88 0 0         if( $line !~ /^pub:/) { next; }
  0            
89 0 0         if( $line =~ /^pub:([^:]+):/) {
90 0           push( @ids, $1 );
91             } else {
92 0           die("unknown line format: ".$line);
93             }
94             }
95 0           return( @ids );
96             }
97              
98             1;
99              
100             __END__
101              
102             =pod
103              
104             =encoding UTF-8
105              
106             =head1 NAME
107              
108             PGP::Finger::Keyserver - gpgfinger source to query a keyserver
109              
110             =head1 VERSION
111              
112             version 1.1
113              
114             =head1 AUTHOR
115              
116             Markus Benning <ich@markusbenning.de>
117              
118             =head1 COPYRIGHT AND LICENSE
119              
120             This software is Copyright (c) 2015 by Markus Benning.
121              
122             This is free software, licensed under:
123              
124             The GNU General Public License, Version 2 or later
125              
126             =cut