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