File Coverage

blib/lib/CGI/ACL.pm
Criterion Covered Total %
statement 61 75 81.3
branch 22 36 61.1
condition 4 9 44.4
subroutine 10 10 100.0
pod 4 4 100.0
total 101 134 75.3


line stmt bran cond sub pod time code
1             package CGI::ACL;
2              
3             # Author Nigel Horne: njh@bandsman.co.uk
4             # Copyright (C) 2017, Nigel Horne
5              
6             # Usage is subject to licence terms.
7             # The licence terms of this software are as follows:
8             # Personal single user, single computer use: GPL2
9             # All other users (including Commercial, Charity, Educational, Government)
10             # must apply in writing for a licence for use from Nigel Horne at the
11             # above e-mail.
12              
13 4     4   358707 use 5.006_001;
  4         11  
14 4     4   17 use warnings;
  4         5  
  4         136  
15 4     4   15 use strict;
  4         8  
  4         64  
16 4     4   1663 use namespace::clean;
  4         44129  
  4         15  
17 4     4   461 use Carp;
  4         6  
  4         169  
18 4     4   2003 use Net::CIDR;
  4         15306  
  4         2199  
19              
20             =head1 NAME
21              
22             CGI::ACL - Decide whether to allow a client to run this script
23              
24             =head1 VERSION
25              
26             Version 0.02
27              
28             =cut
29              
30             our $VERSION = '0.02';
31              
32             =head1 SYNOPSIS
33              
34             Does what it says on the tin.
35              
36             use CGI::Info;
37             use CGI::ACL;
38              
39             my $acl = CGI::ACL->new();
40             # ...
41             my $denied = $acl->all_denied(info => CGI::Info->new());
42              
43             =head1 SUBROUTINES/METHODS
44              
45             =head2 new
46              
47             Creates a CGI::ACL object.
48              
49             =cut
50              
51             sub new {
52 4     4 1 408661 my $proto = shift;
53 4   33     29 my $class = ref($proto) || $proto;
54              
55 4 50       11 return unless(defined($class));
56              
57 4 50       20 my %args = (ref($_[0]) eq 'HASH') ? %{$_[0]} : @_;
  0         0  
58              
59 4         13 return bless { }, $class;
60             }
61              
62             =head2 allow_ip
63              
64             Give an IP (or CIDR) that we allow to connect to us
65              
66             use CGI::ACL;
67              
68             # Allow Google to connect to us
69             my $acl = CGI::ACL->new()->allow_ip(ip => '8.35.80.39');
70              
71             =cut
72              
73             sub allow_ip {
74 3     3 1 679 my $self = shift;
75 3         4 my %params;
76            
77 3 50       22 if(ref($_[0]) eq 'HASH') {
    100          
78 0         0 %params = %{$_[0]};
  0         0  
79             } elsif(@_ % 2 == 0) {
80 2         3 %params = @_;
81             } else {
82 1         4 $params{'ip'} = shift;
83             }
84              
85 3 100       7 if(!defined($params{'ip'})) {
86 1         4 Carp::carp 'Usage: allow_ip($ip_address)';
87             } else {
88 2         7 $self->{_allowed_ips}->{$params{'ip'}} = 1;
89             }
90 3         206 return $self;
91             }
92              
93             =head2 deny_country
94              
95             Give a country, or a reference to a list of countries, that we will not allow to access us
96              
97             use CGI::ACL;
98              
99             # Don't allow the UK to connect to us
100             my $acl = CGI::ACL->new()->deny_country('UK');
101              
102             =cut
103              
104             sub deny_country {
105 1     1 1 960 my $self = shift;
106 1         2 my %params;
107            
108 1 50       16 if(ref($_[0]) eq 'HASH') {
    50          
109 0         0 %params = %{$_[0]};
  0         0  
110             } elsif(@_ % 2 == 0) {
111 0         0 %params = @_;
112             } else {
113 1         3 $params{'country'} = shift;
114             }
115              
116 1 50       4 if(!defined($params{'country'})) {
117 0         0 Carp::carp 'Usage: deny_country($country)';
118             } else {
119             # This shenanegans allows country to be a scalar or list
120 1         2 my $c = $params{'country'};
121 1 50       3 if(ref($c) eq 'ARRAY') {
122 0         0 foreach my $country(@{$c}) {
  0         0  
123 0         0 $self->{_deny_countries}->{lc($country)} = 1;
124             }
125             } else {
126 1         5 $self->{_deny_countries}->{lc($c)} = 1;
127             }
128             }
129 1         2 return $self;
130             }
131              
132             =head2 all_denied
133              
134             If any of the restrictions return false, return false, which should allow access
135              
136             use CGI::Info;
137             use CGI::Lingua;
138             use CGI::ACL;
139              
140             # Allow Google to connect to us
141             my $acl = CGI::ACL->new()->allow_ip(ip => '8.35.80.39');
142              
143             if($acl->all_denied(info => CGI::Info->new())) {
144             print 'You are not allowed to view this site';
145             return;
146             }
147              
148             $acl = CGI::ACL->new()->deny_country(country => 'br');
149              
150             if($acl->all_denied(lingua => CGI::Lingua->new(supported => ['en']))) {
151             print 'Brazilians cannot view this site for now';
152             return;
153             }
154              
155             =cut
156              
157             sub all_denied {
158 5     5 1 2451 my $self = shift;
159              
160 5 50 66     22 if((!defined($self->{_allowed_ips})) && !defined($self->{_deny_countries})) {
161 1         13 return 0;
162             }
163              
164 4 50       10 my $addr = $ENV{'REMOTE_ADDR'} ? $ENV{'REMOTE_ADDR'} : '127.0.0.1';
165              
166 4 50       7 if($self->{_allowed_ips}) {
167 4 100       9 if($self->{_allowed_ips}->{$addr}) {
168 1         4 return 0;
169             }
170              
171 3         4 my @cidrlist;
172 3         1 foreach my $block(keys(%{$self->{_allowed_ips}})) {
  3         7  
173 3         11 @cidrlist = Net::CIDR::cidradd($block, @cidrlist);
174             }
175 3 100       621 if(Net::CIDR::cidrlookup($addr, @cidrlist)) {
176 1         103 return 0;
177             }
178             }
179              
180 2         272 my %params;
181            
182 2 100       8 if(ref($_[0]) eq 'HASH') {
    50          
183 1         2 %params = %{$_[0]};
  1         4  
184             } elsif(@_ % 2 == 0) {
185 0         0 %params = @_;
186             } else {
187 1         2 $params{'info'} = shift;
188             }
189              
190 2 0 33     6 if((!defined($params{'info'})) && !defined($params{'lingua'})) {
191 0         0 Carp::carp 'Usage: all_denied($info/$lingua)';
192 0         0 return 1;
193             }
194              
195 2 50       6 if(my $lingua = $params{'lingua'}) {
196 0         0 return $self->{_deny_countries}->{$lingua->country()};
197             }
198              
199 2         7 return 1;
200             }
201              
202             =head1 AUTHOR
203              
204             Nigel Horne, C<< >>
205              
206             =head1 BUGS
207              
208             Please report any bugs or feature requests to C,
209             or through the web interface at
210             L.
211             I will be notified, and then you'll
212             automatically be notified of progress on your bug as I make changes.
213              
214             =head1 SEE ALSO
215              
216             L
217              
218             =head1 SUPPORT
219              
220             You can find documentation for this module with the perldoc command.
221              
222             perldoc CGI::ACL
223              
224             You can also look for information at:
225              
226             =over 4
227              
228             =item * RT: CPAN's request tracker
229              
230             L
231              
232             =item * AnnoCPAN: Annotated CPAN documentation
233              
234             L
235              
236             =item * CPAN Ratings
237              
238             L
239              
240             =item * Search CPAN
241              
242             L
243              
244             =back
245              
246             =head1 LICENSE AND COPYRIGHT
247              
248             Copyright 2017 Nigel Horne.
249              
250             This program is released under the following licence: GPL
251              
252             =cut
253              
254             1; # End of CGI::ACL