File Coverage

blib/lib/IO/EPP/TCI.pm
Criterion Covered Total %
statement 12 104 11.5
branch 0 42 0.0
condition 0 16 0.0
subroutine 4 11 36.3
pod 6 7 85.7
total 22 180 12.2


line stmt bran cond sub pod time code
1             package IO::EPP::TCI;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::TCI
8              
9             =head1 SYNOPSIS
10              
11             use IO::EPP::TCI;
12              
13             # Parameters for IO::Socket::SSL
14             my %sock_params = (
15             PeerHost => 'uap.tcinet.ru',
16             PeerPort => 8130, # .дети 8130, .tatar 8131
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::TCI->new( {
24             user => 'XXX-DETI',
25             pass => 'XXXXXXXX',
26             sock_params => \%sock_params,
27             server => 'afilias', # or pir, ...
28             test_mode => 0, # real connect
29             } );
30              
31             # Check domain
32             my ( $answ, $code, $msg ) = $conn->check_domains( { domains => [ 'xn--80akfym3e.xn--d1acj3b' ] } );
33              
34             # Call logout() and destroy object
35             undef $conn;
36              
37             =head1 DESCRIPTION
38              
39             Work with normal TCI EPP API
40              
41             .дети/.xn--d1acj3b documents:
42             L, L
43              
44             .tatar documents:
45             L, L
46              
47             =cut
48              
49 1     1   1958 use IO::EPP::Base;
  1         3  
  1         35  
50 1     1   7 use parent qw( IO::EPP::Base );
  1         2  
  1         7  
51              
52 1     1   58 use strict;
  1         1  
  1         17  
53 1     1   4 use warnings;
  1         1  
  1         1169  
54              
55             my $cont_ext =
56             'xmlns:contact="http://www.tcinet.ru/epp/tci-contact-ext-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tcinet.ru/epp/tci-contact-ext-1.0 tci-contact-ext-1.0.xsd"';
57              
58             sub make_request {
59 0     0 1   my ( $action, $params ) = @_;
60              
61 0           my ( $self, $code, $msg, $answ );
62              
63 0 0         unless ( $params->{conn} ) {
64 0   0       $params->{sock_params}{PeerHost} ||= 'uap.tcinet.ru';
65 0   0       $params->{sock_params}{PeerPort} ||= 8130; # .дети, for .tatar need 8131
66              
67 0           ( $self, $code, $msg ) = __PACKAGE__->new( $params );
68              
69 0 0 0       unless ( $code and $code == 1000 ) {
70 0           goto END_MR;
71             }
72             }
73             else {
74 0           $self = $params->{conn};
75             }
76              
77              
78 0           $self->{critical_error} = '';
79              
80 0 0         if ( $self->can( $action ) ) {
81 0           ( $answ, $code, $msg ) = $self->$action( $params );
82             }
83             else {
84 0           $msg = "undefined command <$action>, request cancelled";
85 0           $code = 0;
86             }
87              
88              
89             END_MR:
90              
91 0 0         $msg .= '; ' . $self->{critical_error} if $self->{critical_error};
92              
93 0           my $full_answ = "code: $code\nmsg: $msg";
94              
95 0 0 0       $answ = {} unless $answ && ref $answ;
96              
97 0           $answ->{code} = $code;
98 0           $answ->{msg} = $msg;
99              
100 0 0         return wantarray ? ( $answ, $full_answ, $self ) : $answ;
101             }
102              
103             =head1 METHODS
104              
105             Further overlap functions where the provider has features
106              
107             =head2 login
108              
109             Ext params for login,
110              
111             INPUT: new password for change
112              
113             =cut
114              
115             sub login {
116 0     0 1   my ( $self, $pw ) = @_;
117              
118 0           my $svcs = '
119             urn:ietf:params:xml:ns:epp-1.0
120             urn:ietf:params:xml:ns:eppcom-1.0
121             urn:ietf:params:xml:ns:contact-1.0
122             urn:ietf:params:xml:ns:domain-1.0
123             urn:ietf:params:xml:ns:host-1.0';
124 0           my $extension = '
125             http://www.tcinet.ru/epp/tci-contact-ext-1.0
126             http://www.tcinet.ru/epp/tci-domain-ext-1.0
127             urn:ietf:params:xml:ns:launch-1.0
128             urn:ietf:params:xml:ns:secDNS-1.1
129             urn:ietf:params:xml:ns:rgp-1.0
130             http://www.tcinet.ru/epp/tci-billing-1.0';
131              
132 0           return $self->SUPER::login( $pw, $svcs, $extension );
133             }
134              
135              
136             sub contact_ext {
137 0     0 0   my ( undef, $params ) = @_;
138              
139 0           my $ext = '';
140              
141 0 0         if ( $params->{birthday} ) {
142 0           $ext .= " \n";
143              
144 0           foreach my $f ( 'birthday', 'passport', 'TIN' ) {
145 0 0         $ext .= " $$params{$f}\n" if $$params{$f};
146             }
147              
148 0           $ext .= " ";
149             }
150              
151 0 0         if ( $params->{legal} ) {
152 0           $ext .= " \n";
153 0           foreach my $type ( 'int', 'loc' ) {
154 0           $ext .= qq| \n|;
155              
156 0 0         $$params{legal}{$type}{addr} = [ $$params{legal}{$type}{addr} ] unless ref $$params{legal}{$type}{addr};
157              
158 0           foreach my $s ( @{$$params{legal}{$type}{addr}} ) {
  0            
159 0           $ext .= " $s\n";
160             }
161              
162 0           $ext .= " $$params{legal}{$type}{city}\n";
163 0 0         $ext .= ( $$params{legal}{$type}{'state'} ? " $$params{legal}{$type}{state}\n" : " \n" );
164 0 0         $ext .= ( $$params{legal}{$type}{postcode} ? " $$params{legal}{$type}{postcode}\n" : " \n" );
165 0           $ext .= " $$params{legal}{$type}{country_code}\n";
166              
167 0           $ext .= " \n";
168             }
169 0           $ext .= " $$params{TIN}\n";
170 0           $ext .= " ";
171             }
172              
173 0           return $ext;
174             }
175              
176              
177             =head2 create_contact
178              
179             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,
180             then loc type data must be entered in Cyrillic.
181             This is mandatory for citizens and legal entities of Russia, Ukraine, Belarus and other countries that have the Cyrillic alphabet.
182              
183             In addition, the owner must provide additional information.
184              
185             For individuals:
186              
187             C -- date of birth;
188              
189             C -- passport series and number, by whom and when it was issued;
190              
191             C -- TIN for individual entrepreneurs.
192              
193             For legal entities:
194              
195             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.
196              
197             You also need to specify the C field.
198              
199             An Example:
200              
201             Individuals:
202              
203             my %cont = (
204             int => {
205             first_name => 'Igor',
206             patronymic => 'Igorevich',
207             last_name => 'Igorev',
208             org => '',
209             addr => 'Igoreva str, 129',
210             city => 'Igorevsk',
211             state => 'Ogorevskaya obl.',
212             postcode => '699001',
213             country_code => 'RU',
214             },
215             loc => {
216             first_name => 'Игорь',
217             patronymic => 'Игоревич',
218             last_name => 'Игорев',
219             org => '',
220             addr => 'ул. Игорева, 129',
221             city => 'Игоревск',
222             state => 'Игоревская обл.',
223             postcode => '699001',
224             country_code => 'RU',
225             },
226             birthday => '1909-01-14',
227             passport => '11.11.2011, выдан Отделом УФМС России по Игоревской области в г.Игоревске, 2211 446622',
228             phone => '+7.9012345678',
229             fax => '',
230             email => 'igor@i.ru',
231             TIN => '',
232             };
233              
234             my ( $answ, $msg, $conn ) = make_request( 'create_contact', \%cont );
235              
236             Legal entities:
237              
238             my %cont = (
239             int => {
240             first_name => 'Igor',
241             patronymic => 'Igorevich',
242             last_name => 'Igorev',
243             org => 'Igor and Co',
244             addr => 'Igoreva str, 129',
245             city => 'Igorevsk',
246             state => 'Igorevskaya obl.',
247             postcode => '699001',
248             country_code => 'RU',
249             },
250             loc => {
251             first_name => 'Игорь',
252             patronymic => 'Игоревич',
253             last_name => 'Игорев',
254             org => 'Игорь и Ко',
255             addr => 'ул. Игорева, 129',
256             city => 'Игоревск',
257             state => 'Игоревская обл.',
258             postcode => '699001',
259             country_code => 'RU',
260             },
261             legal => {
262             int => {
263             addr => 'Company str, 1',
264             city => 'Igorevsk',
265             state => 'Igorevskaya obl.',
266             postcode => '699002',
267             country_code => 'RU',
268             },
269             loc => {
270             addr => 'ул. Компаний, 1',
271             city => 'Игоревск',
272             state => 'Игоревская обл.',
273             postcode => '699002',
274             country_code => 'RU',
275             }
276             }
277             };
278              
279             my ( $answ, $code, $msg ) = $conn->create_contact( \%cont );
280              
281             =cut
282              
283             sub create_contact {
284 0     0 1   my ( $self, $params ) = @_;
285              
286 0   0       $params->{cont_id} ||= IO::EPP::Base::gen_id( 16 );
287              
288 0           $params->{authinfo} = IO::EPP::Base::gen_pw( 16 );
289              
290 0           my $extension = $self->contact_ext( $params );
291              
292 0 0         if ( $extension ) {
293 0           $params->{extension} = " \n$extension \n";
294             }
295              
296 0           return $self->SUPER::create_contact( $params );
297             }
298              
299              
300             sub get_contact_ext {
301 0     0 1   my ( undef, $ext ) = @_;
302              
303 0           my %cont;
304              
305 0 0         if ( $ext =~ m|]+tci-contact-ext-1[^<>]+>(.+?)|s ) {
306 0           my $data = $1;
307              
308 0 0         if ( $data =~ m|(.+)|s ) {
309 0           my $person_data = $1;
310              
311 0           my @rows = $person_data =~ m|([^<>]+)|gs;
312              
313 0           foreach my $row ( @rows ) {
314 0 0         if ( $row =~ m|([^<>]+)| ) {
315 0           $cont{$1} = $2;
316             }
317             }
318             }
319              
320 0 0         if ( $data =~ m|(.+)|s ) {
321 0           my $org_data = $1;
322              
323 0           ( $cont{TIN} ) = $org_data =~ /([^<>]+)<\/contact:TIN>/;
324              
325 0           my @atypes = ( 'int', 'loc' );
326 0           foreach my $atype ( @atypes ) {
327 0           my ( $postal ) = $org_data =~ m|(.+?)|s;
328              
329 0 0         next unless $postal;
330              
331 0           $cont{legal}{$atype}{addr} = join(' ', $postal =~ /([^<>]*)<\/contact:street>/ );
332              
333 0           ( $cont{legal}{$atype}{city} ) = $postal =~ /([^<>]*)<\/contact:city>/;
334              
335 0           ( $cont{legal}{$atype}{'state'} ) = $postal =~ /([^<>]*)<\/contact:sp>/;
336              
337 0           ( $cont{legal}{$atype}{postcode} ) = $postal =~ /([^<>]*)<\/contact:pc>/;
338              
339 0           ( $cont{legal}{$atype}{country_code} ) = $postal =~ /([A-Z]+)<\/contact:cc>/;
340             }
341             }
342             }
343              
344 0           return \%cont;
345             }
346              
347              
348             =head2 create_domain
349              
350             Has an optional C field.
351              
352             For .дети tld automatically adds the idn extension with lang C.
353              
354             =cut
355              
356             sub create_domain {
357 0     0 1   my ( $self, $params ) = @_;
358              
359 0   0       $params->{authinfo} ||= IO::EPP::Base::gen_pw( 16 );
360              
361 0           my $extension = '';
362              
363 0 0         if ( $params->{dname} =~ /\.xn--80adxhks$/ ) {
364             # .москва support RU lang only
365 0           $extension .= qq| \n|;
366 0           $extension .= " ru-RU\n";
367 0           $extension .= " \n";
368             }
369              
370 0 0         $params->{extension} = $extension if $extension;
371              
372 0           return $self->SUPER::create_domain( $params );
373             }
374              
375             =head2 get_domain_spec_ext
376              
377             Processes the additional description field.
378              
379             =cut
380              
381             sub get_domain_spec_ext {
382 0     0 1   my ( undef, $ext ) = @_;
383              
384 0           my %info;
385              
386 0 0         if ( $ext =~ m|]+tci-domain-ext-1[^<>]+>(.+?)|s ) {
387 0           my $tciinfo = $1;
388              
389 0           ( $info{descr} ) = $tciinfo =~ m|([^<>]+)|;
390             }
391              
392 0           return \%info;
393             }
394              
395              
396             1;
397              
398             __END__