File Coverage

blib/lib/IO/EPP/Verisign.pm
Criterion Covered Total %
statement 116 236 49.1
branch 31 110 28.1
condition 23 54 42.5
subroutine 21 29 72.4
pod 25 25 100.0
total 216 454 47.5


line stmt bran cond sub pod time code
1             package IO::EPP::Verisign;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::Verisign
8              
9             =head1 SYNOPSIS
10              
11             use IO::EPP::Verisign;
12              
13             # Parameters for IO::Socket::SSL
14             my %sock_params = (
15             PeerHost => 'epp.verisign-grs.com',
16             PeerPort => 700,
17             SSL_key_file => 'key_file.pem',
18             SSL_cert_file => 'cert_file.pem',
19             Timeout => 30,
20             );
21              
22             # Create object, get greeting and call login()
23             my $conn = IO::EPP::Verisign->new( {
24             user => 'login',
25             pass => 'XXXXX',
26             sock_params => \%sock_params,
27             server => 'Core', # or NameStore, or DotName
28             test_mode => 0, # real connect
29             } );
30              
31             # Check domain
32             my ( $answ, $code, $msg ) = $conn->check_domains( { domains => [ 'com.net', 'net.com' ] } );
33              
34             # Call logout() and destroy object
35             undef $conn;
36              
37             =head1 DESCRIPTION
38              
39             Work with Verisign EPP API
40              
41             Features:
42             Very mach extension, verisign here is leader. Absolutely all extensions have not yet been implemented
43              
44             docs:
45             L,
46             L (need white IP)
47              
48             for .name:
49             L
50              
51             The behavior of C and C servers is markedly different.
52              
53             =cut
54              
55 1     1   1643 use IO::EPP::Base;
  1         3  
  1         40  
56 1     1   7 use parent qw( IO::EPP::Base );
  1         2  
  1         6  
57              
58 1     1   62 use strict;
  1         2  
  1         18  
59 1     1   4 use warnings;
  1         2  
  1         3475  
