File Coverage

blib/lib/Config/OpenSSH/Authkey.pm
Criterion Covered Total %
statement 85 90 94.4
branch 25 34 73.5
condition 6 14 42.8
subroutine 18 19 94.7
pod 12 12 100.0
total 146 169 86.3


line stmt bran cond sub pod time code
1             # -*- Perl -*-
2             #
3             # Methods to interact with OpenSSH authorized_keys file data.
4              
5             package Config::OpenSSH::Authkey;
6              
7 1     1   24756 use strict;
  1         2  
  1         39  
8 1     1   6 use warnings;
  1         2  
  1         31  
9              
10 1     1   6 use Carp qw/croak/;
  1         3  
  1         226  
11 1     1   628 use Config::OpenSSH::Authkey::Entry ();
  1         34  
  1         31  
12              
13 1     1   7236 use IO::Handle qw(getline);
  1         9510  
  1         1484  
14              
15             our $VERSION = '1.04';
16              
17             ######################################################################
18             #
19             # Utility Methods - Internal
20              
21             {
22             # Utility class for comments or blank lines in authorized_keys files
23             package Config::OpenSSH::Authkey::MetaEntry;
24              
25             sub new {
26 23     23   1286 my $class = shift;
27 23         41 my $entry = shift;
28 23         85 bless \$entry, $class;
29             }
30              
31             sub as_string {
32 1     1   451 ${ $_[0] };
  1         11  
33             }
34             }
35              
36             ######################################################################
37             #
38             # Class methods
39              
40             sub new {
41 3     3 1 2357 my $class = shift;
42 3   100     18 my $options_ref = shift || {};
43              
44 3         28 my $self = {
45             _fh => undef,
46             _keys => [],
47             _seen_keys => {},
48             _auto_store => 0,
49             _tag_dups => 0,
50             _nostore_nonkey_data => 0
51             };
52              
53 3         8 for my $pref (qw/auto_store tag_dups nostore_nonkey_data/) {
54 9 100       26 if ( exists $options_ref->{$pref} ) {
55 3 50       13 $self->{"_$pref"} = $options_ref->{$pref} ? 1 : 0;
56             }
57             }
58              
59 3         11 bless $self, $class;
60 3         30 return $self;
61             }
62              
63             ######################################################################
64             #
65             # Instance methods
66              
67             sub fh {
68 1     1 1 3 my $self = shift;
69 1   33     4 my $fh = shift || croak 'fh requires a filehandle';
70              
71 1         3 $self->{_fh} = $fh;
72 1         16 return $self;
73             }
74              
75             sub file {
76 1     1 1 4 my $self = shift;
77 1   33     4 my $file = shift || croak 'file requires a file';
78              
79 1         2 my $fh;
80 1 50       60 open( $fh, '<', $file ) or croak $!;
81 1         2 $self->{_fh} = $fh;
82              
83 1         6 return $self;
84             }
85              
86             sub iterate {
87 16     16 1 7489 my $self = shift;
88 16 50       45 croak 'no filehandle to iterate on' if !defined $self->{_fh};
89              
90 16         503 my $line = $self->{_fh}->getline;
91 16 100       550 return defined $line ? $self->parse($line) : ();
92             }
93              
94             sub consume {
95 1     1 1 2 my $self = shift;
96 1 50       4 croak 'no filehandle to consume' if !defined $self->{_fh};
97              
98 1         8 my $old_auto_store = $self->auto_store();
99 1         3 $self->auto_store(1);
100              
101 1         38 while ( my $line = $self->{_fh}->getline ) {
102 15         456 $self->parse($line);
103             }
104              
105 1         36 $self->auto_store($old_auto_store);
106              
107 1         2 return $self;
108             }
109              
110             sub parse {
111 31     31 1 44 my $self = shift;
112 31   33     78 my $data = shift || croak 'need data to parse';
113              
114 31         33 my $entry;
115              
116 31 100       106 if ( $data =~ m/^\s*(?:#|$)/ ) {
117 22         36 chomp($data);
118 22         63 $entry = Config::OpenSSH::Authkey::MetaEntry->new($data);
119 22 50 33     124 if ( $self->{_auto_store} and !$self->{_nostore_nonkey_data} ) {
120 0         0 push @{ $self->{_keys} }, $entry;
  0         0  
121             }
122             } else {
123 9         39 $entry = Config::OpenSSH::Authkey::Entry->new($data);
124 8 100       21 if ( $self->{_tag_dups} ) {
125 4 100       18 if ( exists $self->{_seen_keys}->{ $entry->key } ) {
126 1         5 $entry->duplicate_of( $self->{_seen_keys}->{ $entry->key } );
127             } else {
128 3         11 $self->{_seen_keys}->{ $entry->key } = $entry;
129             }
130             }
131 8 50       21 push @{ $self->{_keys} }, $entry if $self->{_auto_store};
  8         16  
132             }
133              
134 30         410 return $entry;
135             }
136              
137             sub get_stored_keys {
138 7     7 1 536 shift->{_keys};
139             }
140              
141             sub reset_store {
142 1     1 1 3 my $self = shift;
143 1         3 $self->{_seen_keys} = {};
144 1         6 $self->{_keys} = [];
145 1         20 return $self;
146             }
147              
148             sub reset_dups {
149 0     0 1 0 my $self = shift;
150 0         0 $self->{_seen_keys} = {};
151 0         0 return $self;
152             }
153              
154             sub auto_store {
155 7     7 1 432 my $self = shift;
156 7         8 my $setting = shift;
157 7 100       19 if ( defined $setting ) {
158 3 50       10 $self->{_auto_store} = $setting ? 1 : 0;
159             }
160 7         20 return $self->{_auto_store};
161             }
162              
163             sub tag_dups {
164 3     3 1 1258 my $self = shift;
165 3         5 my $setting = shift;
166 3 100       10 if ( defined $setting ) {
167 1 50       4 $self->{_tag_dups} = $setting ? 1 : 0;
168             }
169 3         12 return $self->{_tag_dups};
170             }
171              
172             sub nostore_nonkey_data {
173 3     3 1 960 my $self = shift;
174 3         4 my $setting = shift;
175 3 100       9 if ( defined $setting ) {
176 1 50       4 $self->{_nostore_nonkey_data} = $setting ? 1 : 0;
177             }
178 3         10 return $self->{_nostore_nonkey_data};
179             }
180              
181             1;
182              
183             __END__