File Coverage

blib/lib/IO/EPP/DrsUa.pm
Criterion Covered Total %
statement 12 120 10.0
branch 0 44 0.0
condition 0 13 0.0
subroutine 4 15 26.6
pod 6 10 60.0
total 22 202 10.8


line stmt bran cond sub pod time code
1             package IO::EPP::DrsUa;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::DrsUa
8              
9             =head1 SYNOPSIS
10              
11             use IO::EPP::DrsUa;
12              
13             # Parameters for IO::Socket::SSL
14             my %sock_params = (
15             PeerHost => 'epp.uadns.com',
16             PeerPort => 700,
17             # without certificate
18             Timeout => 30,
19             );
20              
21             # Create object, get greeting and call login()
22             my $conn = IO::EPP::DrsUa->new( {
23             user => 'login',
24             pass => 'xxxx',
25             sock_params => \%sock_params,
26             test_mode => 0, # real connect
27             } );
28              
29             # Check domain
30             my ( $answ, $code, $msg ) = $conn->check_domains( { domains => [ 'qqq.com.ua', 'aaa.biz.ua' ] } );
31              
32             # Call logout() and destroy object
33             undef $conn;
34              
35             =head1 DESCRIPTION
36              
37             Module for work with nic.ua/drs.ua domains
38              
39             Drs.ua is a registry for biz.ua, co.ua, pp.ua and reseller for other .ua tlds
40              
41             drs.ua uses deprecated epp version 0.5 --
42             drs.ua использует устаревший epp версии 0.5 -- it uses hostAttr instead of hostObj
43              
44             Features:
45              
46             =over 4
47              
48             =item *
49              
50             special PP format
51              
52             =item *
53              
54             the contact id must be suffixed on "-cunic"
55              
56             =item *
57              
58             need full name in contact:update
59              
60             =item *
61              
62             to change the email address, you need to update the contact, not change the contact id
63              
64             =item *
65              
66             additional extensions with login should be passed as objURI, not extURI
67              
68             =item *
69              
70             contacts have only type loc
71              
72             =item *
73              
74             no commands host:check, host:create, host:update (consequence of hostAttr)
75              
76             =item *
77              
78             cannot use punycode in the email to the left of @
79              
80             =item *
81              
82             in contacts for an individual, the company field must be empty
83              
84             =item *
85              
86             domains in the zone pp.ua you can not delete, you can only not confirm the sms about registration or renewal so that they themselves are deleted
87              
88             =item *
89              
90             the disclose flag only works for biz.ua, co.ua
91              
92             For pp.ua you can't hide contacts
93              
94             In other tlds Privacy Protection must be performed on the client side
95              
96             =item *
97              
98             epp poll sends only the transaction number and also the result in the form of ok or fail, without the domain name or contact id
99              
100             =back
101              
102             Documentation:
103             L,
104             L
105              
106             =cut
107              
108 1     1   2086 use IO::EPP::Base;
  1         21  
  1         32  
109 1     1   5 use parent qw( IO::EPP::Base );
  1         2  
  1         5  
110              
111 1     1   52 use strict;
  1         1  
  1         15  
112 1     1   4 use warnings;
  1         1  
  1         1280  