60              
61             # not to change formatting:
62             our $sub_product_ext_begin =
63             '
64             ';
65             our $sub_product_ext_end =
66             '
67             ';
68             our $idn_ext =
69             'xmlns:idnLang="http://www.verisign.com/epp/idnLang-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.verisign.com/epp/idnLang-1.0 idnLang-1.0.xsd"';
70             our $rgp_ext =
71             'xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:rgp-1.0 rgp-1.0.xsd"';
72              
73             sub make_request {
74 26     26 1 10203 my ( $action, $params ) = @_;
75              
76 26         46 my ( $self, $code, $msg, $answ );
77              
78 26 100       69 unless ( $params->{conn} ) {
79 19   50     50 $params->{sock_params}{PeerHost} ||= 'epp.verisign-grs.com';
80 19   50     36 $params->{sock_params}{PeerPort} ||= 700;
81              
82 19         51 ( $self, $code, $msg ) = __PACKAGE__->new( $params );
83              
84 19 50 33     68 unless ( $code and $code == 1000 ) {
85 0         0 goto END_MR;
86             }
87             }
88             else {
89 7         12 $self = $params->{conn};
90             }
91              
92              
93             # You can change the zone if you do not change the server
94             # com <-> net <-> edu
95             # cc <-> tv <-> jobs <-> name <-> ... new gtld
96 26   100     80 my $tld = $self->{tld} || '';
97              
98 26 50 66     72 if ( not $tld and $params->{dname} ) {
99 0         0 ( $tld ) = $params->{dname} =~ /\.([^.]+)$/;
100             }
101              
102 26 100       48 if ( $tld ) {
103 17 50       37 if ( lc ( $tld ) eq 'name' ) {
104 0         0 $self->{dzone} = 'name';
105             }
106             else {
107 17         36 $self->{dzone} = 'dot' . uc( $tld );
108             }
109              
110 17         50 $self->{namestore_ext} = $sub_product_ext_begin . $self->{dzone} . $sub_product_ext_end ."\n";
111             }
112              
113              
114 26         50 $self->{critical_error} = '';
115              
116 26 50       109 if ( $self->can( $action ) ) {
117 26         69 ( $answ, $code, $msg ) = $self->$action( $params );
118             }
119             else {
120 0         0 $msg = "undefined command <$action>, request cancelled";
121 0         0 $code = 0;
122             }
123              
124              
125             END_MR:
126              
127 26 50       83 $msg .= '; ' . $self->{critical_error} if $self->{critical_error};
128              
129 26         64 my $full_answ = "code: $code\nmsg: $msg";
130              
131 26 50 33     117 $answ = {} unless $answ && ref $answ;
132              
133 26         60 $answ->{code} = $code;
134 26         51 $answ->{msg} = $msg;
135              
136 26 50       125 return wantarray ? ( $answ, $full_answ, $self ) : $answ;
137             }
138              
139              
140             sub req_test {
141 166     166 1 292 my ( $self, $out_data, $info ) = @_;
142              
143 166 100       694 $self->epp_log( "$info request:\n$out_data" ) if $out_data;
144              
145 166         246 my $answ;
146              
147 166 50       358 if ( $self->{server} eq 'Core' ) {
148 166         1645 require IO::EPP::Test::VerisignCore;
149              
150             eval{
151 166         431 $answ = IO::EPP::Test::VerisignCore::req( @_ );
152 166         412 1;
153             }
154 166 50       281 or do {
155 0         0 $self->{critical_error} = "$info req error: $@";
156 0         0 return;
157             };
158             }
159             else { # DotName, NameStore
160 0         0 require IO::EPP::Test::VerisignName;
161              
162             eval{
163 0         0 $answ = IO::EPP::Test::VerisignName::req( @_ );
164 0         0 1;
165             }
166 0 0       0 or do {
167 0         0 $self->{critical_error} = "$info req error: $@";
168 0         0 return;
169             };
170             }
171              
172 166         799 $self->epp_log( "$info answer:\n$answ" );
173              
174 166         436 return $answ;
175             }
176              
177              
178             =head1 METHODS
179              
180             Here are the features that distinguish the registry from the EPP RFC.
181             All basic information about functions is in L
182              
183             =head2 new
184              
185             See description in L
186              
187             Requires the C field to be specified, which can have values:
188             C for .com/.net/.edu,
189             C for .name,
190             C for cctld and new gtlds.
191              
192             =cut
193              
194             sub new {
195 28     28 1 8290 my ( $package, $params ) = @_;
196              
197 28 0 33     62 unless ( $params->{server} || $params->{dname} || $params->{tld} ) {
      0        
198 0 0       0 if ( $params->{sock_params}{PeerHost} =~ 'epp.verisign-grs.com' ) {
    0          
199 0         0 $params->{server} = 'Core';
200             }
201             elsif ( $params->{sock_params}{PeerHost} eq 'namestoressl.verisign-grs.com' ) {
202 0         0 $params->{server} = 'NameStore';
203             }
204             }
205              
206 28 0 33     56 unless ( $params->{server} or $params->{tld} or $params->{dname} ) {
      0        
207 0 0       0 return wantarray ? ( 0, 0, 'unknown server: Core or DotName, need set server, tld or dname field' ) : 0 ;
208             }
209              
210 28 100       76 $params->{dname} = lc $params->{dname} if $params->{dname};
211              
212 28   100     77 my $tld = $params->{tld} || '';
213              
214 28 50 66     71 if ( not $tld and $params->{dname} ) {
215 0         0 ( $tld ) = $params->{dname} =~ /\.([^.]+)$/;
216             }
217              
218 28 100 66     107 if ( $params->{server} and not $tld ) {
219 11 50       25 if ( $params->{server} eq 'Core' ) {
    0          
220 11         53 $tld = 'com';
221             }
222             elsif ( $params->{server} eq 'DotName' ) {
223 0         0 $tld = 'name';
224             }
225             else {
226 0         0 $tld = 'tv';
227             }
228             }
229              
230 28 50 33     99 if ( $tld and not $params->{server} ) {
231 0 0       0 if ( $tld eq 'name' ) {
    0          
232 0         0 $params->{server} = 'DotName';
233             }
234             elsif ( $tld =~ /^(com|net|edu)$/ ) {
235 0         0 $params->{server} = 'Core';
236             }
237             else {
238 0         0 $params->{server} = 'NameStore';
239             }
240             }
241              
242 28 50 33     64 $params->{server} = 'DotName' if $tld eq 'name' && $params->{server} ne 'DotName';
243              
244              
245 28         90 my ( $self, $code, $msg ) = $package->SUPER::new( $params );
246              
247 28 50 33     93 unless ( $code and $code == 1000 ) {
248 0 0       0 return wantarray ? ( 0, $code, $msg ) : 0;
249             }
250              
251 28 50       61 if ( $tld ) {
252 28 50       74 if ( lc ( $tld ) eq 'name' ) {
253 0         0 $self->{dzone} = 'name';
254             }
255             else {
256 28         81 $self->{dzone} = 'dot' . uc( $tld );
257             }
258              
259 28         91 $self->{namestore_ext} = " $sub_product_ext_begin" . $self->{dzone} . "$sub_product_ext_end\n";
260             }
261              
262 28 100       100 return wantarray ? ( $self, $code, $msg ) : $self;
263             }
264              
265              
266             =head2 login
267              
268             Ext params for login,
269              
270             INPUT: new password for change
271              
272             =cut
273              
274             sub login {
275 28     28 1 53 my ( $self, $pw ) = @_;
276              
277 28         43 my $svcs = '
278             urn:ietf:params:xml:ns:domain-1.0
279             urn:ietf:params:xml:ns:host-1.0
280             urn:ietf:params:xml:ns:contact-1.0
281             http://www.verisign.com/epp/lowbalance-poll-1.0';
282              
283 28         43 my $extension = '
284             urn:ietf:params:xml:ns:secDNS-1.1
285             http://www.verisign.com/epp/idnLang-1.0
286             http://www.verisign-grs.com/epp/namestoreExt-1.1
287             urn:ietf:params:xml:ns:rgp-1.0';
288              
289 28 50       67 if ( $self->{server} eq 'Core' ) {
    0          
    0          
290              
291 28         48 $svcs .= '
292             http://www.verisign.com/epp/registry-1.0
293             http://www.verisign.com/epp/rgp-poll-1.0';
294 28         47 $extension .= '
295             http://www.verisign.com/epp/whoisInf-1.0
296             urn:ietf:params:xml:ns:coa-1.0
297             http://www.verisign.com/epp/sync-1.0
298             http://www.verisign.com/epp/relatedDomain-1.0
299             urn:ietf:params:xml:ns:changePoll-1.0';
300              
301             }
302             elsif ( $self->{server} eq 'DotName' ) {
303             # moved to NameStore but extension in use
304             # https://www.verisign.com/assets/email-forwarding-mapping.pdf
305 0         0 $svcs .= '
306             http://www.nic.name/epp/nameWatch-1.0
307             http://www.nic.name/epp/emailFwd-1.0
308             http://www.nic.name/epp/defReg-1.0';
309 0         0 $extension .= '
310             http://www.nic.name/epp/persReg-1.0';
311              
312             }
313             elsif ( $self->{server} eq 'NameStore' ) {
314              
315 0         0 $svcs .= '
316             http://www.verisign.com/epp/rgp-poll-1.0
317             http://www.verisign.com/epp/balance-1.0
318             http://www.verisign-grs.com/epp/suggestion-1.1
319             http://www.verisign.com/epp/registry-1.0';
320 0         0 $extension .= '
321             http://www.verisign.com/epp/sync-1.0
322             http://www.verisign.com/epp/jobsContact-1.0
323             http://www.verisign.com/epp/premiumdomain-1.0
324             urn:ietf:params:xml:ns:launch-1.0
325             urn:ietf:params:xml:ns:verificationCode-1.0
326             urn:ietf:params:xml:ns:fee-0.9';
327              
328             }
329              
330 28         74 return $self->SUPER::login( $pw, $svcs, $extension );
331             }
332              
333             =head2 check_contacts
334              
335             .com/.net/.edu zones are not currently supported
336              
337             For more information, see L
338              
339             An Example
340              
341             my ( $answ, $msg ) = make_request( 'check_contacts', { tld => 'name', contacts => [ 'PP-SP-001', 'GB789HBHKS' ] } );
342              
343             # answer:
344              
345             {
346             'msg' => 'Command completed successfully',
347             'PP-SP-001' => {
348             'avail' => '0'
349             },
350             'GB789HBHKS' => {
351             'avail' => '1'
352             },
353             'BHJVJH' => {
354             'avail' => '1'
355             },
356             'code' => '1000'
357             };
358              
359             =cut
360              
361             sub check_contacts {
362 0     0 1 0 my ( $self, $params ) = @_;
363              
364 0         0 $params->{extension} = $self->{namestore_ext};
365              
366 0         0 return $self->SUPER::check_contacts( $params );
367             }
368              
369             =head2 create_contact
370              
371             You cannot register a contact that has two data types at once -- C and C,
372             a contact can have any type, but only one.
373              
374             .com/.net/.edu zones are not currently supported.
375              
376             For .jobs need additional parameters:
377             C, C, C, C.
378              
379             About .jobs parameters see L.
380              
381             The C / flag is not supported, and the registry does not display contacts in whois
382              
383             For more information, see L.
384              
385             Example with C data type
386              
387             my %cont = (
388             name => 'Protection of Private Person',
389             org => 'Private Person',
390             addr => 'PO box 01, Protection Service',
391             city => 'Moscow',
392             state => '',
393             postcode => '125000',
394             country_code => 'RU',
395             phone => '+7.4951111111',
396             fax => '+7.4951111111',
397             email => 'my@private.ru',
398             );
399              
400             my ( $answ, $msg ) = make_request( 'create_contact', { tld => 'name', %cont } );
401              
402             # answer
403             {
404             'msg' => 'Command completed successfully',
405             'cont_id' => '5555LECTU555',
406             'cre_date' => '2020-01-11 11:11:11',
407             'cltrid' => '5552d5cc9ab81c787eb9892eed888888',
408             'code' => 1000,
409             'svtrid' => '8888176177629-666916888'
410             };
411              
412             Example with C data type
413              
414             my %cont = (
415             loc => {
416             name => 'Защита персональных данных',
417             org => 'Частное лицо',
418             addr => 'А/Я 01, Сервис защиты персональных данных',
419             city => 'Москва',
420             state => '',
421             postcode => '125000',
422             country_code => 'RU',
423             },
424             phone => '+7.4951111111',
425             fax => '+7.4951111111',
426             email => 'my@private.ru',
427             );
428              
429             my ( $answ, $msg ) = make_request( 'create_contact', { tld => 'name', %cont } );
430              
431             # answer
432              
433             {
434             'msg' => 'Command completed successfully',
435             'cont_id' => '5555EMELT555',
436             'cre_date' => '2020-01-11 11:11:11',
437             'cltrid' => '88807717dfcb0ea49d0106697e888888',
438             'code' => 1000,
439             'svtrid' => '8889175980353-666988888'
440             };
441              
442             =cut
443              
444             sub create_contact {
445 0     0 1 0 my ( $self, $params ) = @_;
446              
447 0   0     0 $params->{cont_id} ||= IO::EPP::Base::gen_id( 16 );
448              
449 0         0 $params->{authinfo} = IO::EPP::Base::gen_pw( 16 );
450              
451 0         0 my $extension = '';
452              
453 0 0       0 if ( $self->{dzone} eq 'dotJOBS' ) {
454 0         0 $extension .= q| \n|;
455 0         0 $extension .= " $$params{jobs_title}\n";
456 0         0 $extension .= " $$params{jobs_website}\n";
457 0         0 $extension .= " $$params{jobs_industry_type}\n";
458 0         0 $extension .= " $$params{is_admin}\n";
459 0         0 $extension .= " No\n";
460 0         0 $extension .= " \n";
461             }
462              
463 0         0 $params->{extension} = $extension . $self->{namestore_ext};
464              
465 0         0 return $self->SUPER::create_contact( $params );
466             }
467              
468             =head2 get_contact_info
469              
470             .com/.net/.edu zones are not currently supported.
471              
472             For more information, see L.
473              
474             An Example
475              
476             my ( $answ, $msg ) = make_request( 'get_contact_info', { tld => 'name', cont_id => '5555LECTU555' } );
477              
478             # answer
479              
480             {
481             'int' => {
482             'city' => 'Moscow',
483             'country_code' => 'RU',
484             'name' => 'Protection of Private Person',
485             'postcode' => '125000',
486             'addr' => 'PO box 01, Protection Service',
487             'state' => undef
488             },
489             'roid' => '22222100_CONTACT_NAME-VRSN',
490             'cre_date' => '2020-01-11 11:11:11',
491             'email' => [
492             'my@private.ru'
493             ],
494             'upd_date' => '2020-01-11 11:11:11',
495             'fax' => [
496             '+7.4951111111'
497             ],
498             'creater' => 'login',
499             'authinfo' => 'HF+B5ON$,qUDkyYW',
500             'code' => '1000',
501             'owner' => 'LOGIN',
502             'msg' => 'Command completed successfully',
503             'phone' => [
504             '+7.4951111111'
505             ],
506             'updater' => 'login',
507             'cont_id' => '5555LECTU555',
508             'statuses' => {
509             'ok' => '+'
510             }
511             };
512              
513             =cut
514              
515             sub get_contact_info {
516 0     0 1 0 my ( $self, $params ) = @_;
517              
518 0         0 $params->{extension} = $self->{namestore_ext};
519              
520 0         0 return $self->SUPER::get_contact_info( $params );
521             }
522              
523              
524             =head2 update_contact
525              
526             .com/.net/.edu zones are not currently supported.
527              
528             For more information, see L.
529              
530             =cut
531              
532             sub update_contact {
533 0     0 1 0 my ( $self, $params ) = @_;
534              
535 0         0 $params->{extension} = $self->{namestore_ext};
536              
537 0         0 return $self->SUPER::update_contact( $params );
538             }
539              
540              
541             =head2 delete_contact
542              
543             .com/.net/.edu zones are not currently supported.
544              
545             For more information, see L.
546              
547             =cut
548              
549             sub delete_contact {
550 0     0 1 0 my ( $self, $params ) = @_;
551              
552 0         0 $params->{extension} = $self->{namestore_ext};
553              
554 0         0 return $self->SUPER::delete_contact( $params );
555             }
556              
557              
558             sub check_nss {
559 1     1 1 2 my ( $self, $params ) = @_;
560              
561 1         2 $params->{extension} = $self->{namestore_ext};
562              
563 1         5 return $self->SUPER::check_nss( $params );
564             }
565              
566             =head2 create_ns
567              
568             Within a single server, all NS-s are shared, that is,
569             if you register NS for the .com tld, it will be available for the .net tld as well.
570              
571             For details, see L.
572              
573             =cut
574              
575             sub create_ns {
576 9     9 1 1251 my ( $self, $params ) = @_;
577              
578 9         20 $params->{extension} = $self->{namestore_ext};
579              
580 9         29 return $self->SUPER::create_ns( $params );
581             }
582              
583              
584             sub get_ns_info {
585 4     4 1 3659 my ( $self, $params ) = @_;
586              
587 4         40 $params->{extension} = $self->{namestore_ext};
588              
589 4         20 return $self->SUPER::get_ns_info( $params );
590             }
591              
592              
593             sub update_ns {
594 13     13 1 14414 my ( $self, $params ) = @_;
595              
596 13         31 $params->{extension} = $self->{namestore_ext};
597              
598 13 50       43 $params->{no_empty_chg} = 1 unless $params->{chg};
599              
600 13         44 return $self->SUPER::update_ns( $params );
601             }
602              
603              
604             sub delete_ns {
605 3     3 1 2491 my ( $self, $params ) = @_;
606              
607 3         6 $params->{extension} = $self->{namestore_ext};
608              
609 3         13 return $self->SUPER::delete_ns( $params );
610             }
611              
612             =head2 check_domains
613              
614             With a single request, you can check availability in all zones of this server at once,
615             if they have accreditation
616              
617             In the example, accreditation is not available in the .edu tld.
618             The .info tld belongs to a different registry.
619              
620             my ( $answ, $msg ) = make_request( 'check_domains', {
621             tld => 'com',
622             domains => [ 'qwerty.com', 'bjdwferbkr-e3jd0hf.net', 'bjk8bj-kewew.edu', 'xn--xx.com', 'hiebw.info' ]
623             } );
624              
625             # answer
626              
627             {
628             'msg' => 'Command completed successfully',
629             'qwerty.com' => {
630             'reason' => 'Domain exists',
631             'avail' => '0'
632             },
633             'hiebw.info' => {
634             'reason' => 'Not an authoritative TLD',
635             'avail' => '0'
636             },
637             'bjk8bj-kewew.edu' => {
638             'reason' => 'Not authorized',
639             'avail' => '0'
640             },
641             'code' => '1000',
642             'xn--xx.com' => {
643             'reason' => 'Invalid punycode encoding',
644             'avail' => '0'
645             },
646             'bjdwferbkr-e3jd0hf.net' => {
647             'avail' => '1'
648             }
649             };
650              
651             For details, see L.
652              
653             =cut
654              
655             sub check_domains {
656 1     1 1 3 my ( $self, $params ) = @_;
657              
658 1         3 $params->{extension} = $self->{namestore_ext};
659              
660 1         8 return $self->SUPER::check_domains( $params );
661             }
662              
663             =head2 create_domain
664              
665             For IDN domains you need to specify the language code in the C field
666              
667             See L,
668             and L for .com, .net
669              
670             An Example of a domain with C, without NSs
671              
672             ( $answ, $code, $msg ) = $conn->create_domain( {
673             tld => 'com',
674             dname => 'xn----htbdjfuifot5a9e.com', # хитрый-домен.com
675             period => 1,
676             idn_lang => 'RUS'
677             } );
678              
679             # answer
680              
681             {
682             'dname' => 'xn----htbdjfuifot5a9e.com',
683             'exp_date' => '2021-01-01 01:01:01',
684             'cre_date' => '2020-01-01 01:01:01',
685             'cltrid' => '37777a45e43d0c691c65538aacd77777',
686             'svtrid' => '8888827708-7856526698888'
687             };
688              
689             For more information, see L.
690              
691             =cut
692              
693             sub create_domain {
694 9     9 1 9933 my ( $self, $params ) = @_;
695              
696 9   66     48 $params->{authinfo} ||= IO::EPP::Base::gen_pw( 16 );
697              
698             # Do not change the order of records
699 9         17 my $extension = $self->{namestore_ext};
700              
701 9 50       21 if ( $params->{idn_lang} ) {
702 0         0 $extension .= " $$params{idn_lang}\n";
703             }
704              
705 9         19 $params->{extension} = $extension;
706              
707 9         29 return $self->SUPER::create_domain( $params );
708             }
709              
710              
711             sub transfer {
712 0     0 1 0 my ( $self, $params ) = @_;
713              
714 0 0       0 if ( defined $params->{authinfo} ) {
715 0         0 $params->{authinfo} =~ s/&/&/g;
716 0         0 $params->{authinfo} =~ s/
717 0         0 $params->{authinfo} =~ s/>/>/g;
718             }
719              
720 0         0 $params->{extension} = $self->{namestore_ext};
721              
722 0         0 return $self->SUPER::transfer( $params );
723             }
724              
725             =head2 get_domain_info
726              
727             For details, see L.
728              
729             An Example
730              
731             my ( $answ, $msg, $conn ) = make_request( 'get_domain_info', { dname => 'llll.com' } );
732              
733             # answer
734              
735             {
736             'msg' => 'Command completed successfully',
737             'owner' => '1000',
738             'hosts' => [
739             'ns2.llll.com',
740             'ns1.llll.com'
741             ],
742             'roid' => '2222489946_DOMAIN_COM-VRSN',
743             'exp_date' => '2020-01-01 01:01:01',
744             'cre_date' => '2018-01-01 01:01:01',
745             'nss' => [
746             'ns1.rrr.ru',
747             'ns2.rrr.ru'
748             ],
749             'dname' => 'llll.com',
750             'updater' => 'login',
751             'upd_date' => '2019-12-30 13:17:54',
752             'creater' => 'login',
753             'authinfo' => 'AAA:8k.o5*p"_pAA',
754             'statuses' => {
755             'clientTransferProhibited' => '+'
756             },
757             'code' => 1000
758             };
759              
760             =cut
761              
762             sub get_domain_info {
763 10     10 1 8357 my ( $self, $params ) = @_;
764              
765 10         24 $params->{extension} = $self->{namestore_ext};
766              
767 10         34 return $self->SUPER::get_domain_info( $params );
768             }
769              
770              
771             sub renew_domain {
772 6     6 1 5561 my ( $self, $params ) = @_;
773              
774 6         27 $params->{extension} = $self->{namestore_ext};
775              
776 6         24 return $self->SUPER::renew_domain( $params );
777             }
778              
779              
780             sub update_domain {
781 17     17 1 1898 my ( $self, $params ) = @_;
782              
783 17         35 $params->{extension} = $self->{namestore_ext};
784              
785 17         50 return $self->SUPER::update_domain( $params );
786             }
787              
788             =head2 delete_domain
789              
790             You can delete a domain only if it does not have NS-s that are used by other domains.
791             If there are such NS-s, they should be renamed using the C<< update_ns( chg => { new_name => 'new.ns.xxxx.com' } ) >>,
792             For details see L.
793              
794             For more information about C, see L
795              
796             =cut
797              
798             sub delete_domain {
799 6     6 1 4579 my ( $self, $params ) = @_;
800              
801 6         15 $params->{extension} = $self->{namestore_ext};
802              
803 6         22 return $self->SUPER::delete_domain( $params );
804             }
805              
806              
807             =head2 restore_domain
808              
809             First call of restore — request
810              
811             INPUT:
812              
813             params with key:
814              
815             C — domain name
816              
817             OUTPUT:
818             see L.
819              
820             =cut
821              
822             sub restore_domain {
823 1     1 1 8 my ( $self, $params ) = @_;
824              
825             $params->{extension} = $self->{namestore_ext} .
826 1         7 "
827            
828             \n";
829              
830 1         4 return $self->SUPER::update_domain( $params );
831             }
832              
833              
834             =head2 confirmations_restore_domain
835              
836             Secont call of restore — confirmation
837              
838             INPUT:
839              
840             params with keys:
841              
842             C — domain name
843              
844             C — whois before delete, may be none;
845              
846             C — whois now, may be none;
847              
848             C — domain delete datetime in UTC;
849              
850             C — restore request call datetime in UTC.
851              
852             The following fields already contain the required value, they do not need to be passed:
853              
854             C — restore reason: "Customer forgot to renew.";
855              
856             C — need to write what it is for the client:
857             "I agree that the Domain Name has not been restored in order to assume the rights to use or sell the name to myself or for any third party.
858             I agree that the information provided in this Restore Report is true to the best of my knowledge, and acknowledge that intentionally supplying false information in the Restore Report shall constitute an incurable material breach of the Registry-Registrar Agreement.";
859              
860             C — additional information, may be empty.
861              
862             OUTPUT:
863             see L.
864              
865             =cut
866              
867             sub confirmations_restore_domain {
868 1     1 1 994 my ( $self, $params ) = @_;
869              
870 1         3 my $extension = $self->{namestore_ext};
871              
872 1   50     8 $params->{pre_data} ||= 'none';
873 1   50     7 $params->{post_data} ||= 'none';
874              
875 1         10 $params->{extension} = <
876             $extension
877            
878            
879            
880             $$params{pre_data}
881             $$params{post_data}
882             $$params{del_time}
883             $$params{rest_time}
884             Customer forgot to renew.
885             I agree that the Domain Name has not been restored in order to assume the rights to use or sell the name to myself or for any third party.
886             I agree that the information provided in this Restore Report is true to the best of my knowledge, and acknowledge that intentionally supplying false information in the Restore Report shall constitute an incurable material breach of the Registry-Registrar Agreement.
887            
888            
889            
890            
891             RGPEXT
892              
893 1         6 return $self->SUPER::update_domain( $params );
894             }
895              
896              
897             =head2 req_poll_ext
898              
899             Processing a special messages from a poll.
900             Now only processing the message about deleting NS.
901              
902             An Example
903              
904             my ( $answ, $msg, $conn ) = make_request( 'req_poll', \%conn_params );
905              
906             # answer:
907              
908             {
909             'roid' => '77777866_HOST_NAME-VRSN',
910             'date' => '2020-01-10 10:10:10',
911             'cre_date' => '2010-01-10 10:15:05',
912             'ips' => [
913             '3.1.1.1'
914             ],
915             'upd_date' => '2013-01-01 10:00:01',
916             'qmsg' => 'Unused Objects Policy',
917             'creater' => 'direct',
918             'id' => '2222282',
919             'ext' => {
920             'change' => {
921             'who' => 'ctldbatch',
922             'row_msg' => 'delete',
923             'date' => '2020-01-10 10:00:10.000',
924             'reason' => 'Unused objects policy',
925             'svtrid' => '416801225',
926             'state' => 'before'
927             }
928             },
929             'code' => 1301,
930             'msg' => 'Command completed successfully; ack to dequeue',
931             'owner' => 'LOGIN',
932             'count' => '13',
933             'cltrid' => '2222701245bb287334838a273fd22222',
934             'ns' => 'ns1.abuse.name',
935             'updater' => 'ctldbatch',
936             'statuses' => {
937             'ok' => '+'
938             },
939             'svtrid' => '7777770945650-666947777'
940             };
941              
942             =cut
943              
944             sub req_poll_ext {
945 0     0 1   my ( $self, $ext ) = @_;
946              
947 0           my %info;
948              
949 0 0         if ( $ext =~ m|]+>(.+)|s ) {
950 0           $info{change}{'state'} = $1;
951 0           my $row = $2;
952              
953 0 0         if ( $row =~ s|([^<>]+)|| ) {
954 0           $info{change}{date} = $1;
955              
956 0           $info{change}{date} =~ s/T/ /;
957 0           $info{change}{date} =~ s/Z$//;
958             }
959              
960 0 0         if ( $row =~ s|([^<>]+)|| ) {
961 0           $info{change}{who} = $1;
962             }
963              
964 0 0         if ( $row =~ s|([^<>]+)|| ) {
965 0           $info{change}{svtrid} = $1;
966             }
967              
968 0 0         if ( $row =~ s|([^<>]+)|| ) {
969 0           $info{change}{reason} = $1;
970             }
971              
972 0           $info{change}{row_msg} = $row;
973             }
974             else {
975 0           $info{ext} = $ext;
976             }
977              
978 0           return \%info;
979             }
980              
981              
982             =head2 get_registry_info
983              
984             Registry information for the specified zone
985              
986             key in params: C
987              
988             An Example:
989              
990             my ( $answ, $code, $msg ) = $conn->get_registry_info( { tld => 'net' } );
991              
992             # answer
993              
994             {
995             'alphaNumStart' => 'true',
996             'max' => [
997             '13',
998             '13'
999             ],
1000             'language code' => [
1001             'ARG',
1002             'ASM',
1003             'AST',
1004             'AVE',
1005             'AWA',
1006             'BAK',
1007             'BAL',
1008             'BAN',
1009             'BAS',
1010             'BEL',
1011             'BOS',
1012             'CAR',
1013             'CHE',
1014             'CHV',
1015             'COP',
1016             'COS',
1017             'WEL',
1018             'DIV',
1019             'DOI',
1020             'FIJ',
1021             'FRY',
1022             'GLA',
1023             'GLE',
1024             'GON',
1025             'INC',
1026             'IND',
1027             'INH',
1028             'JAV',
1029             'KAS',
1030             'KAZ',
1031             'KHM',
1032             'KIR',
1033             'LTZ',
1034             'MAO',
1035             'MAY',
1036             'MLT',
1037             'MOL',
1038             'MON',
1039             'OSS',
1040             'PUS',
1041             'SIN',
1042             'SMO',
1043             'SOM',
1044             'SRD',
1045             'TGK',
1046             'YID',
1047             'AFR',
1048             'ALB',
1049             'ARA',
1050             'ARM',
1051             'AZE',
1052             'BAQ',
1053             'BEN',
1054             'BHO',
1055             'TIB',
1056             'BUL',
1057             'BUR',
1058             'CAT',
1059             'CZE',
1060             'CHI',
1061             'DAN',
1062             'GER',
1063             'DUT',
1064             'GRE',
1065             'ENG',
1066             'EST',
1067             'FAO',
1068             'PER',
1069             'FIN',
1070             'FRE',
1071             'GEO',
1072             'GUJ',
1073             'HEB',
1074             'HIN',
1075             'SCR',
1076             'HUN',
1077             'ICE',
1078             'ITA',
1079             'JPN',
1080             'KOR',
1081             'KUR',
1082             'LAO',
1083             'LAV',
1084             'LIT',
1085             'MAC',
1086             'MAL',
1087             'NEP',
1088             'NOR',
1089             'ORI',
1090             'PAN',
1091             'POL',
1092             'POR',
1093             'RAJ',
1094             'RUM',
1095             'RUS',
1096             'SAN',
1097             'SCC',
1098             'SLO',
1099             'SLV',
1100             'SND',
1101             'SPA',
1102             'SWA',
1103             'SWE',
1104             'SYR',
1105             'TAM',
1106             'TEL',
1107             'THA',
1108             'TUR',
1109             'UKR',
1110             'URD',
1111             'UZB',
1112             'VIE'
1113             ],
1114             'gracePeriod command:transfer unit:d' => '5',
1115             'gracePeriod command:create unit:d' => '5',
1116             'default unit:y' => [
1117             '1',
1118             '1',
1119             '1'
1120             ],
1121             'gracePeriod command:autorenew unit:d' => '45',
1122             'subProduct' => 'NET',
1123             'idnVersion' => '1.1',
1124             'expression' => [
1125             '[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?',
1126             '^(?=.*\\\\d)(?=.*[a-zA-Z])(?=.*[\\\\x21-\\\\x2F\\\\x3A-\\\\x40\\\\x5B-\\\\x60\\\\x7B-\\\\x7E])[\\\\x21-\\\\x7e]{8,32}$',
1127             '^([\\-|\\w])+\\.([\\-|\\w])+\\s{0,}$)$'
1128             ],
1129             'redemptionPeriod unit:d' => '30',
1130             'encoding' => 'PunyCode',
1131             'max unit:y' => [
1132             '10',
1133             '10',
1134             '1'
1135             ],
1136             'name' => 'NET',
1137             'maxCheckHost' => '20',
1138             'urgent' => 'false',
1139             'default' => '604800',
1140             'onlyDnsChars' => 'true',
1141             'maxCheckDomain' => '20',
1142             'transferHoldPeriod unit:d' => '5',
1143             'digestType' => [
1144             'SHA-1',
1145             'SHA-256',
1146             'GOST R 34.11-94',
1147             'SHA-384'
1148             ],
1149             'alg' => [
1150             'RSAMD5',
1151             'DH',
1152             'DSA',
1153             'RSASHA1',
1154             'DSA-NSEC3-SHA1',
1155             'RSASHA1-NSEC3-SHA1',
1156             'RSASHA256',
1157             'RSASHA512',
1158             'ECC-GOST',
1159             'ECDSAP256SHA256',
1160             'ECDSAP384SHA384'
1161             ],
1162             'startDate' => '2000-01-01T00:00:00Z',
1163             'minLength' => '3',
1164             'status' => [
1165             'ok',
1166             'serverHold',
1167             'serverRenewProhibited',
1168             'serverTransferProhibited',
1169             'serverUpdateProhibited',
1170             'serverDeleteProhibited',
1171             'redemptionPeriod',
1172             'pendingRestore',
1173             'pendingDelete',
1174             'clientRenewProhibited',
1175             'clientTransferProhibited',
1176             'clientUpdateProhibited',
1177             'clientDeleteProhibited',
1178             'pendingTransfer',
1179             'clientHold',
1180             'ok',
1181             'pendingDelete',
1182             'pendingTransfer',
1183             'serverUpdateProhibited',
1184             'serverDeleteProhibited',
1185             'clientUpdateProhibited',
1186             'clientDeleteProhibited',
1187             'linked'
1188             ],
1189             'zoneMember type:equal' => 'NET',
1190             'group' => 'THIN',
1191             'clientDefined' => 'false',
1192             'pendingRestore unit:d' => '7',
1193             'minIP' => [
1194             '1',
1195             '0'
1196             ],
1197             'extURI required:true' => [
1198             'urn:ietf:params:xml:ns:coa-1.0',
1199             'http://www.verisign.com/epp/idnLang-1.0',
1200             'urn:ietf:params:xml:ns:secDNS-1.1',
1201             'http://www.verisign-grs.com/epp/namestoreExt-1.1',
1202             'urn:ietf:params:xml:ns:rgp-1.0',
1203             'http://www.verisign.com/epp/whoisInf-1.0',
1204             'http://www.verisign.com/epp/sync-1.0',
1205             'http://www.verisign.com/epp/relatedDomain-1.0',
1206             'urn:ietf:params:xml:ns:launch-1.0'
1207             ],
1208             'upDate' => '2013-08-10T21:16:01Z',
1209             'min unit:y' => [
1210             '1',
1211             '1',
1212             '1'
1213             ],
1214             'unicodeVersion' => '6.0',
1215             'commingleAllowed' => 'false',
1216             'pendingDelete unit:d' => '5',
1217             'sharePolicy' => [
1218             'perSystem',
1219             'perSystem'
1220             ],
1221             'min' => [
1222             '0',
1223             '0',
1224             '1'
1225             ],
1226             'idnaVersion' => 'IDNA 2008',
1227             'objURI required:true' => [
1228             'urn:ietf:params:xml:ns:domain-1.0',
1229             'urn:ietf:params:xml:ns:contact-1.0',
1230             'urn:ietf:params:xml:ns:host-1.0',
1231             'http://www.verisign.com/epp/registry-1.0',
1232             'http://www.verisign.com/epp/lowbalance-poll-1.0',
1233             'http://www.verisign.com/epp/rgp-poll-1.0'
1234             ],
1235             'crDate' => '2000-01-01T00:00:00Z',
1236             'premiumSupport' => 'false',
1237             'alphaNumEnd' => 'true',
1238             'gracePeriod command:renew unit:d' => '5',
1239             'maxLength' => '63',
1240             'maxIP' => [
1241             '13',
1242             '0'
1243             ],
1244             'contactsSupported' => 'false'
1245             };
1246              
1247             =cut
1248              
1249             sub get_registry_info {
1250 0     0 1   my ( $self, $params ) = @_;
1251              
1252 0           my $tld = uc( $params->{tld} );
1253              
1254 0           my $cltrid = IO::EPP::Base::get_cltrid();
1255              
1256 0           my $body = <
1257             $$self{urn}{head}
1258            
1259            
1260            
1261             $tld
1262            
1263            
1264             $cltrid
1265            
1266            
1267             RINFO
1268              
1269 0           my $content = $self->req( $body, 'get_registry_info' );
1270              
1271 0 0         if ( $content =~ /result code=['"](\d+)['"]/ ) {
1272 0           my $rcode = $1 + 0;
1273              
1274 0           my $msg = '';
1275 0 0         if ( $content =~ /]*>(.+)<\/msg>.+\/result>/s ) {
1276 0           $msg = $1;
1277             }
1278              
1279 0           my %info;
1280              
1281             # take the main part and disassemble
1282 0 0         if ( $content =~ /(.+)<\/resData>/s ) {
1283 0           my $rdata = $1;
1284              
1285 0           my @list = $rdata =~ m|(]+>[^<>]+]+>)|g;
1286              
1287 0           foreach my $row ( @list ) {
1288 0 0         if ( $row =~ m|([^<>]+)]+>| ) {
    0          
    0          
1289 0           my $k = $1;
1290              
1291 0           push @{$info{$k}}, $2;
  0            
1292             }
1293             elsif ( $row =~ m|([^<>]+)]+>| ) {
1294 0           my $k = "$1 $2:$3";
1295              
1296 0           push @{$info{$k}}, $4;
  0            
1297             }
1298             elsif ( $row =~ m|([^<>]+)]+>| ) {
1299 0           my $k = "$1 $2:$3 $4:$5";
1300              
1301 0           push @{$info{$k}}, $6;
  0            
1302             }
1303             }
1304              
1305 0           @list = $rdata =~ m|(]+/>)|g;
1306              
1307 0           foreach my $row ( @list ) {
1308 0 0         if ( $row =~ m|| ) {
1309 0           my $k .= "$1 $2";
1310              
1311 0           push @{$info{$k}}, "$3";
  0            
1312             }
1313             }
1314              
1315 0           foreach my $k ( keys %info ) {
1316 0 0         if ( ( scalar @{$info{$k}} ) == 1 ) {
  0            
1317 0           $info{$k} = $info{$k}[0];
1318             }
1319             }
1320             }
1321             else {
1322 0 0         return wantarray ? ( 0, $rcode, $msg ) : 0 ;
1323             }
1324              
1325 0 0         return wantarray ? ( \%info, $rcode, $msg ) : \%info;
1326             }
1327              
1328 0 0         return wantarray ? ( 0, 0, 'empty answer' ) : 0 ;
1329             }
1330              
1331              
1332             1;
1333              
1334              
1335             __END__