File Coverage

blib/lib/IO/EPP/Flexireg.pm
Criterion Covered Total %
statement 12 126 9.5
branch 0 48 0.0
condition 0 25 0.0
subroutine 4 14 28.5
pod 7 10 70.0
total 23 223 10.3


line stmt bran cond sub pod time code
1             package IO::EPP::Flexireg;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::Flexireg
8              
9             =head1 SYNOPSIS
10              
11             use IO::EPP::Flexireg;
12              
13             # Parameters for IO::Socket::SSL
14             my %sock_params = (
15             PeerHost => 'epp.flexireg.net',
16             PeerPort => 700,
17             Timeout => 30,
18             );
19              
20             # Create object, get greeting and call login()
21             my $conn = IO::EPP::Flexireg->new( {
22             user => 'login-msk-fir',
23             pass => 'xxxxxxxx',
24             sock_params => \%sock_params,
25             test_mode => 0, # real connect
26             } );
27              
28             # Check domain
29             my ( $answ, $code, $msg ) = $conn->check_domains( { domains => [ 'my.moscow', 'xn--l1ae5c.xn--80adxhks' ] } );
30              
31             # Call logout() and destroy object
32             undef $conn;
33              
34             =head1 DESCRIPTION
35              
36             Module work with Flexireg tlds: .moscow, .москва, ru.net and 3lvl.ru/su
37              
38             Frontend:
39             https://faitid.org/
40              
41             Backend:
42             http://flexireg.net/
43              
44              
45             Documentaion:
46              
47             moscow, москва
48             L,
49             L
50              
51             ru.net+
52             L
53              
54              
55             =cut
56              
57 1     1   1764 use IO::EPP::Base;
  1         20  
  1         33  
58 1     1   6 use parent qw( IO::EPP::Base );
  1         2  
  1         5  
59              
60 1     1   55 use strict;
  1         2  
  1         15  
61 1     1   4 use warnings;
  1         2  
  1         1389  