113              
114              
115             sub make_request {
116 0     0 1   my ( $action, $params ) = @_;
117              
118 0           my ( $self, $code, $msg, $answ );
119              
120 0 0         unless ( $params->{conn} ) {
121 0   0       $params->{sock_params}{PeerHost} ||= 'epp.uadns.com';
122 0   0       $params->{sock_params}{PeerPort} ||= 700;
123              
124 0           ( $self, $code, $msg ) = __PACKAGE__->new( $params );
125              
126 0 0 0       unless ( $code and $code == 1000 ) {
127 0           goto END_MR;
128             }
129             }
130             else {
131 0           $self = $params->{conn};
132             }
133              
134              
135 0           $self->{critical_error} = '';
136              
137 0 0         if ( $self->can( $action ) ) {
138 0           ( $answ, $code, $msg ) = $self->$action( $params );
139             }
140             else {
141 0           $msg = "undefined command <$action>, request cancelled";
142 0           $code = 0;
143             }
144              
145              
146             END_MR:
147              
148 0 0         $msg .= '; ' . $self->{critical_error} if $self->{critical_error};
149              
150 0           my $full_answ = "code: $code\nmsg: $msg";
151              
152 0 0 0       $answ = {} unless $answ && ref $answ;
153              
154 0           $answ->{code} = $code;
155 0           $answ->{msg} = $msg;
156              
157 0 0         return wantarray ? ( $answ, $full_answ, $self ) : $answ;
158             }
159              
160             =head1 METHODS
161              
162             Further overlap functions where the provider has features
163              
164             =cut
165              
166             sub login {
167 0     0 1   my ( $self, $pw ) = @_;
168              
169             # wihout urn:ietf:params:xml:ns:host
170 0           my $svcs = '
171             urn:ietf:params:xml:ns:contact-1.0
172             urn:ietf:params:xml:ns:domain-1.0';
173              
174 0           my $extension = '
175             http://drs.ua/epp/drs-1.0'; # objURI !!! not extURI !!!
176              
177 0           return $self->SUPER::login( $pw, $svcs, $extension );
178             }
179              
180              
181             sub _prepare_contact {
182 0     0     my ( $params ) = @_;
183              
184             # int only: code: 2400, msg: Only 'loc' type of postal info is supported
185             # int + loc: code: 2400, msg: Multiple postal info not supported
186 0 0         unless ( $$params{'loc'} ) {
187 0           foreach my $f ( 'name','first_name','last_name','company','addr','city','state','postcode','country_code' ) {
188 0 0         $$params{'loc'}{$f} = delete $$params{$f} if defined $$params{$f};
189             }
190             }
191             }
192              
193             =head1 create_contact
194              
195             It has many features, see the description of the module above
196              
197             =cut
198              
199             sub create_contact {
200 0     0 1   my ( $self, $params ) = @_;
201              
202 0           _prepare_contact( $params );
203              
204 0 0         my $visible = $$params{pp_flag} ? 0 : 1;
205              
206             # This format is feature drs, but for biz.ua, co.ua only
207 0           $params->{pp_ext} = '
208            
209            
210            
211            
212            
213            
214            
215             ';
216              
217 0           return $self->SUPER::create_contact( $params );
218             }
219              
220             =head1 update_contact
221              
222             It has many features, see the description of the module above
223              
224             =cut
225              
226             sub update_contact {
227 0     0 1   my ( $self, $params ) = @_;
228              
229 0           _prepare_contact( $params );
230              
231 0           $params->{chg}{need_name} = 1;
232              
233 0 0         my $visible = $$params{pp_flag} ? 0 : 1;
234              
235 0           $params->{pp_ext} = '
236            
237            
238            
239            
240            
241            
242            
243             ';
244              
245 0           return $self->SUPER::update_contact( $params );
246             }
247              
248              
249             sub create_domain_nss {
250 0     0 0   my ( $self, $params ) = @_;
251              
252 0           my $nss = '';
253              
254             # Old EPP version, sbut it was resolved in https://tools.ietf.org/html/rfc3731
255 0           foreach my $ns ( @{$params->{nss}} ) {
  0            
256 0           $nss .= " \n $ns\n \n";
257             }
258              
259 0 0         $nss = "\n \n$nss " if $nss;
260              
261 0           return $nss;
262             }
263              
264              
265             sub create_domain {
266 0     0 1   my ( $self, $params ) = @_;
267              
268 0   0       $params->{authinfo} ||= IO::EPP::Base::gen_pw( 16 );
269              
270 0           return $self->SUPER::create_domain( $params );
271             }
272              
273              
274             sub update_domain_add_nss {
275 0     0 0   my ( $self, $params ) = @_;
276              
277 0           my $add = " \n";
278              
279             # Old EPP version, see in https://tools.ietf.org/html/rfc3731
280 0           foreach my $ns ( @{$$params{add}{nss}} ) {
  0            
281 0           $add .= " \n $$ns{ns}\n";
282 0 0         if ( $ns->{ips} ) {
283 0           foreach my $ip ( @{$ns->{ips}} ) {
  0            
284 0 0         if ( $ip =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
285 0           $add .= " $ip\n";
286             }
287             else {
288 0           $add .= " $ip\n";
289             }
290             }
291             }
292              
293 0           $add .= " \n";
294             }
295              
296 0           $add .= " \n";
297              
298 0           return $add;
299             }
300              
301              
302             sub update_domain_rem_nss {
303 0     0 0   my ( $self, $params ) = @_;
304              
305 0           my $rem = " \n";
306              
307             # Old EPP version, see in https://tools.ietf.org/html/rfc3731
308 0           foreach my $ns ( @{$$params{rem}{nss}} ) {
  0            
309 0           $rem .= " \n $$ns{ns}\n";
310              
311 0 0         if ( $ns->{ips} ) {
312 0           foreach my $ip ( @{$ns->{ips}} ) {
  0            
313 0 0         if ( $ip =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
314 0           $rem .= " $ip\n";
315             }
316             else {
317 0           $rem .= " $ip\n";
318             }
319             }
320             }
321              
322 0           $rem .= " \n";
323             }
324              
325 0           $rem .= " \n";
326              
327 0           return $rem;
328             }
329              
330              
331             sub update_domain {
332 0     0 1   my ( $self, $params ) = @_;
333              
334 0           $params->{nss_as_attr} = 1;
335              
336 0           return $self->SUPER::update_domain( $params );
337             }
338              
339             =head1 req_poll
340              
341             It has many features, see the description of the module above
342              
343             =cut
344              
345             sub req_poll_rdata {
346 0     0 0   my ( $self, $rdata, undef ) = @_;
347              
348 0           my %info;
349              
350 0 0         if ( $rdata =~ /^
    0          
    0          
351             # TRANSFER_PENDING, TRANSFER_CLIENT_APPROVED, TRANSFER_SERVER_APPROVED
352 0           $info{transfer} = {};
353 0           ( $info{transfer}{dname} ) = $rdata =~ /([^<>]+)<\/domain:name>/;
354 0           ( $info{transfer}{status} ) = $rdata =~ /([^<>]+)<\/domain:trStatus>/;
355              
356 0           my %id = %IO::EPP::Base::id;
357 0           foreach my $k ( keys %id ) {
358 0 0         if ( $rdata =~ /([^<>]+)<\/domain:$k>/ ) {
359 0           $info{transfer}{$id{$k}} = $1;
360             }
361             }
362             #( $info{transfer}{from} ) = $rdata =~ /([^<>]+)<\/domain:acID>/;
363             #( $info{transfer}{to} ) = $rdata =~ /([^<>]+)<\/domain:reID>/;
364 0           my %dt = %IO::EPP::Base::dt;
365 0           foreach my $k ( keys %dt ) {
366 0 0         if ( $rdata =~ /([^<>]+)<\/domain:$k>/ ) {
367 0           $info{transfer}{$dt{$k}} = IO::EPP::Base::cldate( $1 );
368             }
369             }
370             }
371             elsif ( $rdata =~ /^
372             # Pending action completed with error.
373             # Pending action completed successfully.
374 0           $info{upd_del} = {};
375 0           ( $info{upd_del}{result}, $info{upd_del}{dname} ) = $rdata =~ /([^<>]+)<\/domain:name>/;
376              
377 0 0         if ( $rdata =~ /(.+)<\/domain:paTRID>/ ) {
378 0           my $trids = $1;
379 0           ( $info{upd_del}{cltrid} ) = $trids =~ /([^<>]+)<\/clTRID>/;
380 0           ( $info{upd_del}{svtrid} ) = $trids =~ /([^<>]+)<\/svTRID>/;
381             }
382              
383 0 0         if ( $rdata =~ /([^<>]+)<\/domain:paDate>/ ) {
384 0           $info{upd_del}{date} = IO::EPP::Base::cldate( $1 );
385             }
386             }
387             elsif ( $rdata =~ /^
388             # drs feature
389 0           $info{notify} = {};
390 0           ( $info{notify}{type} ) = $rdata =~ /([^<>]+)<\/drs:type>/; # command
391 0           ( $info{notify}{object} ) = $rdata =~ /([^<>]+)<\/drs:object>/; # domain
392 0           ( $info{notify}{message} ) = $rdata =~ /([^<>]+)<\/drs:message>/; #
393             }
394             else {
395 0           return ( 0, 'New DrsUa message type!' );
396             }
397              
398 0           return ( \%info, '' );
399             }
400              
401             1;
402              
403              
404             __END__