File Coverage

blib/lib/Config/OpenSSH/Authkey.pm
Criterion Covered Total %
statement 87 92 94.5
branch 25 34 73.5
condition 6 14 42.8
subroutine 19 20 95.0
pod 12 12 100.0
total 149 172 86.6


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