File Coverage

blib/lib/Net/Defensio.pm
Criterion Covered Total %
statement 87 104 83.6
branch 21 36 58.3
condition 21 50 42.0
subroutine 10 15 66.6
pod 8 13 61.5
total 147 218 67.4


line stmt bran cond sub pod time code
1             package Net::Defensio;
2              
3             # TODO: XML format support, YAML::Syck support
4              
5 6     6   241547 use strict;
  6         15  
  6         247  
6 6     6   3792 use Net::Defensio::Response;
  6         19  
  6         64  
7              
8             our $VERSION = '0.02';
9             our $ERROR;
10             our $API_VERSION = '1.1';
11              
12             my $UA = "Perl-Net-Defensio/$VERSION";
13              
14             our $REQUEST_PARAMS = {
15             'validate-key' => { required => [ qw( owner-url ) ] },
16             'announce-article' => { required => [ qw( owner-url article-author
17             article-author-email article-title article-content permalink ) ] },
18             'audit-comment' => { required => [ qw( owner-url user-ip
19             article-date comment-author comment-author-email
20             comment-type ) ],
21             optional => [ qw( comment-content
22             comment-author-url permalink referrer user-logged-in
23             trusted-user test-force ) ] },
24             'report-false-negatives' => { required => [ qw( owner-url
25             signatures ) ] },
26             'report-false-positives' => { required => [ qw( owner-url
27             signatures ) ] },
28             'get-stats' => { required => [ qw( owner-url ) ] },
29             };
30             our $RESPONSE_PARAMS = {
31             'validate-key' => [ qw( status message api-version ) ],
32             'announce-article' => [ qw( status message api-version ) ],
33             'audit-comment' => [ qw( status message api-version signature
34             spam spaminess ) ],
35             'report-false-negatives' => [ qw( status message api-version ) ],
36             'report-false-positives' => [ qw( status message api-version ) ],
37             'get-stats' => [ qw( status message api-version accuracy spam ham
38             false-positives false-negatives learning learning-message ) ],
39             };
40              
41             sub new {
42 3     3 1 41 my $pkg = shift;
43 3 50       13 $pkg = ref $pkg if ref $pkg;
44              
45 3         14 my (%param) = @_;
46              
47 3 50       12 return $pkg->error("Required parameter missing: 'api_key'")
48             unless $param{api_key};
49              
50 3         12 my $obj = { api_key => $param{api_key} };
51 3         10 $obj->{user_agent} = delete $param{user_agent};
52 3   33     29 $obj->{agent} = delete $param{agent} || $UA;
53 3   33     17 $obj->{api_version} = delete $param{api_version} || $API_VERSION;
54 3   50     20 $obj->{host} = delete $param{host} || 'api.defensio.com';
55 3   50     20 $obj->{format} = delete $param{format} || 'yaml';
56 3   100     17 $obj->{service_type} = delete $param{service_type} || 'app';
57 3   50     22 $obj->{protocol} = delete $param{protocol} || 'http';
58 3   50     22 $obj->{port} = delete $param{port} || 80;
59              
60 3         14 return bless $obj, $pkg;
61             }
62              
63             sub user_agent {
64 4     4 1 7 my $obj = shift;
65 4 50       16 $obj->{user_agent} = shift if @_;
66 4 100       20 return $obj->{user_agent} if $obj->{user_agent};
67 3         3742 require LWP::UserAgent;
68 3         183573 return $obj->{user_agent} = LWP::UserAgent->new;
69             }
70              
71             sub service_url {
72 4     4 0 8 my $obj = shift;
73 4         21 my (%param) = @_;
74              
75 4 50       17 my $action = $param{action}
76             or return $obj->error("'action' parameter required");
77              
78 4   33     51 my $protocol = $param{protocol} || $obj->{protocol};
79 4   33     29 my $host = $param{host} || $obj->{host};
80 4   33     25 my $port = $param{port} || $obj->{port};
81 4 50 33     29 if (($port ne '') && ($port != 80)) {
82 0         0 $port = ':' . $port;
83             } else {
84 4         9 $port = '';
85             }
86 4   33     61 my $service_type = $param{service_type} || $obj->{service_type};
87 4   33     27 my $api_version = $param{api_version} || $obj->{api_version};
88 4   33     23 my $api_key = $param{api_key} || $obj->{api_key};
89 4   33     22 my $format = $param{format} || $obj->{format};
90              
91 4         26 my $url = join "/", "$protocol:/", "$host$port",
92             $service_type, $api_version, $action, "$api_key.$format";
93              
94 4         23 return $url;
95             }
96              
97             sub safe_submit {
98 4     4 0 9 my $obj = shift;
99 4         10 my ($action, $param) = @_;
100              
101 4 50       20 return $obj->error("Invalid request for unknown '$action'")
102             unless exists $REQUEST_PARAMS->{$action};
103              
104 4   50     22 my $req_params = $REQUEST_PARAMS->{$action}{required} || [];
105 4   100     23 my $opt_params = $REQUEST_PARAMS->{$action}{optional} || [];
106 4         8 my %req_param;
107             my @params;
108              
109 4         10 foreach my $p (@$req_params) {
110 14         50 (my $under_p = $p) =~ s/-/_/g;
111 14         18 my $val;
112 14         25 foreach ($p, $under_p, lc($under_p)) {
113 28 100       204 $val = $param->{$_}, last if exists $param->{$_};
114             }
115 14 50       35 return $obj->error("Required parameter missing: '$p'")
116             unless defined $val;
117 14 50       51 push @params, $p, $val if defined $val;
118             }
119 4         9 foreach my $p (@$opt_params) {
120 14         31 (my $under_p = $p) =~ s/-/_/g;
121 14         66 my $val;
122 14         24 foreach ($p, $under_p, lc($under_p)) {
123 26 100       61 $val = $param->{$_}, last if exists $param->{$_};
124             }
125 14 100       35 push @params, $p, $val if defined $val;
126             }
127              
128 4   33     54 my $service_url = $param->{'service-url'} || $param->{service_url} ||
129             $obj->service_url( action => $action, %$param );
130              
131 4         19 my $response = $obj->user_agent->post( $service_url, \@params );
132              
133 4 50 33     2263895 if ($response && !$response->is_success()) {
    50          
134 0         0 return $obj->error("Error with $action request: "
135             . $response->status_line);
136             }
137             elsif (!$response) {
138 0         0 return $obj->error("Error with $action request");
139             }
140              
141 4         92 $obj->process_http_response($action, $response);
142             }
143              
144             sub process_http_response {
145 4     4 0 9 my $obj = shift;
146 4         12 my ($action, $http_resp) = @_;
147              
148 4         34 my $content = $http_resp->content();
149 4         55 my $result = {};
150 4 50       25 if ($content =~ m/^\s*<\?xml/) {
151             # process as xml!
152             }
153             else {
154             # process as yaml!
155 4         4807 require YAML::Tiny;
156 4         31238 my $y = YAML::Tiny->read_string($content);
157 4         3743 my $doc = $y->[0];
158 4         20 my $resp_params = $RESPONSE_PARAMS->{$action};
159 4         47 foreach my $p (@$resp_params) {
160 25         59 my $val = $doc->{'defensio-result'}{$p};
161 25         51 $p =~ s/-/_/g;
162 25 100       105 if (defined $val) {
163 23         148 $result->{$p} = $val;
164             }
165             }
166             }
167 4         15 $result->{action} = $action;
168 4         70 return Net::Defensio::Response->new($result);
169             }
170              
171             # API methods
172              
173             sub validate_key {
174 1     1 1 89 my $obj = shift;
175 1         4 my (%param) = @_;
176 1         6 $obj->safe_submit('validate-key', \%param);
177             }
178              
179             sub announce_article {
180 0     0 1 0 my $obj = shift;
181 0         0 my (%param) = @_;
182 0         0 $obj->safe_submit('announce-article', \%param);
183             }
184              
185             sub audit_comment {
186 2     2 1 16 my $obj = shift;
187 2         23 my (%param) = @_;
188 2         9 $obj->safe_submit('audit-comment', \%param);
189             }
190              
191             sub report_false_negatives {
192 0     0 1 0 my $obj = shift;
193 0         0 my (%param) = @_;
194 0         0 $obj->safe_submit('report-false-negatives', \%param);
195             }
196              
197             sub report_false_positives {
198 0     0 1 0 my $obj = shift;
199 0         0 my (%param) = @_;
200 0         0 $obj->safe_submit('report-false-positives', \%param);
201             }
202              
203             sub get_stats {
204 1     1 1 10 my $obj = shift;
205 1         3 my (%param) = @_;
206 1         6 $obj->safe_submit('get-stats', \%param);
207             }
208              
209             # Error API
210              
211             sub errstr {
212 0     0 0   my $pkg = shift;
213 0 0         return ref($pkg) ? $pkg->{error} : $ERROR;
214             }
215              
216             sub error {
217 0     0 0   my $pkg = shift;
218 0 0         (ref($pkg) ? $pkg->{error} : $ERROR) = shift;
219 0           return undef;
220             }
221              
222             1;
223             __END__