File Coverage

blib/lib/WebService/Hexonet/Connector/APIClient.pm
Criterion Covered Total %
statement 296 304 97.3
branch 58 70 82.8
condition 7 14 50.0
subroutine 51 52 98.0
pod 32 35 91.4
total 444 475 93.4


line stmt bran cond sub pod time code
1             package WebService::Hexonet::Connector::APIClient;
2              
3 1     1   17 use 5.026_000;
  1         4  
4 1     1   5 use strict;
  1         3  
  1         18  
5 1     1   4 use warnings;
  1         2  
  1         40  
6 1     1   634 use utf8;
  1         15  
  1         5  
7 1     1   678 use WebService::Hexonet::Connector::Logger;
  1         3  
  1         31  
8 1     1   749 use WebService::Hexonet::Connector::Response;
  1         5  
  1         36  
9 1     1   7 use WebService::Hexonet::Connector::ResponseTemplateManager;
  1         2  
  1         23  
10 1     1   787 use WebService::Hexonet::Connector::SocketConfig;
  1         4  
  1         31  
11 1     1   792 use LWP::UserAgent;
  1         47905  
  1         37  
12 1     1   7 use Carp;
  1         3  
  1         60  
13 1     1   7 use Readonly;
  1         2  
  1         41  
14 1     1   6 use Data::Dumper;
  1         3  
  1         42  
15 1     1   6 use Config;
  1         2  
  1         36  
16 1     1   5 use POSIX;
  1         2  
  1         7  
17              
18             Readonly my $SOCKETTIMEOUT => 300; # 300s or 5 min
19             Readonly my $IDX4 => 4; # Index 4 constant
20             Readonly our $ISPAPI_CONNECTION_URL => 'https://api.ispapi.net/api/call.cgi'; # Default Connection Setup URL
21             Readonly our $ISPAPI_CONNECTION_URL_PROXY => 'http://127.0.0.1/api/call.cgi'; # High Speed Connection Setup URL
22              
23 1     1   2331 use version 0.9917; our $VERSION = version->declare('v2.9.1');
  1         19  
  1         8  
