File Coverage

blib/lib/Reprepro/Uploaders.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # Copyright (c) 2011 Raphael Pinson.
2             #
3             # This library is free software; you can redistribute it and/or
4             # modify it under the terms of the GNU Lesser Public License as
5             # published by the Free Software Foundation; either version 2.1 of
6             # the License, or (at your option) any later version.
7             #
8             # Config-Model is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11             # Lesser Public License for more details.
12             #
13             # You should have received a copy of the GNU Lesser Public License
14             # along with Config-Model; if not, write to the Free Software
15             # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16             # 02110-1301 USA
17              
18             package Reprepro::Uploaders;
19              
20 3     3   67836 use strict;
  3         7  
  3         122  
21 3     3   16 use warnings;
  3         8  
  3         115  
22 3     3   27 use base qw(Class::Accessor);
  3         7  
  3         2993  
23 3     3   10518 use Config::Augeas qw(get match);
  0            
  0            
24             use Text::Glob qw(match_glob);
25              
26             our $VERSION = '0.004';
27              
28             my %conditions_types = (
29             'source' => \&check_source,
30             'byhand' => \&check_byhand,
31             'sections' => \&check_items,
32             'binaries' => \&check_items,
33             'architectures' => \&check_items,
34             );
35              
36             sub new {
37             my $class = shift;
38             my %options = @_;
39              
40             my $self = __PACKAGE__->SUPER::new();
41              
42             $self->{uploaders} = $options{uploaders};
43             die "E: You must provide an uploders file" unless $self->{uploaders};
44              
45             $self->{debug} = $options{debug};
46             $self->{verbose} = $self->{debug};
47             $self->{verbose} ||= $options{verbose};
48              
49             $self->{augeas_opts} = $options{augeas_opts};
50             $self->setup_augeas();
51              
52             return $self;
53             }
54              
55             sub setup_augeas {
56             my ($self) = @_;
57              
58             $self->{augeas_opts}->{no_load} = 1;
59              
60             my $aug = Config::Augeas->new(%{$self->{augeas_opts}});
61             $aug->rm("/augeas/load/*");
62             $aug->set("/augeas/load/Reprepro_Uploaders/lens", "Reprepro_Uploaders.lns");
63             $aug->set("/augeas/load/Reprepro_Uploaders/incl", $self->{uploaders});
64             $aug->load();
65             $aug->match("/augeas/files//error") && die "E: Parsing failed";
66              
67             $self->{aug} = $aug;
68             }
69              
70             sub check_package {
71             my ($self, $package) = @_;
72              
73             my $key = $package->{'key'};
74              
75             my $key_condition = "by/key = '$key' or by/key = 'any'";
76             $key_condition .= " or by = 'anybody' or by = 'unsigned'";
77              
78             my $key_path = "/files/$self->{uploaders}/allow[$key_condition]";
79              
80             $self->{package} = $package;
81             @{$self->{errors}} = ();
82              
83             my @allows = $self->{aug}->match($key_path);
84              
85             if ($#allows < 0) {
86             push @{$self->{errors}}, "Unknown key $key";
87             return 0;
88             }
89              
90             foreach my $allow (@allows) {
91             return 1 if ($self->check_allow($allow));
92             }
93              
94             return 0;
95             }
96              
97             sub check_allow {
98             my ($self, $allow) = @_;
99              
100             my $aug = $self->{aug};
101             my $package = $self->{package};
102              
103             print "V: Checking against $allow:",$/ if $self->{verbose};
104             print $aug->print($allow).$/ if $self->{debug};
105            
106             my $allow_val = $aug->get($allow);
107             if ($allow_val && $allow_val eq '*') {
108             print "V: Wildcard found".$/ if $self->{verbose};
109             return 1;
110             }
111              
112             if ($self->check_condition_list($allow)) {
113             return 1;
114             }
115              
116             return 0;
117             }
118              
119             sub check_condition_list {
120             my ($self, $allow) = @_;
121              
122             my $aug = $self->{aug};
123             my $package = $self->{package};
124              
125             my @conditions = $aug->match("$allow/and");
126              
127             foreach my $condition (@conditions) {
128             return 0 unless ($self->check_condition($condition));
129             }
130              
131             return 1;
132             }
133              
134             sub check_condition {
135             my ($self, $condition) = @_;
136              
137             my $aug = $self->{aug};
138             my $package = $self->{package};
139              
140             my @conditions_or = $aug->match("$condition/or");
141              
142             my $not;
143              
144             foreach my $condition_or (@conditions_or) {
145             my $condition_type = $aug->get($condition_or);
146              
147             die "E: Unknown condition type $condition_type\n"
148             unless (defined $conditions_types{$condition_type});
149              
150             # A 'not' node invets the condition
151             $not = ($aug->match("$condition_or/not")) ? 1 : 0;
152              
153             if ($conditions_types{$condition_type}($self, $condition_or, $condition_type)) {
154             return 1-$not;
155             }
156             }
157              
158             return $not;
159             }
160              
161              
162             sub check_source {
163             my ($self, $condition, $field) = @_;
164              
165             my $aug = $self->{aug};
166             my $package = $self->{package};
167              
168             my $source = $package->{source};
169             my $value = $aug->get("$condition/or");
170              
171             if (match_glob($value, $source)) {
172             print "V: $field $source matches $value",$/ if $self->{verbose};
173             return 1;
174             } else {
175             print "V: $field $source does not match $value",$/ if $self->{verbose};
176             push @{$self->{errors}}, "$field $source does not match $value";
177             return 0;
178             }
179             }
180              
181             sub check_byhand {
182             my ($self, $condition) = @_;
183              
184             # TO BE IMPLEMENTED
185             }
186              
187             sub check_items {
188             my ($self, $condition, $field) = @_;
189              
190             my $aug = $self->{aug};
191             my $package = $self->{package};
192              
193             # A 'contain' node makes the test valid if only one item is valid
194             my $contain = 0;
195             $contain = 1 if ($aug->match("$condition/contain"));
196              
197             my $accepted = -1;
198             my @items = @{$package->{$field}};
199              
200             my $field_singular = $field;
201             $field_singular =~ s|s$||;
202              
203             ITEM: foreach my $item (@items) {
204             foreach my $value_n ($aug->match("$condition/or")) {
205             my $value = $aug->get($value_n);
206             if (match_glob($value, $item)) {
207             return 1 if ($contain);
208             $accepted++;
209             print "V: $field_singular $item matches $value",$/ if $self->{verbose};
210             next ITEM;
211             } else {
212             print "V: $field_singular $item does not match $value",$/ if $self->{verbose};
213             push @{$self->{errors}}, "$field_singular $item does not match $value";
214             }
215             }
216             }
217              
218             return ($accepted == $#items);
219             }
220              
221             1;
222              
223              
224             __END__