File Coverage

blib/lib/API/ISPManager.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package API::ISPManager;
2              
3 2     2   3013 use strict;
  2         5  
  2         75  
4 2     2   11 use warnings;
  2         4  
  2         72  
5 2     2   2013 use lib qw(../..);
  2         1512  
  2         13  
6              
7 2     2   1760 use Exporter::Lite;
  2         1871  
  2         18  
8 2     2   2326 use LWP::UserAgent;
  2         121919  
  2         87  
9             #use XML::LibXML;
10 2     2   1319 use XML::Simple;
  0            
  0            
11             use Data::Dumper;
12              
13             # Main packages
14             use API::ISPManager::ip;
15             use API::ISPManager::user;
16             use API::ISPManager::domain;
17             use API::ISPManager::mailbox;
18              
19             # Addition packages
20             use API::ISPManager::backup;
21             use API::ISPManager::db;
22             use API::ISPManager::preset;
23             use API::ISPManager::stat;
24             use API::ISPManager::services;
25             use API::ISPManager::ftp;
26             use API::ISPManager::misc;
27             use API::ISPManager::file;
28              
29             # VDSManager
30             use API::ISPManager::vds;
31             use API::ISPManager::diskpreset;
32             use API::ISPManager::vdspreset;
33              
34             # BillManager
35             use API::ISPManager::software;
36             use API::ISPManager::order;
37              
38             our @EXPORT = qw/get_auth_id refs is_success get_data query_abstract is_ok get_error/;
39             our @EXPORT_OK = qw//;
40             our $VERSION = 0.07;
41             our $DEBUG = '';
42              
43             =head1 NAME
44              
45             API::ISPManager - interface to the ISPManager Hosting Panel API ( http://ispsystem.com )
46              
47             =head1 SYNOPSIS
48              
49             use API::ISPManager;
50            
51             my $connection_params = {
52             username => 'username',
53             password => 'qwerty',
54             host => '11.22.33.44',
55             path => 'manager',
56             };
57              
58             ### Get all panel IP
59             my $ip_list = API::ISPManager::ip::list( $connection_params );
60              
61             unless ($ip_list && ref $ip_list eq 'ARRAY' && scalar @$ip_list) {
62             die 'Cannot get ip list from ISP';
63             }
64              
65             my $ip = $ip_list->[0];
66             my $dname = 'perlaround.ru';
67              
68             my $client_creation_result = API::ISPManager::user::create( {
69             %{ $connection_params },
70             name => 'user_login',
71             passwd => 'user_password',
72             ip => '11.11.22.33',
73             preset => 'template_name',
74             domain => $dname,
75             });
76              
77             # Switch off account:
78             my $suspend_result = API::ISPManager::user::disable( {
79             %{ $connection_params },
80             elid => $use_login,
81             } );
82              
83             unless ( $suspend_result ) {
84             die "Cannot suspend account";
85             }
86              
87              
88              
89             # Switch on account
90             my $resume_result = API::ISPManager::user::enable( {
91             %{ $connection_params },
92             elid => $user_login,
93             } );
94              
95             unless ( $resume_result ) {
96             die "Cannot suspend account";
97             }
98              
99              
100              
101             # Delete account
102             my $delete_result = API::ISPManager::user::delete( {
103             %{ $connection_params },
104             elid => $login,
105             } );
106              
107             unless ( $delete_result ) {
108             die "Cannot delete account";
109             }
110              
111              
112             =cut
113              
114             # Last raw answer from server
115             our $last_answer = '';
116              
117             # Public!
118             sub is_ok {
119             my $answer = shift;
120              
121             return '' unless $answer && ref $answer eq 'HASH' && $answer->{success};
122             }
123              
124              
125             sub get_error {
126             my $answer = shift;
127              
128             return '' if is_ok($answer); # ok == no error
129              
130             return Dumper( $answer->{error} );
131             }
132              
133             # Get data from @_
134             sub get_params {
135             my @params = @_;
136              
137             if (scalar @params == 1 && ref $params[0] eq 'HASH' ) {
138             return { %{ $params[0] } };
139             } else {
140             return { @params };
141             }
142             }
143              
144             # Make query string
145             # STATIC(HASHREF: params)
146             sub mk_query_string {
147             my $params = shift;
148              
149             return '' unless $params &&
150             ref $params eq 'HASH' && %$params ;
151              
152             my $result = join '&', map { "$_=$params->{$_}" } sort keys %$params;
153             warn $result if $DEBUG;
154              
155             return $result;
156             }
157              
158             # Kill slashes at start / end string
159             # STATIC(STRING:input_string)
160             sub kill_start_end_slashes {
161             my $str = shift;
162              
163             for ($str) {
164             s/^\/+//sgi;
165             s/\/+$//sgi;
166             }
167            
168             return $str;
169             }
170              
171             # Make full query string (with host, path and protocol)
172             # STATIC(HASHREF: params)
173             # params:
174             # host*
175             # path
176             # allow_http
177             # param1
178             # param2
179             # ...
180             sub mk_full_query_string {
181             my $params = shift;
182              
183             return '' unless
184             $params &&
185             ref $params eq 'HASH' &&
186             %$params &&
187             $params->{host};
188              
189             my $host = delete $params->{host};
190             my $path = delete $params->{path} || '';
191             my $allow_http = delete $params->{allow_http} || '';
192              
193             unless ($path) {
194             $path = 'manager';
195             }
196              
197             $path = kill_start_end_slashes($path);
198             $host = kill_start_end_slashes($host);
199              
200             my $query_path = ( $allow_http ? 'http' : 'https' ) . "://$host/$path/ispmgr?";
201              
202             return %$params ? $query_path . mk_query_string($params) : '';
203             }
204              
205              
206             # Make request to server and get answer
207             # STATIC (STRING: query_string)
208             sub mk_query_to_server {
209             my $query_string = shift;
210              
211             return '' unless $query_string;
212             warn "Query string: $query_string\n" if $DEBUG;
213              
214             my $ua = LWP::UserAgent->new;
215             $ua->agent("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
216             # Don`t working without this string!
217              
218             my $response = $ua->get($query_string);
219              
220             if ($response->is_success) {
221             my $content = $response->content;
222              
223             if ($response->header('content-type') eq 'text/xml') {
224             # allow only XML answers
225             if ($content && $content =~ /^<\?xml version="\d\.\d" encoding="UTF-8"\?>/s) {
226             warn $content if $DEBUG;
227             return $content;
228             } else {
229             return '';
230             }
231             } else {
232             return '';
233             }
234             } else {
235             return '';
236             }
237             }
238              
239             # Parse answer
240             # STATIC(HASHREF: params)
241             # params:
242             # STRING: answer
243             # HASHREF: xml_parser_params)
244             sub parse_answer {
245             my %params = @_;
246              
247             my $answer_string =
248             $params{answer};
249             my $parser_params =
250             $params{parser_params} || { };
251              
252             return '' unless $answer_string;
253              
254             my $deparsed = XMLin( $answer_string, %$parser_params );
255             warn Dumper $deparsed if $DEBUG;
256            
257             return $deparsed ? $deparsed : '';
258             }
259              
260             # Get + deparse
261             # STATIC(STRING: query_string)
262             sub process_query {
263             my %params = @_;
264              
265             my $query_string = $params{query_string};
266             my $xml_parser_params = $params{parser_params} || '';
267             my $fake_answer = $params{fake_answer} || '';
268              
269             return '' unless $query_string;
270              
271             my $answer = $fake_answer ? $fake_answer : mk_query_to_server($query_string);
272             warn $answer if $answer && $DEBUG;
273              
274             return $answer ?
275             parse_answer(
276             answer => $answer,
277             parser_params => $xml_parser_params
278             ) : '';
279             }
280              
281             # Filter hash
282             # STATIC(HASHREF: hash, ARRREF: allowed_keys)
283             # RETURN: hashref only with allowed keys
284             sub filter_hash {
285             my ($hash, $allowed_keys) = @_;
286              
287             return unless ref $hash eq 'HASH' &&
288             ref $allowed_keys eq 'ARRAY';
289            
290             my $new_hash = { };
291              
292             foreach my $allowed_key (@$allowed_keys) {
293             if (exists $hash->{$allowed_key}) {
294             $new_hash->{$allowed_key} = $hash->{$allowed_key};
295             }
296             }
297              
298             return $new_hash;
299             }
300              
301             # Get access key, time to live -- 30 minutes
302             # STATIC(HASHREF: params_hash)
303             # params_hash:
304             # - all elements from mk_full_query_string +
305             # - username*
306             # - password*
307             sub get_auth_id {
308             my %params_raw = @_;
309              
310             warn 'get_auth_id params: ' . Dumper(\%params_raw) if $DEBUG;
311              
312             my $params = filter_hash(
313             \%params_raw,
314             [ 'host', 'path', 'allow_http', 'username', 'password' ]
315             );
316              
317             # Check this sub params
318             unless ($params->{username} && $params->{password}) {
319             return '';
320             }
321              
322            
323             my $query_string = mk_full_query_string( {
324             %$params,
325             func => 'auth',
326             out => 'xml',
327             } );
328              
329             return '' unless $query_string;
330            
331             warn $query_string if $DEBUG;
332              
333             my $xml = process_query( query_string => $query_string);
334              
335             if ($xml) {
336             my $error_node = exists $xml->{authfail};
337             return '' if $error_node;
338              
339             return $xml->{auth}->{id};
340             } else {
341             return '';
342             }
343             }
344              
345             # Wrapper for "ref" on undef value, without warnings :)
346             # Possible very stupid sub :)
347             # STATIC(REF: our_ref)
348             sub refs {
349             my $ref = shift;
350              
351             return '' unless $ref;
352              
353             return ref $ref;
354             }
355              
356             # INTERNAL!!! Check server answer result
357             # STATIC(data_block)
358             sub is_success {
359             my $data_block = shift;
360              
361             if ( ref $data_block eq 'HASH' && ! $data_block->{error} && $data_block->{data} ) {
362             return 1;
363             } else {
364             return '';
365             }
366             }
367              
368             # Get data from server answer
369             # STATIC(data_block)
370             sub get_data {
371             my $data_block = shift;
372              
373             unless ( is_success($data_block) ) {
374             return '';
375             }
376              
377             return $data_block->{data};
378             }
379              
380             # list all users
381             # all params derived from get_auth_id
382             sub query_abstract {
383             my %params = @_;
384              
385             my $params_raw = $params{params};
386             my $func_name = $params{func};
387             my $fake_answer = $params{fake_answer} || '';
388              
389             warn 'query_abstract ' . Dumper( \%params ) if $DEBUG;
390              
391             return '' unless $params_raw && $func_name;
392              
393             my $allowed_fields = $params{allowed_fields} || [ 'host', 'path', 'allow_http' ];
394             # TODO сделать сцепку массивов тут!!!!
395              
396             my $xml_parser_params = $params{parser_params};
397              
398             my $auth_id = $fake_answer ? '112323' : get_auth_id( %$params_raw );
399             warn "Auth_id: $auth_id\n" if $DEBUG;
400              
401             if ($auth_id or $func_name eq 'ftp') { # ftp hacked by authinfo
402             my $params = filter_hash( $params_raw, $allowed_fields);
403            
404             my $query_string = mk_full_query_string( {
405             ( $func_name eq 'ftp' ? ( ) : ( auth => $auth_id ) ), # for ftp auth not used, only authinfo
406             func => $func_name,
407             out => 'xml',
408             %$params,
409             } );
410              
411             warn Dumper $query_string if $DEBUG;
412              
413             return process_query(
414             query_string => $query_string,
415             parser_params => $xml_parser_params,
416             fake_answer => $fake_answer,
417             );
418              
419             #
420             # TODO add this check here
421             # if ( $server_answer && $server_answer->{elem} && ref $server_answer->{elem} eq 'HASH' ) {
422             # return { data => $server_answer->{elem} };
423             # }
424             #
425              
426             } else {
427             warn "auth_id not found or func type not ftp" if $DEBUG;
428             return '';
429             }
430             }
431              
432             1;