62              
63             sub make_request {
64 0     0 1   my ( $action, $params ) = @_;
65              
66 0           my ( $self, $code, $msg, $answ );
67              
68 0 0         unless ( $params->{conn} ) {
69 0   0       $params->{sock_params}{PeerHost} ||= 'epp.flexireg.net';
70 0   0       $params->{sock_params}{PeerPort} ||= 700;
71              
72 0           ( $self, $code, $msg ) = __PACKAGE__->new( $params );
73              
74 0 0 0       unless ( $code and $code == 1000 ) {
75 0           goto END_MR;
76             }
77             }
78             else {
79 0           $self = $params->{conn};
80             }
81              
82              
83 0           $self->{critical_error} = '';
84              
85 0 0         if ( $self->can( $action ) ) {
86 0           ( $answ, $code, $msg ) = $self->$action( $params );
87             }
88             else {
89 0           $msg = "undefined command <$action>, request cancelled";
90 0           $code = 0;
91             }
92              
93              
94             END_MR:
95              
96 0 0         $msg .= '; ' . $self->{critical_error} if $self->{critical_error};
97              
98 0           my $full_answ = "code: $code\nmsg: $msg";
99              
100 0 0 0       $answ = {} unless $answ && ref $answ;
101              
102 0           $answ->{code} = $code;
103 0           $answ->{msg} = $msg;
104              
105 0 0         return wantarray ? ( $answ, $full_answ, $self ) : $answ;
106             }
107              
108             =head1 METHODS
109              
110             Further overlap functions where the provider has features
111              
112             =head2 login
113              
114             Ext params for login,
115              
116             INPUT: new password for change
117              
118             =cut
119              
120             sub login {
121 0     0 1   my ( $self, $pw ) = @_;
122              
123 0           my $svcs = '
124             urn:ietf:params:xml:ns:contact-1.0
125             urn:ietf:params:xml:ns:domain-1.0
126             urn:ietf:params:xml:ns:host-1.0';
127 0           my $extension = '
128             http://www.tcinet.ru/epp/tci-contact-ext-1.0
129             urn:ietf:params:xml:ns:fee-0.11
130             urn:ietf:params:xml:ns:idn-1.0
131             urn:ietf:params:xml:ns:launch-1.0
132             urn:ietf:params:xml:ns:rgp-1.0
133             urn:ietf:params:xml:ns:secDNS-1.1';
134              
135 0           return $self->SUPER::login( $pw, $svcs, $extension );
136             }
137              
138              
139             sub contact_ext {
140 0     0 0   my ( undef, $params ) = @_;
141              
142 0           my $ext = '';
143              
144 0 0         if ( $params->{birthday} ) {
145 0           $ext .= "\n";
146              
147 0           foreach my $f ( 'birthday', 'passport', 'TIN' ) {
148 0 0         $ext .= " $$params{$f}\n" if $$params{$f};
149             }
150              
151 0           $ext .= " ";
152             }
153              
154 0 0         if ( $params->{legal} ) {
155 0           $ext .= " \n";
156 0           foreach my $type ( 'int', 'loc' ) {
157 0           $ext .= qq| \n|;
158              
159 0 0         $$params{legal}{$type}{addr} = [ $$params{legal}{$type}{addr} ] unless ref $$params{legal}{$type}{addr};
160              
161 0           foreach my $s ( @{$$params{legal}{$type}{addr}} ) {
  0            
162 0           $ext .= " $s\n";
163             }
164              
165 0           $ext .= " $$params{legal}{$type}{city}\n";
166 0 0         $ext .= ( $$params{legal}{$type}{'state'} ? " $$params{legal}{$type}{state}\n" : " \n" );
167 0 0         $ext .= ( $$params{legal}{$type}{postcode} ? " $$params{legal}{$type}{postcode}\n" : " \n" );
168 0           $ext .= " $$params{legal}{$type}{country_code}\n";
169              
170 0           $ext .= " \n";
171             }
172 0           $ext .= " $$params{TIN}\n";
173 0           $ext .= " ";
174             }
175              
176 0           return $ext;
177             }
178              
179              
180             =head2 create_contact
181              
182             For moscow/москва:
183              
184             When registering a contact, you must specify both int type data and loc type data, and if the domain owner has passport data in Cyrillic,
185             then loc type data must be entered in Cyrillic.
186             This is mandatory for citizens and legal entities of Russia, Ukraine, Belarus and other countries that have the Cyrillic alphabet.
187              
188             In addition, the owner must provide additional information.
189              
190             For individuals:
191              
192             C -- date of birth;
193              
194             C -- passport series and number, by whom and when it was issued;
195              
196             C -- TIN for individual entrepreneurs.
197              
198             For legal entities:
199              
200             hashref C, that contains the legal address, it also needs to specify two types: C and C, consisting of the fields C, C, C, C, C.
201              
202             You also need to specify the C field.
203              
204             An Example:
205              
206             Individuals:
207              
208             my %cont = (
209             int => {
210             first_name => 'Igor',
211             patronymic => 'Igorevich',
212             last_name => 'Igorev',
213             org => '',
214             addr => 'Igoreva str, 129',
215             city => 'Igorevsk',
216             state => 'Ogorevskaya obl.',
217             postcode => '699001',
218             country_code => 'RU',
219             },
220             loc => {
221             first_name => 'Игорь',
222             patronymic => 'Игоревич',
223             last_name => 'Игорев',
224             org => '',
225             addr => 'ул. Игорева, 129',
226             city => 'Игоревск',
227             state => 'Игоревская обл.',
228             postcode => '699001',
229             country_code => 'RU',
230             },
231             birthday => '1909-01-14',
232             passport => '11.11.2011, выдан Отделом УФМС России по Игоревской области в г.Игоревске, 2211 446622',
233             phone => '+7.9012345678',
234             fax => '',
235             email => 'igor@i.ru',
236             TIN => '',
237             };
238              
239             my ( $answ, $msg, $conn ) = make_request( 'create_contact', \%cont );
240              
241             Legal entities:
242              
243             my %cont = (
244             int => {
245             first_name => 'Igor',
246             patronymic => 'Igorevich',
247             last_name => 'Igorev',
248             org => 'Igor and Co',
249             addr => 'Igoreva str, 129',
250             city => 'Igorevsk',
251             state => 'Igorevskaya obl.',
252             postcode => '699001',
253             country_code => 'RU',
254             },
255             loc => {
256             first_name => 'Игорь',
257             patronymic => 'Игоревич',
258             last_name => 'Игорев',
259             org => 'Игорь и Ко',
260             addr => 'ул. Игорева, 129',
261             city => 'Игоревск',
262             state => 'Игоревская обл.',
263             postcode => '699001',
264             country_code => 'RU',
265             },
266             legal => {
267             int => {
268             addr => 'Company str, 1',
269             city => 'Igorevsk',
270             state => 'Igorevskaya obl.',
271             postcode => '699002',
272             country_code => 'RU',
273             },
274             loc => {
275             addr => 'ул. Компаний, 1',
276             city => 'Игоревск',
277             state => 'Игоревская обл.',
278             postcode => '699002',
279             country_code => 'RU',
280             }
281             }
282             };
283              
284             my ( $answ, $code, $msg ) = $conn->create_contact( \%cont );
285              
286             =cut
287              
288             sub create_contact {
289 0     0 1   my ( $self, $params ) = @_;
290              
291 0           $params->{cont_id} = IO::EPP::Base::gen_id( 16 );
292              
293 0           $params->{authinfo} = IO::EPP::Base::gen_pw( 16 );
294              
295 0           my $extension = $self->contact_ext( $params );
296              
297 0 0         if ( $extension ) {
298 0           $params->{extension} = qq| \n$extension \n|;
299             }
300              
301 0           return $self->SUPER::create_contact( $params );
302             }
303              
304              
305             sub get_contact_ext {
306 0     0 0   my ( undef, $ext ) = @_;
307              
308 0           my %cont;
309              
310 0 0         if ( $ext =~ m|]+tci-contact-ext-1[^<>]+>(.+?)|s ) {
311 0           my $data = $1;
312              
313 0 0         if ( $data =~ m|(.+)|s ) {
314 0           my $person_data = $1;
315              
316 0           my @rows = $person_data =~ m|([^<>]+)|gs;
317              
318 0           foreach my $row ( @rows ) {
319 0 0         if ( $row =~ m|([^<>]+)| ) {
320 0           $cont{$1} = $2;
321             }
322             }
323             }
324              
325 0 0         if ( $data =~ m|(.+)|s ) {
326 0           my $org_data = $1;
327              
328 0           ( $cont{TIN} ) = $org_data =~ /([^<>]+)<\/contact:TIN>/;
329              
330 0           my @atypes = ( 'int', 'loc' );
331 0           foreach my $atype ( @atypes ) {
332 0           my ( $postal ) = $org_data =~ m|(.+?)|s;
333              
334 0 0         next unless $postal;
335              
336 0           $cont{legal}{$atype}{addr} = join(' ', $postal =~ /([^<>]*)<\/contact:street>/ );
337              
338 0           ( $cont{legal}{$atype}{city} ) = $postal =~ /([^<>]*)<\/contact:city>/;
339              
340 0           ( $cont{legal}{$atype}{'state'} ) = $postal =~ /([^<>]*)<\/contact:sp>/;
341              
342 0           ( $cont{legal}{$atype}{postcode} ) = $postal =~ /([^<>]*)<\/contact:pc>/;
343              
344 0           ( $cont{legal}{$atype}{country_code} ) = $postal =~ /([A-Z]+)<\/contact:cc>/;
345             }
346             }
347             }
348              
349 0           return \%cont;
350             }
351              
352             =head2 create_domain
353              
354             Domains ru.net+ tlds have only the registrant, without the administrator and other contacts
355              
356             =cut
357              
358             sub create_domain {
359 0     0 1   my ( $self, $params ) = @_;
360              
361 0   0       $params->{authinfo} ||= IO::EPP::Base::gen_pw( 16 );
362              
363 0           my $extension = '';
364              
365 0 0         if ( $params->{dname} =~ /\.xn--80adxhks$/ ) {
366             # .москва support RU lang only
367 0           $extension .= qq| \n|;
368 0           $extension .= " ru-RU\n";
369 0           $extension .= " \n";
370             }
371              
372 0 0 0       if ( $params->{price} or $params->{fee} ) {
373 0   0       my $price = $params->{price} || $params->{fee};
374             # Russian Ruble only
375 0           $extension .= qq| \n|;
376 0           $extension .= " RUB\n";
377 0           $extension .= " $price\n";
378 0           $extension .= " \n";
379             }
380              
381 0 0         $params->{extension} = $extension if $extension;
382              
383 0           return $self->SUPER::create_domain( $params );
384             }
385              
386              
387             sub get_domain_spec_ext {
388 0     0 0   my ( undef, $ext ) = @_;
389              
390 0           my %info;
391              
392 0 0         if ( $ext =~ /(.+?)<\/idn:data>/s ) {
393 0           my $idn = $1;
394              
395 0           ( $info{uname} ) = $idn =~ /([^<>]+)<\/idn:uname>/;
396             }
397              
398 0           return \%info;
399             }
400              
401              
402             sub renew_domain {
403 0     0 1   my ( $self, $params ) = @_;
404              
405 0           my $extension = '';
406              
407 0 0 0       if ( $params->{price} or $params->{fee} ) {
408 0   0       my $price = $params->{price} || $params->{fee};
409             # Russian Ruble only
410 0           $extension .= qq| \n|;
411 0           $extension .= " RUB\n";
412 0           $extension .= " $price\n";
413 0           $extension .= " \n";
414             }
415              
416 0 0         $params->{extension} = $extension if $extension;
417              
418 0           return $self->SUPER::renew_domain( $params );
419             }
420              
421              
422             =head2 restore_domain
423              
424             first call for restore_domain
425              
426             =cut
427              
428             sub restore_domain {
429 0     0 1   my ( $self, $params ) = @_;
430              
431 0           $params->{extension} = qq|
432            
433             |;
434              
435 0           return $self->SUPER::update_domain( $params );
436             }
437              
438              
439             =head2 confirmations_restore_domain
440              
441             Second call for restore_domain
442              
443             =over 4
444              
445             =item C
446              
447             whois before delete;
448              
449             =item C
450              
451             whois on now;
452              
453             =item C
454              
455             delete domain date-time, see. upd_date in domain:info before call restore_domain;
456              
457             =item C
458              
459             restore request call datetime in UTC;
460              
461             =item C
462              
463             restore reason,
464              
465             variants: C, C, C;
466              
467             =item C
468              
469             need to write what it is for the client;
470              
471             =item C
472              
473             can and without other.
474              
475             =back
476              
477             =cut
478              
479             sub confirmations_restore_domain {
480 0     0 1   my ( $self, $params ) = @_;
481              
482 0           $params->{extension} = <
483            
484            
485            
486             $$params{pre_data}
487             $$params{post_data}
488             $$params{del_time}
489             $$params{rest_time}
490             $$params{reason}
491             $$params{statement}
492            
493            
494            
495            
496             RGPEXT
497              
498 0           return $self->SUPER::update_domain( $params );
499             }
500              
501              
502             1;
503              
504              
505             __END__