File Coverage

blib/lib/Mail/Karmasphere/Parser/Record.pm
Criterion Covered Total %
statement 25 36 69.4
branch 13 22 59.0
condition 0 3 0.0
subroutine 10 12 83.3
pod 0 9 0.0
total 48 82 58.5


line stmt bran cond sub pod time code
1             package Mail::Karmasphere::Parser::Record;
2              
3 9     9   1466 use strict;
  9         20  
  9         338  
4 9     9   50 use warnings;
  9         16  
  9         6112  
5              
6             # acceptable identity types include RBLDNSd format identities:
7             # * IP: a CIDR netblock: 192.168.0.0/24
8             # * IP: a CIDR range: 192.168.0.1-192.168.0.255
9             # * IP: a single IP address: 192.168.0.1
10             # * domain: a domain name: foo.example.com
11             # * domain: a subdomain mask: .example.com
12             #
13             # also,
14             # * URI: some sort of http://whatnot/ or ftp://whatnot/, etc
15             #
16             # this can all be in UTF-8.
17              
18             my %keys = (
19             s => "stream",
20             # t => "type",
21             i => "identity",
22             v => "value",
23             );
24              
25             sub new {
26 57     57 0 170 my $class = shift;
27 57 50       285 my $self = ($#_ == 0) ? { %{ (shift) } } : { @_ };
  0         0  
28 57         162 for (keys %keys) {
29 171 50       411 die "No $keys{$_} ($_) in Record" unless defined $self->{$_};
30             }
31 57 100       245 $self->{t} = guess_identity_type($self->{i})
32             unless exists $self->{t};
33 57         398 return bless $self, $class;
34             }
35              
36             my $ip4p = q{(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9]{1,2})};
37             my $ip4s = "[.]";
38             my $ip4 = qq{(?:$ip4p(?:$ip4s$ip4p){0,3})};
39              
40             sub is_ip4 {
41 57     57 0 1549 return $_[0] =~ m!^$ip4(?:-$ip4|/[0-9]{1,2})?$!o;
42             }
43              
44             sub guess_identity_type {
45 57     57 0 4628 my $identity = shift;
46              
47 57 100       96 if (is_ip4($identity)) {
    100          
    100          
    100          
    50          
48 24         78 return 'ip4';
49             }
50             elsif ($identity =~ /^[0-9a-f:]{2,64}$/i) {
51 1         6 return 'ip6';
52             }
53             elsif ($identity =~ /^(https?|ftp):\/\//) {
54 8         44 return 'url';
55             }
56             elsif ($identity =~ /@/) {
57 3         9 return 'email';
58             }
59             elsif ($identity =~ /\.[a-z]{2,4}\.?$/) {
60 21         100 return 'domain';
61             }
62              
63 0         0 return 'unknown';
64             }
65              
66             sub stream {
67 57     57 0 168 return $_[0]->{s};
68             }
69              
70             sub type {
71 57     57 0 191 return $_[0]->{t};
72             }
73              
74             sub identity {
75 5     5 0 1554 return $_[0]->{i};
76             }
77              
78             sub value {
79 5     5 0 41 return $_[0]->{v};
80             }
81              
82             sub data {
83 5     5 0 20 return $_[0]->{d};
84             }
85              
86             sub _quote {
87 0     0     my $value = shift;
88 0 0         return $value unless $value =~ m/["', ]/;
89 0           $value =~ s/"/""/g;
90 0           return '"' . $value . '"';
91             }
92              
93             # poor man's CSV.
94             # produces one of
95             # 1.2.3.4
96             # 1.2.3.4,-1000 (or some other number)
97             # 1.2.3.4,1000,"because why"
98             #
99             # note that 1.2.3.4,1000 is NOT optimized away to just 1.2.3.4
100             # we cannot assume that the feed is a whitelist
101             #
102             sub as_string {
103 0     0 0   my $self = shift;
104 0           my $out = _quote($self->{i});
105              
106 0 0 0       $out .= "," . $self->{v} if (defined $self->{v} or
107             defined $self->{d});
108 0 0         $out .= "," . _quote($self->{d}) if (defined $self->{d});
109              
110             # print STDERR "v = $self->{v} -> $out\n";
111              
112 0           return $out;
113             }
114              
115             1;