File Coverage

blib/lib/IO/EPP/IRRP.pm
Criterion Covered Total %
statement 12 186 6.4
branch 0 100 0.0
condition 0 28 0.0
subroutine 4 19 21.0
pod 15 15 100.0
total 31 348 8.9


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   2303 use IO::EPP::Base;
  1         3  
  1         40  
56 1     1   8 use parent qw( IO::EPP::Base );
  1         2  
  1         10  
57              
58 1     1   69 use strict;
  1         2  
  1         20  
59 1     1   5 use warnings;
  1         2  
  1         3064  
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              
149             =head2 create_domain
150              
151             Additional tld parameters must be specified as described in the tld documentation
152              
153             =cut
154              
155             sub create_domain {
156 0     0 1   my ( $self, $params ) = @_;
157              
158 0   0       $params->{authinfo} ||= SRS::Comm::Provider::EPP::Base::gen_pw( 16 );
159              
160 0           my $extension = '';
161              
162             # Up keys for key-value extension
163 0           foreach my $k ( keys %$params ) {
164 0 0         if ( $k =~ /^x-/ ) {
165 0           $params->{ uc($k) } = delete $params->{$k}
166             }
167             }
168              
169 0           foreach my $k ( keys %$params ) {
170 0 0         if ( $k =~ /^X-/ ) {
171 0           $extension .= " \n"
172             }
173             }
174              
175 0 0         if ( $extension ) {
176 0           $params->{extension} = " \n$extension \n";
177             }
178              
179 0           return $self->SUPER::create_domain( $params );
180             }
181              
182              
183             =head2 check_transfer
184              
185             Check the availability of domain transfer, the specific function
186              
187             INPUT:
188              
189             key of params:
190             C -- domain name
191              
192             An Example, request:
193              
194             my ( $answ, $msg ) = make_request( 'check_transfer', { dname => 'irrp.xyz', %conn_params } );
195              
196             Answer:
197              
198             {
199             'msg' => 'Object exists; 540 Attribute value is not unique; DOMAIN DOES NOT EXIST [irrp.xyz]',
200             'code' => 2302
201             };
202              
203             =cut
204              
205             sub check_transfer {
206 0     0 1   my ( $self, $params ) = @_;
207              
208 0 0         return ( 0, 0, 'no dname' ) unless $params->{dname};
209              
210 0           my $body = <
211             $$self{urn}{head}
212            
213            
214            
215            
216            
217            
218            
219             CHTR
220              
221 0           my $content = $self->req( $body, 'check_transfer' );
222              
223 0 0 0       if ( $content && $content =~ // ) {
224 0           my $code = $1 + 0;
225              
226 0           my $msg = '';
227 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
228 0           $msg = $1;
229             }
230              
231 0 0         if ( $code != 1000 ) {
232 0           my $reason = join( ';', $content =~ /]*>([^<>]+)<\/reason>/g );
233              
234 0 0         $msg .= "; " . $reason if $reason;
235             }
236              
237 0           my %info;
238              
239 0           my @list = $content =~ m|()|gs;
240              
241 0           foreach my $row ( @list ) {
242 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
243 0           $info{ lc $1 } = $2;
244             }
245             }
246              
247 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
248             }
249              
250 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
251             }
252              
253              
254             sub transfer {
255 0     0 1   my ( $self, $params ) = @_;
256              
257 0 0         if ( defined $params->{authinfo} ) {
258 0           $params->{authinfo} =~ s/&/&/g;
259 0           $params->{authinfo} =~ s/
260 0           $params->{authinfo} =~ s/>/>/g;
261             }
262              
263 0           if ( 0 && $params->{op} eq 'query' ) {
264             #There are two options: its own feature and standard
265             my $body = <
266             $$self{urn}{head}
267            
268            
269            
270            
271            
272            
273            
274             INTTR
275              
276             my $answ = $self->req( $body, 'query_transfer' );
277              
278             # if ( ref $res && $res->{code} == 1000 ) {
279             # $res->{trstatus} = 'pending';
280             # }
281             #
282             return $answ;
283             }
284              
285 0           return $self->SUPER::transfer( $params );
286             }
287              
288             =head2 get_transfer_list
289              
290             Get a list of all domains that are currently in the transfer state
291              
292             No input params
293              
294             An Example, request:
295              
296             my ( $answ, $msg, $conn ) = make_request( 'get_transfer_list', \%conn_params );
297              
298             # Answer:
299              
300             {
301             'user1' => 'login',
302             'parentuser2' => 'brsmedia.net',
303             'user' => 'login',
304             'domainumlaut1' => 'mmmm.travel',
305             'code' => '1000',
306             'count' => '3',
307             'total' => '3',
308             'parentuser' => 'brsmedia.net',
309             'domain1' => 'mmmm.travel',
310             'domainumlaut2' => 'pppp.travel',
311             'createddate' => '2019-02-07 08:56:06',
312             'domain2' => 'pppp.travel',
313             'domain' => 'eeee.travel',
314             'limit' => '10000',
315             'msg' => 'Command completed successfully',
316             'first' => '0',
317             'createddate2' => '2018-03-06 10:26:57',
318             'last' => '2',
319             'parentuser1' => 'brsmedia.net',
320             'domainumlaut' => 'eeee.travel',
321             'createddate1' => '2018-03-27 05:03:40',
322             'user2' => 'login'
323             };
324              
325             =cut
326              
327             sub get_transfer_list {
328 0     0 1   my ( $self, $params ) = @_;
329              
330 0           my $body = <
331             $$self{urn}{head}
332            
333            
334            
335            
336            
337            
338             QTL
339              
340 0           my $content = $self->req( $body, 'get_transfer_list' );
341              
342 0 0 0       if ( $content && $content =~ // ) {
343 0           my $code = $1 + 0;
344              
345 0           my $msg = '';
346 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
347 0           $msg = $1;
348             }
349              
350 0           my %info;
351              
352 0           my @list = $content =~ m|()|gs;
353              
354 0           foreach my $row ( @list ) {
355 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
356 0           $info{ lc $1 } = $2;
357             }
358             }
359              
360 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
361             }
362              
363 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
364             }
365              
366              
367             =head2 get_status_domain
368              
369             Function for getting additional domain data
370              
371             INPUT:
372              
373             key of params:
374             C -- domain name
375              
376             An Example, request:
377              
378             my ( $answ, $msg, $conn ) = make_request( 'get_status_domain', { dname => '777.mx', %conn_params } );
379              
380             # Answer:
381              
382             {
383             'REGISTRATIONGRACEPERIOD' => '0',
384             'NEXTACTION' => 'expire',
385             'FINALIZATIONDATE' => '2021-02-02 15:07:40',
386             'CREATEDDATE' => '2017-12-20 15:07:40',
387             'TRANSFERDATE' => '0000-00-00 00:00:00',
388             'STATUS1' => 'clientTransferProhibited',
389             'TECHCONTACT' => '777esap4gmjnbv',
390             'NAMESERVER' => 'ns1.777.com',
391             'STATUS' => 'ACTIVE',
392             'OWNERCONTACT' => '777vw7yurk2x2k',
393             'FAILUREDATE' => '2021-02-02 15:07:40',
394             'ACCOUNTINGPERIOD' => '0',
395             'RENEWALMODE' => 'AUTOEXPIRE',
396             'USER' => 'login',
397             'code' => 1000,
398             'X-WHOIS-RSP' => 'My Company',
399             'NEXTACTIONDATE' => '2021-02-02 15:07:40',
400             'DOMAINUMLAUT' => '777.mx',
401             'FINALIZATIONPERIOD' => '44d',
402             'NAMESERVER1' => 'ns2.777.com',
403             'EXPIRATIONDATE' => '2020-12-20 15:07:40',
404             'SUBCLASS' => 'MX',
405             'REGISTRARUPDATEDDATE' => '2019-12-26 15:51:38',
406             'PREPAIDPERIOD' => '0',
407             'UPDATEDDATE' => '2019-12-26 15:51:38',
408             'ROID' => 'DOMAIN_77700005500777-MX',
409             'HOSTTYPE' => 'OBJECT',
410             'UPDATEDBY' => 'SYSTEM',
411             'CREATEDBY' => 'SYSTEM',
412             'DESCRIPTION' => '777.mx',
413             'AUTH' => '777rhE!r9q=#y',
414             'ID' => '777.mx',
415             'BILLINGCONTACT' => '777y2emz0ib63xj',
416             'REGISTRAR' => 'SYSTEM',
417             'DELETIONRESTORABLEPERIOD' => '30d',
418             'REGISTRARTRANSFERDATE' => '0000-00-00 00:00:00',
419             'REGISTRATIONEXPIRATIONDATE' => '2020-12-20 15:07:40',
420             'PAIDUNTILDATE' => '2020-12-20 15:07:40',
421             'msg' => 'Command completed successfully',
422             'FAILUREPERIOD' => '44d',
423             'ADMINCONTACT' => '777sagtqh10mvpo',
424             'CLASS' => 'DOMAIN',
425             'ACCOUNTINGDATE' => '2020-12-20 15:07:40',
426             'REPOSITORY' => 'MX-LIVE-1API',
427             'DELETIONHOLDPERIOD' => '0d',
428             'TRANSFERLOCK' => '1',
429             'X-WHOIS-URL' => 'http://www.777.com',
430             'X-WHOIS-BANNER0' => 'Please register your domains at http://www.777.com'
431             };
432              
433             =cut
434              
435             sub get_status_domain {
436 0     0 1   my ( $self, $params ) = @_;
437              
438 0           my $body = qq|$$self{urn}{head}
439            
440            
441            
442            
443            
444            
445             |;
446              
447 0           my $answ = $self->req( $body, 'get_status_domain' );
448              
449 0 0         if ( $answ =~ /result code=['"](\d+)['"]/ ) {
450 0           my $rcode = $1 + 0;
451              
452 0           my $msg = '';
453 0 0         if ( $answ =~ /]*>(.+)<\/msg>.+\/result>/s ) {
454 0           $msg = $1;
455             }
456              
457 0           my %info;
458              
459 0 0         if ( $rcode == 1000 ) {
460 0           my @kv = $answ =~ //sg;
461              
462 0           foreach my $row ( @kv ) {
463 0 0         if ( $row =~ /key="([^"]+)"\s+value="([^"]+)"/ ) {
464 0           $info{$1} = $2;
465             }
466             }
467             }
468              
469 0 0         return wantarray ? ( \%info, $rcode, $msg ) : \%info;
470             }
471              
472 0 0         return wantarray ? ( 0, 0, 'no answer' ) : 0;
473             }
474              
475             =head2 renew_domain
476              
477             Automatic adds an additional parameter for the .jp tld
478              
479             =cut
480              
481             sub renew_domain {
482 0     0 1   my ( $self, $params ) = @_;
483              
484 0 0         if ( $params->{dname} =~ /\.jp$/ ) {
485             $params->{extension} =
486 0           "
487            
488            
489             ";
490             }
491              
492 0           return $self->SUPER::renew_domain( $params );
493             }
494              
495              
496             =head2 set_domain_renewal_mode
497              
498             Update domain renewal mode
499              
500             L
501              
502             INPUT:
503              
504             params with key:
505              
506             C – valid values: C, C, C
507              
508             OUTPUT:
509             see L
510              
511             =cut
512              
513             sub set_domain_renewal_mode {
514 0     0 1   my ( $self, $params ) = @_;
515              
516 0           $params->{renewal_mode} = uc $params->{renewal_mode};
517              
518 0           $params->{extension} = qq|
519            
520            
521            
522            
523             |;
524              
525 0           return $self->SUPER::update_domain( $params );
526             }
527              
528              
529             =head2 update_domain
530              
531             Has additional parameters:
532              
533             C – Changing domain contacts requires confirmation or a fee, depending on the tld;
534              
535             C – send confirmation of changing the owner's email address to the old address;
536              
537             C– send confirmation of changing the owner's email address to the new address;
538              
539             Other additional parameters depend on the tld.
540              
541             =cut
542              
543             sub update_domain {
544 0     0 1   my ( $self, $params ) = @_;
545              
546 0           my $extension = '';
547              
548             # Up keys for key-value extension
549 0           foreach my $k ( keys %$params ) {
550 0 0         if ( $k =~ /^x-/ ) {
551 0           $params->{ uc($k) } = delete $params->{$k};
552             }
553             }
554              
555 0 0         if ( $params->{trade} ) {
556             # a paid update or change the owner of the gtld
557 0           $extension .= " \n";
558              
559 0 0         if ( $params->{dname} =~ /\.xxx$/ ) {
560 0           $extension .= " \n";
561             }
562             }
563              
564 0 0         if ( defined $params->{'confirm_old_registrant'} ) {
565             # confirm old email
566 0           $extension .= " \n";
567             }
568              
569 0 0         if ( defined $params->{'confirm_new_registrant'} ) {
570             # confirm new email
571 0           $extension .= " \n";
572             }
573              
574 0 0         if ( $extension ) {
575 0           $params->{extension} = " \n$extension \n";
576             }
577              
578 0           return $self->SUPER::update_domain( $params );
579             }
580              
581              
582             =head2 restore_domain
583              
584             Domain redemption after deletion
585              
586             its own feature instead of rgp:restore
587              
588             INPUT:
589              
590             key of params:
591             C -- domain name
592              
593             =cut
594              
595             sub restore_domain {
596 0     0 1   my ( $self, $params ) = @_;
597              
598             $params->{extension} =
599 0           "
600            
601            
602             ";
603              
604 0           return $self->SUPER::update_domain( $params );
605             }
606              
607              
608             =head2 get_domain_list
609              
610             Get a list of all your domains
611              
612             =cut
613              
614             sub get_domain_list {
615 0     0 1   my ( $self, $params ) = @_;
616              
617 0           my $body = <
618             $$self{urn}{head}
619            
620            
621            
622            
623            
624            
625             INTTR
626              
627 0           my $content = $self->req( $body, 'get_domain_list' );
628              
629 0 0 0       if ( $content && $content =~ // ) {
630 0           my $code = $1 + 0;
631              
632 0           my $msg = '';
633 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
634 0           $msg = $1;
635             }
636              
637 0           my %info;
638              
639 0           my @list = $content =~ m|()|gs;
640              
641 0           foreach my $row ( @list ) {
642 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
643 0           $info{ lc $1 } = $2;
644             }
645             }
646              
647 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
648             }
649              
650 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
651             }
652              
653              
654             =head2 get_accounting_list
655              
656             Get lists of accounts, it makes sense to watch only the first record
657              
658             my ( $answ, $msg, $conn ) = make_request( 'get_accounting_list', { limit => 1, %conn_params } );
659              
660             You can use this request to check your account balance
661              
662             =cut
663              
664             sub get_accounting_list {
665 0     0 1   my ( $self, $params ) = @_;
666              
667 0           my $add_values = '';
668 0           foreach my $k ( keys %$params ) {
669 0           $add_values .= "\n ";
670             }
671              
672 0           my $body = <
673             $$self{urn}{head}
674            
675            
676             $add_values
677            
678            
679            
680             QAL
681              
682 0           my $content = $self->req( $body, 'get_accounting_list' );
683              
684 0 0 0       if ( $content && $content =~ // ) {
685 0           my $code = $1 + 0;
686              
687 0           my $msg = '';
688 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
689 0           $msg = $1;
690             }
691              
692 0           my %info;
693              
694 0           my @list = $content =~ m|()|gs;
695              
696 0           foreach my $row ( @list ) {
697 0 0         if ( $row =~ /key="([^"]+)" value="([^"]+)"/ ) {
698 0           $info{ lc $1 } = $2;
699             }
700             }
701              
702 0 0         return wantarray ? ( \%info, $code, $msg ) : \%info;
703             }
704              
705 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
706             }
707              
708              
709             =head2 req_poll_ext
710              
711             key-value extension for the req poll
712              
713             =cut
714              
715             sub req_poll_ext {
716 0     0 1   my ( undef, $ext ) = @_;
717              
718 0           my %info;
719              
720 0 0         if ( $ext =~ /]+>(.+)<\/keyvalue:extension>/s ) {
721 0           my $kv = $1;
722 0           my @kv = $kv =~ /]+)\/>/g;
723              
724 0           foreach ( @kv ) {
725 0 0         if ( /key="([^"]+)"\s+value="([^"]+)"/ ) {
726 0           $info{$1} = $2;
727             }
728             }
729              
730 0           foreach my $k ( keys %info ) {
731 0 0         if ( $info{$k} =~ /^[A-Z0-9._-]+$/ ) {
732             # domain and other names
733 0           $info{$k} = lc $info{$k};
734             }
735              
736 0 0         if ( $info{$k} =~ /\%/ ) {
737             # original irrp encode
738 0           $info{$k} =~ tr/+/ /;
739 0           $info{$k} =~ s/%25([0-9a-f]{2})/%$1/g;
740 0           $info{$k} =~ s/%([0-9a-f]{2})/chr(hex($1))/eg; #//
  0            
741             }
742             }
743             }
744              
745 0           return \%info;
746             }
747              
748             1;
749              
750             __END__