24              
25             my $rtm = WebService::Hexonet::Connector::ResponseTemplateManager->getInstance();
26              
27              
28             sub new {
29 2     2 1 7 my $class = shift;
30 2         8 my $self = bless {
31             socketURL => $ISPAPI_CONNECTION_URL,
32             debugMode => 0,
33             socketConfig => WebService::Hexonet::Connector::SocketConfig->new(),
34             ua => q{},
35             curlopts => {},
36             logger => WebService::Hexonet::Connector::Logger->new()
37             }, $class;
38 2         21 $self->setURL($ISPAPI_CONNECTION_URL);
39 2         8 $self->useLIVESystem();
40 2         6 $self->setDefaultLogger();
41 2         5 return $self;
42             }
43              
44              
45             sub setDefaultLogger {
46 2     2 0 4 my $self = shift;
47 2         8 $self->{logger} = WebService::Hexonet::Connector::Logger->new();
48 2         4 return $self;
49             }
50              
51              
52             sub setCustomLogger {
53 0     0 0 0 my ( $self, $logger ) = shift;
54 0 0 0     0 if ( defined($logger) && $logger->can('log') ) {
55 0         0 $self->{logger} = $logger;
56             }
57 0         0 return $self;
58             }
59              
60              
61             sub enableDebugMode {
62 2     2 1 557 my $self = shift;
63 2         6 $self->{debugMode} = 1;
64 2         5 return $self;
65             }
66              
67              
68             sub disableDebugMode {
69 2     2 1 7 my $self = shift;
70 2         5 $self->{debugMode} = 0;
71 2         5 return $self;
72             }
73              
74              
75             sub getPOSTData {
76 52     52 1 1339 my ( $self, $cmd, $secured ) = @_;
77 52         203 my $post = $self->{socketConfig}->getPOSTData();
78 52 100 66     255 if ( defined($secured) && $secured == 1 ) {
79 19         77 $post->{s_pw} = '***';
80             }
81 52         100 my $tmp = q{};
82 52 100       194 if ( ( ref $cmd ) eq 'HASH' ) {
83 51         90 foreach my $key ( sort keys %{$cmd} ) {
  51         242  
84 93 100       227 if ( defined $cmd->{$key} ) {
85 92         174 my $val = $cmd->{$key};
86 92         231 $val =~ s/[\r\n]//msx;
87 92         302 $tmp .= "${key}=${val}\n";
88             }
89             }
90             } else {
91 1         3 $tmp = $cmd;
92             }
93 52 100 66     253 if ( defined($secured) && $secured == 1 ) {
94 19         79 $tmp =~ s/PASSWORD\=[^\n]+/PASSWORD=***/gmsx;
95             }
96 52         281 $tmp =~ s/\n$//msx;
97 52 100       195 if ( utf8::is_utf8($tmp) ) {
98 2         6 utf8::encode($tmp);
99             }
100 52         159 $post->{'s_command'} = $tmp;
101 52         160 return $post;
102             }
103              
104              
105             sub getSession {
106 2     2 1 10 my $self = shift;
107 2         7 my $sessid = $self->{socketConfig}->getSession();
108 2 100       8 if ( length $sessid ) {
109 1         4 return $sessid;
110             }
111 1         2 return;
112             }
113              
114              
115             sub getURL {
116 5     5 1 17 my $self = shift;
117 5         14 return $self->{socketURL};
118             }
119              
120              
121             sub getUserAgent {
122 21     21 1 180 my $self = shift;
123 21 100       104 if ( !( length $self->{ua} ) ) {
124 1         19 my $arch = (POSIX::uname)[ $IDX4 ];
125 1         16 my $os = (POSIX::uname)[ 0 ];
126 1         8 my $rv = $self->getVersion();
127 1         30 $self->{ua} = "PERL-SDK ($os; $arch; rv:$rv) perl/$Config{version}";
128             }
129 21         95 return $self->{ua};
130             }
131              
132              
133             sub setUserAgent {
134 2     2 1 1743 my ( $self, $str, $rv, $modules ) = @_;
135 2         30 my $arch = (POSIX::uname)[ $IDX4 ];
136 2         34 my $os = (POSIX::uname)[ 0 ];
137 2         13 my $rv2 = $self->getVersion();
138 2         9 my $mods = q{};
139 2 100 66     16 if ( defined $modules && length($modules) > 0 ) {
140 1         5 $mods = q{ } . join q{ }, @{$modules};
  1         6  
141             }
142 2         25 $self->{ua} = "$str ($os; $arch; rv:$rv)$mods perl-sdk/$rv2 perl/$Config{version}";
143 2         16 return $self;
144             }
145              
146              
147             sub getProxy {
148 20     20 1 66 my ($self) = @_;
149 20 100       79 if ( exists $self->{curlopts}->{'PROXY'} ) {
150 1         6 return $self->{curlopts}->{'PROXY'};
151             }
152 19         52 return;
153             }
154              
155              
156             sub setProxy {
157 2     2 1 7 my ( $self, $proxy ) = @_;
158 2 100       7 if ( length($proxy) == 0 ) {
159 1         2 delete $self->{curlopts}->{'PROXY'};
160             } else {
161 1         5 $self->{curlopts}->{'PROXY'} = $proxy;
162             }
163 2         4 return $self;
164             }
165              
166              
167             sub getReferer {
168 20     20 1 73 my ($self) = @_;
169 20 100       97 if ( exists $self->{curlopts}->{'REFERER'} ) {
170 1         5 return $self->{curlopts}->{'REFERER'};
171             }
172 19         52 return;
173             }
174              
175              
176             sub setReferer {
177 2     2 1 536 my ( $self, $referer ) = @_;
178 2 100       7 if ( length($referer) == 0 ) {
179 1         4 delete $self->{curlopts}->{'REFERER'};
180             } else {
181 1         4 $self->{curlopts}->{'REFERER'} = $referer;
182             }
183 2         5 return $self;
184             }
185              
186              
187             sub getVersion {
188 4     4 1 31 my $self = shift;
189 4         10 return $VERSION;
190             }
191              
192              
193             sub saveSession {
194 1     1 1 8 my ( $self, $session ) = @_;
195             $session->{socketcfg} = {
196             entity => $self->{socketConfig}->getSystemEntity(),
197             session => $self->{socketConfig}->getSession()
198 1         5 };
199 1         3 return $self;
200             }
201              
202              
203             sub reuseSession {
204 1     1 1 6 my ( $self, $session ) = @_;
205 1         5 $self->{socketConfig}->setSystemEntity( $session->{socketcfg}->{entity} );
206 1         4 $self->setSession( $session->{socketcfg}->{session} );
207 1         2 return $self;
208             }
209              
210              
211             sub setURL {
212 8     8 1 597 my ( $self, $value ) = @_;
213 8         49 $self->{socketURL} = $value;
214 8         20 return $self;
215             }
216              
217              
218             sub setOTP {
219 8     8 1 658 my ( $self, $value ) = @_;
220 8         44 $self->{socketConfig}->setOTP($value);
221 8         20 return $self;
222             }
223              
224              
225             sub setSession {
226 13     13 1 3555 my ( $self, $value ) = @_;
227 13         68 $self->{socketConfig}->setSession($value);
228 13         28 return $self;
229             }
230              
231              
232             sub setRemoteIPAddress {
233 3     3 1 595 my ( $self, $value ) = @_;
234 3         13 $self->{socketConfig}->setRemoteAddress($value);
235 3         8 return $self;
236             }
237              
238              
239             sub setCredentials {
240 12     12 1 1679 my ( $self, $uid, $pw ) = @_;
241 12         67 $self->{socketConfig}->setLogin($uid);
242 12         63 $self->{socketConfig}->setPassword($pw);
243 12         28 return $self;
244             }
245              
246              
247             sub setRoleCredentials {
248 4     4 1 1679 my ( $self, $uid, $role, $pw ) = @_;
249 4         12 my $myuid = "${uid}!${role}";
250 4         16 $myuid =~ s/^\!$//msx;
251 4         15 return $self->setCredentials( $myuid, $pw );
252             }
253              
254              
255             sub login {
256 4     4 1 23 my $self = shift;
257 4         12 my $otp = shift;
258 4   50     35 $self->setOTP( $otp || q{} );
259 4         29 my $rr = $self->request( { COMMAND => 'StartSession' } );
260 4 100       36 if ( $rr->isSuccess() ) {
261 2         10 my $col = $rr->getColumn('SESSION');
262 2         9 my $sessid = q{};
263 2 50       9 if ( defined $col ) {
264 2         11 my @d = $col->getData();
265 2         7 $sessid = $d[ 0 ];
266             }
267 2         58 $self->setSession($sessid);
268             }
269 4         87 return $rr;
270             }
271              
272              
273             sub loginExtended {
274 1     1 1 3 my $self = shift;
275 1         3 my $params = shift;
276 1         4 my $otpc = shift;
277 1 50       6 if ( !defined $otpc ) {
278 1         4 $otpc = q{};
279             }
280 1         7 $self->setOTP($otpc);
281 1         4 my $cmd = { COMMAND => 'StartSession' };
282 1         3 foreach my $key ( keys %{$params} ) {
  1         6  
283 1         11 $cmd->{$key} = $params->{$key};
284             }
285 1         6 my $rr = $self->request($cmd);
286 1 50       12 if ( $rr->isSuccess() ) {
287 1         10 my $col = $rr->getColumn('SESSION');
288 1         8 my $sessid = q{};
289 1 50       9 if ( defined $col ) {
290 1         11 my @d = $col->getData();
291 1         5 $sessid = $d[ 0 ];
292             }
293 1         12 $self->setSession($sessid);
294             }
295 1         14 return $rr;
296             }
297              
298              
299             sub logout {
300 2     2 1 5 my $self = shift;
301 2         12 my $rr = $self->request( { COMMAND => 'EndSession' } );
302 2 100       13 if ( $rr->isSuccess() ) {
303 1         8 $self->setSession(q{});
304             }
305 2         21 return $rr;
306             }
307              
308              
309             sub request {
310 18     18 1 85 my ( $self, $cmd ) = @_;
311             # flatten nested api command bulk parameters
312 18         79 my $newcmd = $self->_flattenCommand($cmd);
313             # auto convert umlaut names to punycode
314 18         96 $newcmd = $self->_autoIDNConvert($newcmd);
315              
316             # request command to API
317 18         87 my $cfg = { CONNECTION_URL => $self->{socketURL} };
318 18         89 my $post = $self->getPOSTData($newcmd);
319 18         66 my $secured = $self->getPOSTData( $newcmd, 1 );
320              
321 18         204 my $ua = LWP::UserAgent->new();
322 18         9904 $ua->agent( $self->getUserAgent() );
323 18         1329 $ua->default_header( 'Expect', q{} );
324 18         1030 $ua->timeout($SOCKETTIMEOUT);
325 18         530 my $referer = $self->getReferer();
326 18 50       67 if ($referer) {
327 0         0 $ua->default_header( 'Referer', $referer );
328             }
329 18         73 my $proxy = $self->getProxy();
330 18 50       67 if ($proxy) {
331 0         0 $ua->proxy( [ 'http', 'https' ], $proxy );
332             }
333              
334 18         94 my $r = $ua->post( $cfg->{CONNECTION_URL}, $post );
335 18 100       5818589 if ( $r->is_success ) {
336 17         396 $r = WebService::Hexonet::Connector::Response->new( $r->decoded_content, $newcmd, $cfg );
337 17 100       127 if ( $self->{debugMode} ) {
338 2         18 $self->{logger}->log( $secured, $r );
339             }
340             } else {
341 1         36 $r = WebService::Hexonet::Connector::Response->new( $rtm->getTemplate('httperror')->getPlain(), $newcmd, $cfg );
342 1 50       15 if ( $self->{debugMode} ) {
343 0         0 $self->{logger}->log( $secured, $r, $r->status_line );
344             }
345             }
346 18         685 return $r;
347             }
348              
349              
350             sub requestNextResponsePage {
351 6     6 1 32 my ( $self, $rr ) = @_;
352 6         33 my $mycmd = $rr->getCommand();
353 6 50       27 if ( defined $mycmd->{LAST} ) {
354 0         0 croak 'Parameter LAST in use! Please remove it to avoid issues in requestNextPage.';
355             }
356 6         16 my $first = 0;
357 6 100       27 if ( defined $mycmd->{FIRST} ) {
358 5         21 $first = $mycmd->{FIRST};
359             }
360 6         30 my $total = $rr->getRecordsTotalCount();
361 6         29 my $limit = $rr->getRecordsLimitation();
362 6         22 $first += $limit;
363 6 100       22 if ( $first < $total ) {
364 5         12 $mycmd->{FIRST} = $first;
365 5         12 $mycmd->{LIMIT} = $limit;
366 5         24 return $self->request($mycmd);
367             }
368 1         4 return;
369             }
370              
371              
372             sub requestAllResponsePages {
373 1     1 1 10 my ( $self, $cmd ) = @_;
374 1         4 my @responses = ();
375 1         3 my $command = {};
376 1         3 foreach my $key ( keys %{$cmd} ) {
  1         5  
377 3         9 $command->{$key} = $cmd->{$key};
378             }
379 1         4 $command->{FIRST} = 0;
380 1         4 my $rr = $self->request($command);
381 1         4 my $tmp = $rr;
382 1         3 my $idx = 0;
383 1         7 while ( defined $tmp ) {
384 4         122 push @responses, $tmp;
385 4         28 $tmp = $self->requestNextResponsePage($tmp);
386             }
387 1         35 return \@responses;
388             }
389              
390              
391             sub setUserView {
392 1     1 1 947 my ( $self, $uid ) = @_;
393 1         8 $self->{socketConfig}->setUser($uid);
394 1         2 return $self;
395             }
396              
397              
398             sub resetUserView {
399 1     1 1 4 my $self = shift;
400 1         8 $self->{socketConfig}->setUser(q{});
401 1         2 return $self;
402             }
403              
404              
405             sub useDefaultConnectionSetup {
406 1     1 1 580 my $self = shift;
407 1         4 return $self->setURL($ISPAPI_CONNECTION_URL);
408             }
409              
410              
411             sub useHighPerformanceConnectionSetup {
412 1     1 1 539 my $self = shift;
413 1         4 return $self->setURL($ISPAPI_CONNECTION_URL_PROXY);
414             }
415              
416              
417             sub useOTESystem {
418 1     1 0 563 my $self = shift;
419 1         6 $self->{socketConfig}->setSystemEntity('1234');
420 1         4 return $self;
421             }
422              
423              
424             sub useLIVESystem {
425 2     2 1 5 my $self = shift;
426 2         8 $self->{socketConfig}->setSystemEntity('54cd');
427 2         4 return $self;
428             }
429              
430              
431             sub _flattenCommand {
432 18     18   61 my ( $self, $cmd ) = @_;
433 18         41 for my $key ( keys %{$cmd} ) {
  18         91  
434 35         98 my $newkey = uc $key;
435 35 100       109 if ( $newkey ne $key ) {
436 1         3 $cmd->{$newkey} = delete $cmd->{$key};
437             }
438 35 100       119 if ( ref( $cmd->{$newkey} ) eq 'ARRAY' ) {
439 3         14 my @val = @{ $cmd->{$newkey} };
  3         14  
440 3         8 my $idx = 0;
441 3         8 for my $str (@val) {
442 6         19 $str =~ s/[\r\n]//gmsx;
443 6         21 $cmd->{"${key}${idx}"} = $str;
444 6         17 $idx++;
445             }
446 3         11 delete $cmd->{$newkey};
447             }
448             }
449 18         60 return $cmd;
450             }
451              
452              
453             sub _autoIDNConvert {
454 18     18   62 my ( $self, $cmd ) = @_;
455 18 100       128 if ( $cmd->{'COMMAND'} =~ /^CONVERTIDN$/imsx ) {
456 1         4 return $cmd;
457             }
458 17         43 my @keys = grep {/^(DOMAIN|NAMESERVER|DNSZONE)(\d*)$/imsx} keys %{$cmd};
  35         200  
  17         63  
459 17 100       73 if ( scalar @keys == 0 ) {
460 15         50 return $cmd;
461             }
462 2         6 my @toconvert = ();
463 2         6 my @idxs = ();
464 2         7 foreach my $key (@keys) {
465 5         19 my $val = $cmd->{$key};
466 5 100       22 if ( $val =~ /[^[:lower:]\d. -]/imsx ) {
467 1         5 push @toconvert, $val;
468 1         3 push @idxs, $key;
469             }
470             }
471 2 100       12 if ( scalar @toconvert == 0 ) {
472 1         5 return $cmd;
473             }
474 1         14 my $r = $self->request(
475             { COMMAND => 'ConvertIDN',
476             DOMAIN => \@toconvert
477             }
478             );
479 1 50       9 if ( $r->isSuccess() ) {
480 1         4 my $col = $r->getColumn('ACE');
481 1 50       13 if ($col) {
482 1         4 my $data = $col->getData();
483 1         3 my $idx = 0;
484 1         2 foreach my $pc ( @{$data} ) {
  1         4  
485 1         7 $cmd->{ $idxs[ $idx ] } = $pc;
486 1         3 $idx++;
487             }
488             }
489             }
490 1         22 return $cmd;
491             }
492              
493             1;
494              
495             __END__