File Coverage

blib/lib/IO/EPP/IRRP.pm
Criterion Covered Total %
statement 12 182 6.5
branch 0 100 0.0
condition 0 28 0.0
subroutine 4 18 22.2
pod 13 14 92.8
total 29 342 8.4


line stmt bran cond sub pod time code
1             package IO::EPP::IRRP;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::IRRP
8              
9             =head1 SYNOPSIS
10              
11             use IO::EPP::IRRP;
12              
13             # Parameters for IO::Socket::SSL
14             my %sock_params = (
15             PeerHost => 'epp.ispapi.net',
16             PeerPort => 700,
17             Timeout => 30,
18             );
19              
20             # Create object, get greeting and call login()
21             my $conn = IO::EPP::IRRP->new( {
22             user => 'login',
23             pass => 'xxxxx',
24             sock_params => \%sock_params,
25             test_mode => 0, # real connect
26             } );
27              
28             # Check domain
29             my ( $answ, $code, $msg ) = $conn->check_domains( { domains => [ 'info.name', 'name.info' ] } );
30              
31             # Call logout() and destroy object
32             undef $conn;
33              
34             =head1 DESCRIPTION
35              
36             Work with iRRP/iDotz/Hexonet epp api:
37              
38             A large number of add-ons, but all special data is passed through the key-value extension
39              
40             Some of the transfer Functions have been replaced with the key-value extension
41              
42             To change the contacts of many zones you need to use trade
43              
44             Description of EPP from iRRP/Hexonet:
45             L
46              
47             Special EPP functions, as Query*List:
48             L
49             (domain, contact, transfer, zone, event, nameserver, accounting)
50              
51             TLD lists: L and New GTLD L
52              
53             =cut
54              
55 1     1   1796 use IO::EPP::Base;
  1         13  
  1         38  
56 1     1   7 use parent qw( IO::EPP::Base );
  1         2  
  1         7  
57              
58 1     1   64 use strict;
  1         1  
  1         18  
59 1     1   4 use warnings;
  1         2  
  1         2328  
