File Coverage

blib/lib/Config/OpenSSH/Authkey.pm
Criterion Covered Total %
statement 88 93 94.6
branch 25 34 73.5
condition 6 14 42.8
subroutine 19 20 95.0
pod 12 12 100.0
total 150 173 86.7


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