File Coverage

blib/lib/String/BlackWhiteList.pm
Criterion Covered Total %
statement 42 43 97.6
branch 17 18 94.4
condition 6 6 100.0
subroutine 7 7 100.0
pod 3 3 100.0
total 75 77 97.4


line stmt bran cond sub pod time code
1 2     2   60718 use 5.008;
  2         9  
  2         72  
2 2     2   11 use strict;
  2         3  
  2         68  
3 2     2   9 use warnings;
  2         5  
  2         109  
4              
5             package String::BlackWhiteList;
6             our $VERSION = '1.100860';
7             # ABSTRACT: Match a string against a blacklist and a whitelist
8 2     2   1741 use parent 'Class::Accessor::Complex';
  2         729  
  2         11  
9             __PACKAGE__
10             ->mk_new
11             ->mk_scalar_accessors(qw(black_re white_re))
12             ->mk_array_accessors(qw(blacklist whitelist))
13             ->mk_boolean_accessors(qw(is_literal_text));
14              
15             sub update {
16 4     4 1 1288 my $self = shift;
17 4         14 my @blacklist = $self->blacklist;
18 4         61 my @whitelist = $self->whitelist;
19 4         49 my %seen;
20 4         81 $seen{$_} = 1 for @blacklist;
21 4         9 for (@whitelist) {
22 100 50       182 next unless $seen{$_};
23 0         0 warn "[$_] is both blacklisted and whitelisted\n";
24             }
25 4         18 my $is_literal_text = $self->is_literal_text; # caching
26 84 100       200 my $black_re =
27             join '|',
28 4         32 map { $is_literal_text ? '\b' . quotemeta($_) . '(\b|\s|$)' : $_ }
29             $self->blacklist;
30 4         449 $self->black_re(qr/$black_re/i);
31 100 100       233 my $white_re =
32             join '|',
33 4         55 map { $is_literal_text ? '\b' . quotemeta($_) . '(\b|\s|$)' : $_ }
34             $self->whitelist;
35 4         431 $self->white_re(qr/$white_re/i);
36 4         88 $self;
37             }
38              
39             sub valid {
40 93     93 1 41142 my ($self, $s) = @_;
41 93 100 100     478 return 1 unless defined $s && length $s;
42 91         263 my $white_re = $self->white_re;
43 91         662 my $black_re = $self->black_re;
44 91 100       1680 if ($s =~ s/$white_re//gi) {
    100          
45              
46             # If part of the string matches the whitelist, but another part of it
47             # matches the blacklist, it is still considered invalid. So we deleted
48             # the part that matched the whitelist and examine the remainder.
49             #
50             # This is necessary because the blacklist can be more general than the
51             # whitelist. For example, you are testing whether a street address
52             # string is a pobox, and you put 'Post' and 'P.O. BOX' in the
53             # blacklist, but put 'Post Street' in the blacklist. Now it's clear
54             # why we had to delete the part that matched the whitelist. Also
55             # consider the case of 'P.O. BOX 37, Post Street 9'.
56 51         589 return $s !~ qr/$black_re/i;
57             } elsif ($s =~ qr/$black_re/i) {
58 32         99 return 0;
59             } else {
60 8         29 return 1;
61             }
62             }
63              
64             sub valid_relaxed {
65 87     87 1 47476 my ($self, $s) = @_;
66 87 100 100     471 return 1 unless defined $s && length $s;
67 85         281 my $white_re = $self->white_re;
68 85         759 my $black_re = $self->black_re;
69 85 100       1827 return 1 if $s =~ qr/$white_re/i;
70 34 100       438 return 0 if $s =~ qr/$black_re/i;
71 6         24 return 1;
72             }
73             1;
74              
75              
76             __END__