60              
61             my $kv_ext = 'xmlns:keyvalue="http://schema.ispapi.net/epp/xml/keyvalue-1.0" xsi:schemaLocation="http://schema.ispapi.net/epp/xml/keyvalue-1.0 keyvalue-1.0.xsd"';
62              
63             sub make_request {
64 0     0 1   my ( $action, $params ) = @_;
65              
66 0           my ( $self, $code, $msg, $answ );
67              
68 0 0         unless ( $params->{conn} ) {
69 0   0       $params->{sock_params}{PeerHost} ||= 'epp.ispapi.net';
70 0   0       $params->{sock_params}{PeerPort} ||= 700;
71              
72 0           ( $self, $code, $msg ) = __PACKAGE__->new( $params );
73              
74 0 0 0       unless ( $code and $code == 1000 ) {
75 0           goto END_MR;
76             }
77             }
78             else {
79 0           $self = $params->{conn};
80             }
81              
82              
83 0           $self->{critical_error} = '';
84              
85 0 0         if ( $self->can( $action ) ) {
86 0           ( $answ, $code, $msg ) = $self->$action( $params );
87             }
88             else {
89 0           $msg = "undefined command <$action>, request cancelled";
90 0           $code = 0;
91             }
92              
93             END_MR:
94              
95 0 0         $msg .= '; ' . $self->{critical_error} if $self->{critical_error};
96              
97 0           my $full_answ = "code: $code\nmsg: $msg";
98              
99 0 0 0       $answ = {} unless $answ && ref $answ;
100              
101 0           $answ->{code} = $code;
102 0           $answ->{msg} = $msg;
103              
104 0 0         return wantarray ? ( $answ, $full_answ, $self ) : $answ;
105             }
106              
107             =head1 METHODS
108              
109             Further overlap functions where the provider has features
110              
111             =head2 login
112              
113             Ext params for login,
114              
115             INPUT: new password for change
116              
117             =cut
118              
119             sub login {
120 0     0 1   my ( $self, $pw ) = @_;
121              
122 0           my $svcs = '
123             urn:ietf:params:xml:ns:host-1.0
124             urn:ietf:params:xml:ns:domain-1.0
125             urn:ietf:params:xml:ns:contact-1.0
126             http://schema.ispapi.net/epp/xml/keyvalue-1.0';
127              
128 0           my $extension = '
129             urn:ietf:params:xml:ns:secDNS-1.1
130             urn:ietf:params:xml:ns:rgp-1.0
131             urn:ietf:params:xml:ns:fee-0.7
132             http://schema.ispapi.net/epp/xml/keyvalue-1.0';
133              
134 0           return $self->SUPER::login( $pw, $svcs, $extension );
135             }
136              
137              
138             sub create_contact {
139 0     0 1   my ( $self, $params ) = @_;
140              
141 0   0       $params->{id} ||= IO::EPP::Base::gen_id( 16 );
142              
143 0           $params->{authinfo} = SRS::Comm::Provider::EPP::Base::gen_pw( 16 );
144              
145 0           return $self->SUPER::create_contact( $params );
146             }
147              
148             sub create_domain {
149 0     0 1   my ( $self, $params ) = @_;
150              
151 0   0       $params->{authinfo} ||= SRS::Comm::Provider::EPP::Base::gen_pw( 16 );
152              
153 0           my $extension = '';
154              
155             # Up keys for key-value extension
156 0           foreach my $k ( keys %$params ) {
157 0 0         if ( $k =~ /^x-/ ) {
158 0           $params->{ uc($k) } = delete $params->{$k}
159             }
160             }
161              
162 0           foreach my $k ( keys %$params ) {
163 0 0         if ( $k =~ /^X-/ ) {
164 0           $extension .= " \n"
165             }
166             }
167              
168 0 0         if ( $extension ) {
169 0           $params->{extension} = " \n$extension \n";
170             }
171              
172 0           return $self->SUPER::create_domain( $params );
173             }
174              
175              
176             =head2 check_transfer
177              
178             Check the availability of domain transfer, the specific function
179              
180             INPUT:
181              
182             key of params:
183             C -- domain name
184              
185             An Example, request:
186              
187             my ( $answ, $msg ) = make_request( 'check_transfer', { dname => 'irrp.xyz', %conn_params } );
188              
189             Answer:
190              
191             {
192             'msg' => 'Object exists; 540 Attribute value is not unique; DOMAIN DOES NOT EXIST [irrp.xyz]',
193             'code' => 2302
194             };
195              
196             =cut
197              
198             sub check_transfer {
199 0     0 1   my ( $self, $params ) = @_;
200              
201 0 0         return ( 0, 0, 'no dname' ) unless $params->{dname};
202              
203 0           my $body = <
204             $$self{urn}{head}
205            
206            
207            
208            
209            
210            
211            
212             CHTR
213              
214 0           my $content = $self->req( $body, 'check_transfer' );
215              
216 0 0 0       if ( $content && $content =~ // ) {
217 0           my $code = $1 + 0;
218              
219 0           my $msg = '';
220 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
221 0           $msg = $1;
222             }
223              
224 0 0         if ( $code != 1000 ) {
225 0           my $reason = join( ';', $content =~ /]*>([^<>]+)<\/reason>/g );
226              
227 0 0         $msg .= "; " . $reason if $reason;
228             }
229              
230 0           my %info;
231              
232 0           my @list = $content =~ m|()|gs;
233              
234 0           foreach my $row ( @list ) {
235 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
236 0           $info{ lc $1 } = $2;
237             }
238             }
239              
240 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
241             }
242              
243 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
244             }
245              
246              
247             sub transfer {
248 0     0 1   my ( $self, $params ) = @_;
249              
250 0 0         if ( defined $params->{authinfo} ) {
251             # не понимает передаваемые на прямую спецсимвол в authinfo
252 0           $params->{authinfo} =~ s/&/&/g;
253 0           $params->{authinfo} =~ s/
254 0           $params->{authinfo} =~ s/>/>/g;
255             }
256              
257 0           if ( 0 && $params->{op} eq 'query' ) {
258             #There are two options: its own feature and standard
259             my $body = <
260             $$self{urn}{head}
261            
262            
263            
264            
265            
266            
267            
268             INTTR
269              
270             my $answ = $self->req( $body, 'transfer' );
271              
272             # if ( ref $res && $res->{code} == 1000 ) {
273             # $res->{trstatus} = 'pending';
274             # }
275             #
276             return $answ;
277             }
278              
279 0           return $self->SUPER::transfer( $params );
280             }
281              
282             =head2 get_transfer_list
283              
284             Get a list of all domains that are currently in the transfer state
285              
286             No input params
287              
288             An Example, request:
289              
290             my ( $answ, $msg, $conn ) = make_request( 'get_transfer_list', \%conn_params );
291              
292             Answer:
293              
294             {
295             'user1' => 'login',
296             'parentuser2' => 'brsmedia.net',
297             'user' => 'login',
298             'domainumlaut1' => 'mmmm.travel',
299             'code' => '1000',
300             'count' => '3',
301             'total' => '3',
302             'parentuser' => 'brsmedia.net',
303             'domain1' => 'mmmm.travel',
304             'domainumlaut2' => 'pppp.travel',
305             'createddate' => '2019-02-07 08:56:06',
306             'domain2' => 'pppp.travel',
307             'domain' => 'eeee.travel',
308             'limit' => '10000',
309             'msg' => 'Command completed successfully',
310             'first' => '0',
311             'createddate2' => '2018-03-06 10:26:57',
312             'last' => '2',
313             'parentuser1' => 'brsmedia.net',
314             'domainumlaut' => 'eeee.travel',
315             'createddate1' => '2018-03-27 05:03:40',
316             'user2' => 'login'
317             };
318              
319             =cut
320              
321             sub get_transfer_list {
322 0     0 1   my ( $self, $params ) = @_;
323              
324 0           my $body = <
325             $$self{urn}{head}
326            
327            
328            
329            
330            
331            
332             QTL
333              
334 0           my $content = $self->req( $body, 'get_transfer_list' );
335              
336 0 0 0       if ( $content && $content =~ // ) {
337 0           my $code = $1 + 0;
338              
339 0           my $msg = '';
340 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
341 0           $msg = $1;
342             }
343              
344 0           my %info;
345              
346 0           my @list = $content =~ m|()|gs;
347              
348 0           foreach my $row ( @list ) {
349 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
350 0           $info{ lc $1 } = $2;
351             }
352             }
353              
354 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
355             }
356              
357 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
358             }
359              
360              
361             =head2 get_status_domain
362              
363             Function for getting additional domain data
364              
365             INPUT:
366              
367             key of params:
368             C -- domain name
369              
370             An Example, request:
371              
372             my ( $answ, $msg, $conn ) = make_request( 'get_status_domain', { dname => '777.mx', %conn_params } );
373              
374             Answer:
375              
376             {
377             'REGISTRATIONGRACEPERIOD' => '0',
378             'NEXTACTION' => 'expire',
379             'FINALIZATIONDATE' => '2021-02-02 15:07:40',
380             'CREATEDDATE' => '2017-12-20 15:07:40',
381             'TRANSFERDATE' => '0000-00-00 00:00:00',
382             'STATUS1' => 'clientTransferProhibited',
383             'TECHCONTACT' => '777esap4gmjnbv',
384             'NAMESERVER' => 'ns1.777.com',
385             'STATUS' => 'ACTIVE',
386             'OWNERCONTACT' => '777vw7yurk2x2k',
387             'FAILUREDATE' => '2021-02-02 15:07:40',
388             'ACCOUNTINGPERIOD' => '0',
389             'RENEWALMODE' => 'AUTOEXPIRE',
390             'USER' => 'login',
391             'code' => 1000,
392             'X-WHOIS-RSP' => 'My Company',
393             'NEXTACTIONDATE' => '2021-02-02 15:07:40',
394             'DOMAINUMLAUT' => '777.mx',
395             'FINALIZATIONPERIOD' => '44d',
396             'NAMESERVER1' => 'ns2.777.com',
397             'EXPIRATIONDATE' => '2020-12-20 15:07:40',
398             'SUBCLASS' => 'MX',
399             'REGISTRARUPDATEDDATE' => '2019-12-26 15:51:38',
400             'PREPAIDPERIOD' => '0',
401             'UPDATEDDATE' => '2019-12-26 15:51:38',
402             'ROID' => 'DOMAIN_77700005500777-MX',
403             'HOSTTYPE' => 'OBJECT',
404             'UPDATEDBY' => 'SYSTEM',
405             'CREATEDBY' => 'SYSTEM',
406             'DESCRIPTION' => '777.mx',
407             'AUTH' => '777rhE!r9q=#y',
408             'ID' => '777.mx',
409             'BILLINGCONTACT' => '777y2emz0ib63xj',
410             'REGISTRAR' => 'SYSTEM',
411             'DELETIONRESTORABLEPERIOD' => '30d',
412             'REGISTRARTRANSFERDATE' => '0000-00-00 00:00:00',
413             'REGISTRATIONEXPIRATIONDATE' => '2020-12-20 15:07:40',
414             'PAIDUNTILDATE' => '2020-12-20 15:07:40',
415             'msg' => 'Command completed successfully',
416             'FAILUREPERIOD' => '44d',
417             'ADMINCONTACT' => '777sagtqh10mvpo',
418             'CLASS' => 'DOMAIN',
419             'ACCOUNTINGDATE' => '2020-12-20 15:07:40',
420             'REPOSITORY' => 'MX-LIVE-1API',
421             'DELETIONHOLDPERIOD' => '0d',
422             'TRANSFERLOCK' => '1',
423             'X-WHOIS-URL' => 'http://www.777.com',
424             'X-WHOIS-BANNER0' => 'Please register your domains at http://www.777.com'
425             };
426              
427             =cut
428              
429             sub get_status_domain {
430 0     0 1   my ( $self, $params ) = @_;
431              
432 0           my $body = qq|$$self{urn}{head}
433            
434            
435            
436            
437            
438            
439             |;
440              
441 0           my $answ = $self->req( $body, 'get_status_domain' );
442              
443 0 0         if ( $answ =~ /result code=['"](\d+)['"]/ ) {
444 0           my $rcode = $1 + 0;
445              
446 0           my $msg = '';
447 0 0         if ( $answ =~ /]*>(.+)<\/msg>.+\/result>/s ) {
448 0           $msg = $1;
449             }
450              
451 0           my %info;
452              
453 0 0         if ( $rcode == 1000 ) {
454 0           my @kv = $answ =~ //sg;
455              
456 0           foreach my $row ( @kv ) {
457 0 0         if ( $row =~ /key="([^"]+)"\s+value="([^"]+)"/ ) {
458 0           $info{$1} = $2;
459             }
460             }
461             }
462              
463 0 0         return wantarray ? ( \%info, $rcode, $msg ) : \%info;
464             }
465              
466 0 0         return wantarray ? ( 0, 0, 'no answer' ) : 0;
467             }
468              
469              
470             sub renew_domain {
471 0     0 1   my ( $self, $params ) = @_;
472              
473 0 0         if ( $params->{dname} =~ /\.jp$/ ) {
474             $params->{extension} =
475 0           "
476            
477            
478             ";
479             }
480              
481 0           return $self->SUPER::renew_domain( $params );
482             }
483              
484              
485             sub update_domain {
486 0     0 1   my ( $self, $params ) = @_;
487              
488 0           my $extension = '';
489              
490             # Up keys for key-value extension
491 0           foreach my $k ( keys %$params ) {
492 0 0         if ( $k =~ /^x-/ ) {
493 0           $params->{ uc($k) } = delete $params->{$k};
494             }
495             }
496              
497 0 0         if ( $params->{trade} ) {
498             # a paid update or change the owner of the gtld
499 0           $extension .= " \n";
500              
501 0 0         if ( $params->{dname} =~ /\.xxx$/ ) {
502 0           $extension .= " \n";
503             }
504             }
505              
506 0 0         if ( defined $params->{'confirm_old_registrant'} ) {
507             # confirm old email
508 0           $extension .= " \n";
509             }
510              
511 0 0         if ( defined $params->{'confirm_new_registrant'} ) {
512             # confirm new email
513 0           $extension .= " \n";
514             }
515              
516 0 0         if ( $extension ) {
517 0           $params->{extension} = " \n$extension \n";
518             }
519              
520 0           return $self->SUPER::update_domain( $params );
521             }
522              
523              
524             =head2 restore_domain
525              
526             Domain redemption after deletion
527              
528             its own feature instead of rgp:restore
529              
530             INPUT:
531              
532             key of params:
533             C -- domain name
534              
535             =cut
536              
537             sub restore_domain {
538 0     0 1   my ( $self, $params ) = @_;
539              
540             $params->{extension} =
541 0           "
542            
543            
544             ";
545              
546 0           return $self->SUPER::update_domain( $params );
547             }
548              
549              
550             =head2 get_domain_list
551              
552             Get a list of all your domains
553              
554             =cut
555              
556             sub get_domain_list {
557 0     0 1   my ( $self, $params ) = @_;
558              
559 0           my $body = <
560             $$self{urn}{head}
561            
562            
563            
564            
565            
566            
567             INTTR
568              
569 0           my $content = $self->req( $body, 'get_domain_list' );
570              
571 0 0 0       if ( $content && $content =~ // ) {
572 0           my $code = $1 + 0;
573              
574 0           my $msg = '';
575 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
576 0           $msg = $1;
577             }
578              
579 0           my %info;
580              
581 0           my @list = $content =~ m|()|gs;
582              
583 0           foreach my $row ( @list ) {
584 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
585 0           $info{ lc $1 } = $2;
586             }
587             }
588              
589 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
590             }
591              
592 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
593             }
594              
595              
596             =head2 get_accounting_list
597              
598             Get lists of accounts, it makes sense to watch only the first record
599              
600             my ( $answ, $msg, $conn ) = make_request( 'get_accounting_list', { limit => 1, %conn_params } );
601              
602             You can use this request to check your account balance
603              
604             =cut
605              
606             sub get_accounting_list {
607 0     0 1   my ( $self, $params ) = @_;
608              
609 0           my $add_values = '';
610 0           foreach my $k ( keys %$params ) {
611 0           $add_values .= "\n ";
612             }
613              
614 0           my $body = <
615             $$self{urn}{head}
616            
617            
618             $add_values
619            
620            
621            
622             QAL
623              
624 0           my $content = $self->req( $body, 'get_accounting_list' );
625              
626 0 0 0       if ( $content && $content =~ // ) {
627 0           my $code = $1 + 0;
628              
629 0           my $msg = '';
630 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
631 0           $msg = $1;
632             }
633              
634 0           my %info;
635              
636 0           my @list = $content =~ m|()|gs;
637              
638 0           foreach my $row ( @list ) {
639 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
640 0           $info{ lc $1 } = $2;
641             }
642             }
643              
644 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
645             }
646              
647 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
648             }
649              
650              
651             sub req_poll_ext {
652 0     0 0   my ( undef, $ext ) = @_;
653              
654 0           my %info;
655              
656 0 0         if ( $ext =~ /]+>(.+)<\/keyvalue:extension>/s ) {
657 0           my $kv = $1;
658 0           my @kv = $kv =~ /]+)\/>/g;
659              
660 0           foreach ( @kv ) {
661 0 0         if ( /key="([^"]+)"\s+value="([^"]+)"/ ) {
662 0           $info{$1} = $2;
663             }
664             }
665              
666 0           foreach my $k ( keys %info ) {
667 0 0         if ( $info{$k} =~ /^[A-Z0-9._-]+$/ ) {
668             # domain and other names
669 0           $info{$k} = lc $info{$k};
670             }
671              
672 0 0         if ( $info{$k} =~ /\%/ ) {
673             # original irrp encode
674 0           $info{$k} =~ tr/+/ /;
675 0           $info{$k} =~ s/%25([0-9a-f]{2})/%$1/g;
676 0           $info{$k} =~ s/%([0-9a-f]{2})/chr(hex($1))/eg; #//
  0            
677             }
678             }
679             }
680              
681 0           return \%info;
682             }
683              
684             1;
685              
686             __END__