File Coverage

blib/lib/WebService/Hexonet/Connector/APIClient.pm
Criterion Covered Total %
statement 294 302 97.3
branch 57 68 83.8
condition 7 14 50.0
subroutine 51 52 98.0
pod 32 35 91.4
total 441 471 93.6


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