File Coverage

blib/lib/IO/EPP/Test/Base.pm
Criterion Covered Total %
statement 893 1089 82.0
branch 445 664 67.0
condition 70 112 62.5
subroutine 32 33 96.9
pod 0 23 0.0
total 1440 1921 74.9


line stmt bran cond sub pod time code
1             package IO::EPP::Test::Base;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::Test::Base
8              
9             =head1 SYNOPSIS
10              
11             Call IO::EPP::Base with parameter "test_mode=1"
12              
13             =head1 DESCRIPTION
14              
15             Module for testing IO::EPP::CNic,
16             emulates answers of base registry
17              
18             =head1 AUTHORS
19              
20             Vadim Likhota
21              
22             =cut
23              
24 2     2   14 use Digest::MD5 qw(md5_hex);
  2         5  
  2         120  
25              
26 2     2   13 use IO::EPP::Base ();
  2         2  
  2         36  
27 2     2   439 use IO::EPP::Test::Server;
  2         4  
  2         50  
28              
29 2     2   11 use strict;
  2         4  
  2         40  
30 2     2   8 use warnings;
  2         5  
  2         67  
31              
32 2     2   12 no utf8; # !!!
  2         2  
  2         12  
33              
34             our %statuses = (
35             clientHold => '+',
36             clientRenewProhibited => 'renewed',
37             clientDeleteProhibited => 'deleted',
38             clientUpdateProhibited => 'updated',
39             clientTransferProhibited => 'transfered',
40             serverHold => '+',
41             serverRenewProhibited => 'renewed',
42             serverDeleteProhibited => 'deleted',
43             serverUpdateProhibited => 'updated',
44             serverTransferProhibited => 'transfered',
45             );
46              
47             sub req {
48 238     238 0 493 my ( $obj, $out_data, undef ) = @_;
49              
50 238         318 my $in_data;
51              
52 238 100 100     3460 if ( !$out_data or $out_data =~ m|]+/>| ) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
53 49         102 $in_data = hello( $out_data );
54             }
55             elsif ( $out_data =~ m||s ) {
56 49         108 $in_data = login( $out_data );
57             }
58             elsif ( $out_data =~ m|]+>| ) {
59 1         5 $in_data = contact_check( $obj, $out_data );
60             }
61             elsif ( $out_data =~ m|]+>| ) {
62 11         31 $in_data = contact_create_update( $obj, $out_data, 'create' );
63             }
64             elsif ( $out_data =~ m|]+>| ) {
65 2         6 $in_data = contact_create_update( $obj, $out_data, 'update' );
66             }
67             elsif ( $out_data =~ m|]+>| ) {
68 4         13 $in_data = contact_info( $obj, $out_data );
69             }
70             elsif ( $out_data =~ m|]+>| ) {
71 2         8 $in_data = contact_delete( $obj, $out_data );
72             }
73             elsif ( $out_data =~ m|]+>| ) {
74 1         5 $in_data = host_check( $obj, $out_data );
75             }
76             elsif ( $out_data =~ m|]+>| ) {
77 8         23 $in_data = host_create( $obj, $out_data );
78             }
79             elsif ( $out_data =~ m|]+>| ) {
80 2         6 $in_data = host_info( $obj, $out_data );
81             }
82             elsif ( $out_data =~ m|]+>| ) {
83 3         9 $in_data = host_update( $obj, $out_data );
84             }
85             elsif ( $out_data =~ m|]+>| ) {
86 2         8 $in_data = host_delete( $obj, $out_data );
87             }
88             elsif ( $out_data =~ m|]+>| ) {
89 2         7 $in_data = domain_check( $obj, $out_data );
90             }
91             elsif ( $out_data =~ m|]+>| ) {
92 12         35 $in_data = domain_create( $obj, $out_data );
93             }
94             elsif ( $out_data =~ m|]+>| ) {
95 4         14 $in_data = domain_info( $obj, $out_data );
96             }
97             elsif ( $out_data =~ m|]+>| ) {
98 5         14 $in_data = domain_renew( $obj, $out_data );
99             }
100             elsif ( $out_data =~ m|]+>| ) {
101 20         53 $in_data = domain_update( $obj, $out_data );
102             }
103             elsif ( $out_data =~ m|]+>| ) {
104 4         14 $in_data = domain_delete( $obj, $out_data );
105             }
106             elsif ( $out_data =~ m|]+>| ) {
107 7         17 $in_data = domain_transfer( $obj, $out_data );
108             }
109             elsif ( $out_data =~ m|]+>| ) {
110 1         5 $in_data = poll( $obj, $out_data );
111             }
112             elsif ( $out_data =~ m|| ) {
113 49         137 $in_data = logout( $out_data );
114             }
115             else {
116 0         0 die "closed connection\n"; # behavior centralnic
117             }
118              
119 238         676 return $in_data;
120             }
121              
122              
123             sub get_svtrid {
124 263     263 0 2519 return 'TEST-' . uc( md5_hex( time() . $$ . rand(1000000) ) ); # as CNIC-7E024512B06F1FC202C6E625DE12C69984799AA81D578111813DFF29646
125             }
126              
127              
128             sub get_dates {
129 66     66 0 112 my ( $y ) = @_;
130 66   100     264 $y ||= 0;
131 66         1766 my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
132              
133 66         235 $year += 1900;
134 66         101 $mon += 1;
135 66         104 my $year2 = $year + $y;
136              
137 66         353 my $dt1 = sprintf( '%0004d-%02d-%02dT%02d:%02d:%02d.0Z', $year, $mon, $mday, $hour, $min, $sec );
138 66         174 my $dt2 = sprintf( '%0004d-%02d-%02dT23:59:59.0Z', $year2, $mon, $mday );
139              
140 66         198 return $dt1, $dt2;
141             }
142              
143              
144             sub hello {
145 49     49 0 103 my ( $dt ) = get_dates();
146              
147 49         223 return qq|EXAMPLE EPP server EPP.EXAMPLE.COM$dt1.0enurn:ietf:params:xml:ns:domain-1.0urn:ietf:params:xml:ns:contact-1.0urn:ietf:params:xml:ns:host-1.0urn:ietf:params:xml:ns:rgp-1.0urn:ietf:params:xml:ns:secDNS-1.1urn:ietf:params:xml:ns:idn-1.0|;
148             }
149              
150             sub _fail_cltrid {
151 0     0   0 my $svtrid = get_svtrid();
152              
153 0         0 return qq|
154            
155            
156            
157             XML schema validation failed: Element '{urn:ietf:params:xml:ns:epp-1.0}clTRID': The value has a length of '0';
158            
159            
160             xxxx
161             $svtrid
162            
163            
164             |;
165             }
166              
167             sub _fail_body {
168 63     63   152 my ( $err, $code, $cl ) = @_;
169 63         123 my $svtrid = get_svtrid();
170 63   50     175 $cl ||= 'xxxx';
171              
172 63         372 return qq|
173            
174            
175            
176             $err
177            
178            
179             $cl
180             $svtrid
181            
182            
183             |;
184             }
185              
186             sub _ok_answ {
187 20     20   66 my ( $res, $cl ) = @_;
188              
189 20         40 my $svtrid = get_svtrid();
190              
191 20   50     60 $cl ||= 'xxxx';
192              
193 20         156 return qq|Command completed successfully.$res$cl$svtrid|;
194             }
195              
196             sub _min_answ {
197 63     63   124 my ( $code, $cl ) = @_;
198              
199 63         105 my $svtrid = get_svtrid();
200              
201 63   50     156 $cl ||= 'xxxx';
202              
203 63         275 return qq|Command completed successfully.$cl$svtrid|;
204             }
205              
206             sub login {
207 49     49 0 85 my ( $body ) = @_;
208              
209 49         341 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|;
210              
211 49 50       143 return _fail_cltrid() unless $cltrid;
212              
213 49 50       294 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
214 0         0 _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
215             }
216              
217 49 50       331 unless ( $body =~ s|^\s+||s ) {
218 0         0 _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
219             }
220              
221 49         87 my $body2;
222 49 50       389 if ( $body =~ m|\s*\s*(.+?)\s+[^<>]+\s+\s+|s ) {
223 49         158 $body2 = $1;
224             }
225             else {
226 0         0 die "closed connection\n"; # behavior centralnic
227             }
228              
229 49         184 my ( $login ) = $body =~ m|([0-9A-Za-z_\-]+)|;
230              
231 49         115 my $svtrid = get_svtrid();
232              
233 49 50       131 return qq|
234            
235            
236            
237             Cannot authenticate $login: not found in database.
238            
239            
240             $cltrid
241             $svtrid
242            
243            
244             |
245             unless $login;
246              
247 49         210 my ( $pass ) = $body =~ m|([0-9A-Za-z!\@\$\%*_.:=+?#,"'\-{}\[\]\(\)]+)|;
248              
249 49 50 33     219 if ( !$pass || length( $pass ) < 6 ) {
250 0         0 return qq|
251            
252            
253            
254             XML schema validation failed: Element '{urn:ietf:params:xml:ns:epp-1.0}pw': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '6'.
255            
256            
257             $cltrid
258             $svtrid
259            
260            
261             |;
262             }
263              
264 49 50       114 if ( $pass eq 'fail-pass' ) {
265 0         0 return qq|
266            
267            
268            
269             Invalid password
270            
271            
272             $cltrid
273             $svtrid
274            
275            
276             |;
277             }
278              
279 49         161 return qq|Welcome user.$cltrid$svtrid|;
280             }
281              
282              
283             sub contact_check {
284 1     1 0 2 my ( $obj, $body ) = @_;
285              
286 1         8 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
287              
288 1 50       4 return _fail_cltrid() unless $cltrid;
289              
290 1 50       7 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
291 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
292             }
293              
294 1 50       8 unless ( $body =~ s|^\s+||s ) {
295 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
296             }
297              
298 1 50       8 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
299 0         0 return _fail_body( 'XML schema validation failed: contact:check', '2001', $cltrid );
300             }
301              
302 1 50       9 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
303 0         0 return _fail_body( 'XML schema validation failed: /contact:check', '2001', $cltrid );
304             }
305              
306 1         8 my ( @contacts ) = $body =~ m|([^<>]+)|g;
307              
308 1 50       4 unless ( scalar @contacts ) {
309 0         0 return _fail_body( 'XML schema validation failed: contact:cd' );
310             }
311              
312 1         2 my $srv_url = $obj->{sock};
313 1         7 my $s = new IO::EPP::Test::Server( $srv_url );
314 1         3 my $answ_list = '';
315 1         3 foreach my $row ( @contacts ) {
316 2         10 my ( $cont_id ) = $row =~ m|([^<>]+)|;
317              
318 2         4 my $reason = '';
319 2 50       7 if ( $s->data->{conts}{$cont_id} ) {
320 0         0 $reason = $s->data->{conts}{$cont_id}{reason};
321             }
322              
323 2 50       6 my $avail = $reason ? 0 : 1;
324              
325 2 50       5 $reason = "$reason" if $reason;
326              
327 2         10 $answ_list .= qq|$cont_id$reason|;
328             }
329              
330 1         3 my $svtrid = get_svtrid();
331              
332 1         9 return qq|
333            
334            
335            
336             Command completed successfully.
337            
338             $answ_list
339             $cltrid$svtrid
340            
341            
342             |;
343             }
344              
345              
346             sub contact_create_update {
347 13     13 0 25 my ( $obj, $body, $act ) = @_;
348              
349 13         90 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
350              
351 13 50       34 return _fail_cltrid() unless $cltrid;
352              
353 13 50       98 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
354 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
355             }
356              
357 13 50       84 unless ( $body =~ s|^\s+||s ) {
358 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
359             }
360              
361 13 50       175 unless ( $body =~ s|^\s+<$act>\s+]+>\s+||s ) {
362 0         0 return _fail_body( "XML schema validation failed: contact:$act", '2001', $cltrid );
363             }
364              
365 13 50       287 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
366 0         0 return _fail_body( "XML schema validation failed: /contact:$act", '2001', $cltrid );
367             }
368              
369 13         97 my $i = () = $body =~ //g;
370              
371 13 50       36 if ( $i > 1 ) {
372             # text from verisign NameStore server
373 0         0 _fail_body( 'Parameter value policy error, Only one int postal address information allowed', '2306', $cltrid );
374             }
375              
376 13         36 my $l = () = $body =~ //g;
377              
378 13 50       37 if ( $l > 1 ) {
379 0         0 _fail_body( 'Parameter value policy error, Only one loc postal address information allowed', '2306', $cltrid );
380             }
381              
382 13 50       29 if ( $i+$l == 0 ) {
383 13         28 _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}voice': This element is not expected. Expected is ( {urn:ietf:params:xml:ns:contact-1.0}postalInfo ).', '2001', $cltrid );
384             }
385              
386 13         23 my %cont;
387 13 50       64 if ( $body =~ m|([^<>]+)| ) {
388 13         57 $cont{id} = $1;
389             }
390             else {
391 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}$act': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:contact-1.0}id, {urn:ietf:params:xml:ns:contact-1.0}ext ).", '2001', $cltrid );
392             }
393              
394 13         30 my $srv_url = $obj->{sock};
395 13         48 my $s = new IO::EPP::Test::Server( $srv_url );
396              
397 13         23 my $top;
398 13 100       33 if ( $act eq 'create' ) {
    50          
399 11 100       29 if ( $s->data->{conts}{$cont{id}} ) {
400 1 50       5 if ( $s->data->{conts}{$cont{id}}{reason} eq 'in use' ) {
401 1         7 return _fail_body( "Contact object '$cont{id}' already exists.", '2302', $cltrid );
402             }
403             else {
404 0         0 return _fail_body( "Contact object '$cont{id}' $s->data->{conts}{$cont{id}}{reason}.", '2302', $cltrid );
405             }
406             }
407              
408 10         16 $top = 'create';
409             }
410             elsif ( $act eq 'update' ) {
411 2 100 66     7 unless ( $s->data->{conts}{$cont{id}} and $s->data->{conts}{$cont{id}}{reason} eq 'in use' ) {
412             # contact does not exist, the reason does not
413 1         4 return _fail_body( 'Cannot find that object.', '2303', $cltrid );
414             }
415              
416 1         2 $top = 'chg';
417             }
418              
419 11         26 for my $t ( 'int', 'loc' ) {
420 22 100       427 if ( $body =~ m|(.+?)|s ) {
421 15         69 $cont{$t} = $1;
422             }
423             }
424              
425              
426 11         26 for my $t ( 'int', 'loc' ) {
427 22         46 my $pi = delete $cont{$t};
428 22 100       48 next unless $pi;
429              
430 15         30 $cont{$t} = {};
431 15         33 foreach my $f ( 'name', 'org', 'addr' ) {
432 45 100       628 if ( $pi =~ m|(.+?)|s ) {
    100          
433 37         144 $cont{$t}{$f} = $1;
434             }
435             elsif ( $pi =~ m|| ) {
436 7 50       28 if ( $f eq 'org' ) {
437             # $cont{$t}{$f} = undef;
438             }
439             else {
440 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}$f': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.", '2001', $cltrid );
441             }
442             }
443             else {
444 1 50 33     9 if ( $f eq 'name' && $act eq 'create' ) {
445 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}postalInfo': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:contact-1.0}$f, {urn:ietf:params:xml:ns:contact-1.0}ext ).", '2001', $cltrid );
446             }
447             }
448             }
449              
450 15         33 my $addr = delete $cont{$t}{addr};
451 15         31 $cont{$t}{addr} = {};
452              
453 15         85 my @street = $addr =~ m|([^<>]+)|g;
454 15 50       39 unless ( scalar @street ) {
455 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}addr': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:contact-1.0}street, {urn:ietf:params:xml:ns:contact-1.0}ext ).", '2001', $cltrid );
456             }
457 15         36 $cont{$t}{addr}{street} = [];
458 15         32 foreach my $row ( @street ) {
459 19 50       79 if ( $row =~ m|([^<>]+)| ) {
460 19         30 push @{$cont{$t}{addr}{street}}, $1;
  19         68  
461             }
462             }
463              
464 15         30 foreach my $f ( 'city', 'sp', 'pc' , 'cc' ) {
465 60 50       740 if ( $pi =~ m|(.+?)|s ) {
    0          
466 60         209 $cont{$t}{addr}{$f} = $1;
467             }
468             elsif ( $pi =~ m|| ) {
469 0 0       0 if ( $f eq 'sp' ) {
470             # $cont{$t}{addr}{$f} = undef;
471             }
472             else {
473 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}$f': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.", '2001', $cltrid );
474             }
475             }
476             else {
477 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}addr': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:contact-1.0}$f, {urn:ietf:params:xml:ns:contact-1.0}ext ).", '2001', $cltrid );
478             }
479             }
480              
481 15 50 33     76 unless ( $cont{$t}{addr}{cc} && length( $cont{$t}{addr}{cc} ) == 2 ) {
482 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}cc': [facet 'length'] The value has a length of '4'; this differs from the allowed length of '2'.', '2001', $cltrid );
483             }
484              
485 15 50       72 if ( $cont{$t}{addr}{cc} !~ /^[A-Z]+$/ ) {
486 0         0 return _fail_body( "The country code '$cont{$t}{addr}{cc}' is not known to us", '2004', $cltrid );
487             }
488             }
489              
490 11         21 foreach my $f ( 'voice', 'fax', 'email' ) {
491 31 100 33     337 if ( $body =~ // ) {
    50          
492 21         422 my @cfs = $body =~ m|([^<>]*)|g; # contact fields
493              
494 21         69 $cont{$f} = [];
495 21         40 foreach my $cf ( @cfs ) {
496 24 50       351 if ( $cf =~ m|([^<>]*)| ) {
497 24         62 my $c = $1;
498              
499 24 50 66     216 if ( length( $c ) == 0 ) {
    100 100        
    50 66        
500 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}$f': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.", '2001', $cltrid );
501             }
502             elsif ( $f eq 'fax' || $f eq 'voice' and $c !~ /^\+\d{1,3}\.\d{1,14}$/ ) {
503 1         5 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}voice': [facet 'pattern'] The value 'A380954272445' is not accepted by the pattern '(\\+[0-9]{1,3}\\.[0-9]{1,14})?'.', '2001', $cltrid );
504             }
505             elsif ( $f eq 'email' and $c !~ /^[0-9a-z\.\-]+\@[0-9a-z\.\-]+$/ ) {
506 0         0 return _fail_body( 'E-mail address is invalid or missing', '2004', $cltrid );
507             }
508             else {
509 23         35 push @{$cont{$f}}, $c;
  23         90  
510             }
511             }
512             }
513             }
514             elsif ( $f eq 'fax' and $body =~ m|| ) {
515 10         34 $cont{$f} = [];
516             }
517             else {
518 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}$top': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:contact-1.0}$f, {urn:ietf:params:xml:ns:contact-1.0}ext ).", '2001', $cltrid );
519             }
520             }
521              
522 10 50       67 if ( $body =~ m|\s*([^<>]+)\s*|s ) {
    0          
523 10         38 $cont{authInfo} = $1;
524             }
525             elsif ( $body =~ m|\s*\s*| ) {
526 0         0 $cont{authInfo} = '';
527             }
528             else {
529 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}authInfo': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:contact-1.0}pw, {urn:ietf:params:xml:ns:contact-1.0}ext ).', '2001', $cltrid );
530             }
531 10 100 66     46 if ( $cont{authInfo} and length( $cont{authInfo} ) < 16 ) {
532 1         3 return _fail_body( 'authInfo code is invalid: password must be at least 16 characters', '2004', $cltrid );
533             }
534 9 50 66     102 unless ( $cont{authInfo} and $cont{authInfo} =~ /[A-Z]/ and $cont{authInfo} =~ /[a-z]/ and $cont{authInfo} =~ /[0-9]/ and $cont{authInfo} =~ /[!\@\$\%*_.:\-=+?#,"'\\\/&]/ ) {
      66        
      66        
      33        
535 1         4 return _fail_body( 'authInfo code is invalid: password must contain a mix of uppercase and lowercase characters', '2004', $cltrid );
536             }
537              
538             # TODO: update statuses
539              
540 8 100       23 if ( $act eq 'create' ) {
541 7         31 my ( $cre_date ) = get_dates();
542              
543 7         139 $s->data->{conts}{$cont{id}} = { %cont, reason => 'in use', statuses => { 'ok' => '+' }, owner => $obj->{user}, creater => $obj->{user}, updater => $obj->{user}, cre_date => $cre_date, upd_date => $cre_date, roid => uc(md5_hex($cont{id}.$cre_date)) . '-TEST' };
544              
545 7         94 return _ok_answ( qq|$cont{id}$cre_date|, $cltrid );
546             }
547             else { # update
548 1         4 my $old = $s->data->{conts}{$cont{id}};
549              
550 1 50       4 if ( $old->{owner} ne $obj->{user} ) {
551             # TODO: check main domain
552 0         0 return _fail_body( 'You are not authorised to modify this contact object (you do not sponsor the parent domain).', '2201', $cltrid );
553             }
554              
555 1         3 my ( $upd_date ) = get_dates();
556              
557 1         4 foreach my $f ( 'voice','fax','email','authInfo' ) {
558 4         11 $old->{$f} = $cont{$f};
559             }
560              
561 1         2 for my $t ( 'int', 'loc' ) {
562 2 100       7 if ( $cont{$t} ) {
563 1 50       4 $old->{$t}{name} = $cont{$t}{name} if $cont{$t}{name};
564 1 50       4 if ( $cont{$t}{org} ) {
565             $old->{$t}{org} = $cont{$t}{org}
566 0         0 }
567             else {
568 1         3 delete $old->{$t}{org};
569             }
570 1         4 $old->{$t}{addr} = $cont{$t}{addr};
571             }
572             else {
573 1         5 delete $old->{$t};
574             }
575             }
576              
577 1         2 $old->{upd_date} = $upd_date;
578 1         2 $old->{updater} = $obj->{user};
579              
580 1         4 my $svtrid = get_svtrid();
581              
582 1         4 return _min_answ( '1000', $cltrid );
583             }
584             }
585              
586              
587             sub contact_info {
588 4     4 0 8 my ( $obj, $body ) = @_;
589              
590 4         19 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
591              
592 4 50       11 return _fail_cltrid() unless $cltrid;
593              
594 4 50       24 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
595 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
596             }
597              
598 4 50       26 unless ( $body =~ s|^\s+||s ) {
599 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
600             }
601              
602 4 50       23 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
603 0         0 return _fail_body( 'XML schema validation failed: contact:info', '2001', $cltrid );
604             }
605              
606 4 50       24 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
607 0         0 return _fail_body( 'XML schema validation failed: /contact:info', '2001', $cltrid );
608             }
609              
610 4         8 my $id;
611 4 50       15 if ( $body =~ m|([^<>]+)| ) {
612 4         12 $id = $1;
613             }
614             else {
615 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}id': [facet 'minLength'] The value has a length of '1'; this underruns the allowed minimum length of '3'.', '2001', $cltrid );
616             }
617              
618 4         9 my $srv_url = $obj->{sock};
619 4         15 my $s = new IO::EPP::Test::Server( $srv_url );
620              
621 4 100       12 unless ( $s->data->{conts}{$id} ) {
622 1         5 return _fail_body( "Cannot find an object with an ID of $id.", '2303', $cltrid );
623             }
624              
625 3         6 my %cont = %{$s->data->{conts}{$id}};
  3         7  
626              
627             my $answ = '' .
628 3         12 $id . '' . $cont{roid} . '';
629              
630 3         6 foreach my $s ( keys %{ $cont{statuses} } ) {
  3         10  
631 3 50       8 if ( $cont{statuses}{$s} eq '+' ) {
632 3         10 $answ .= qq||;
633             }
634             else {
635 0         0 $answ .= qq|| . $cont{statuses}{$s} . '';
636             }
637             }
638              
639 3         6 for my $t ( 'int', 'loc' ) {
640 6 100       15 if ( $cont{$t} ) {
641 5         15 $answ .= qq||.$cont{$t}{name}.'';
642 5 100       15 $answ .= $cont{$t}{org} ? qq|$cont{$t}{org}| : '' ;
643 5         7 $answ .= '';
644 5         7 $answ .= qq|$_| for @{$cont{$t}{addr}{street}};
  5         17  
645 5         13 $answ .= qq|$cont{$t}{addr}{city}|;
646 5 50       15 $answ .= $cont{$t}{addr}{sp} ? qq|$cont{$t}{addr}{sp}| : '';
647 5 50       13 $answ .= $cont{$t}{addr}{sp} ? qq|$cont{$t}{addr}{sp}| : '';
648 5 50       14 $answ .= $cont{$t}{addr}{cc} ? qq|$cont{$t}{addr}{cc}| : '';
649 5         6 $answ .= '';
650 5         8 $answ .= '';
651             }
652             }
653 3         5 foreach my $v ( @{$cont{voice}} ) {
  3         6  
654 5         22 $answ .= "$v";
655             }
656 3 50       5 if ( scalar @{$cont{fax}} ) {
  3         18  
657 0         0 foreach my $f ( @{$cont{fax}} ) {
  0         0  
658 0         0 $answ .= "$f";
659             }
660             }
661             else {
662 3         6 $answ .= '';
663             }
664 3         4 foreach my $e ( @{$cont{email}} ) {
  3         8  
665 3         7 $answ .= "$e";
666             }
667 3         8 $answ .= "$cont{owner}";
668 3         7 $answ .= "$cont{creater}";
669 3         6 $answ .= "$cont{cre_date}";
670 3 50       9 $answ .= "$cont{updater}" if $cont{updater};
671 3         7 $answ .= "$cont{upd_date}";
672              
673 3         4 $answ .= qq||;
674              
675 3         7 return _ok_answ( $answ, $cltrid );
676             }
677              
678              
679             sub contact_delete {
680 2     2 0 5 my ( $obj, $body ) = @_;
681              
682 2         12 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
683              
684 2 50       5 return _fail_cltrid() unless $cltrid;
685              
686 2 50       13 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
687 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
688             }
689              
690 2 50       13 unless ( $body =~ s|^\s+||s ) {
691 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
692             }
693              
694 2 50       13 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
695 0         0 return _fail_body( 'XML schema validation failed: contact:info', '2001', $cltrid );
696             }
697              
698 2 50       13 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
699 0         0 return _fail_body( 'XML schema validation failed: /contact:delete', '2001', $cltrid );
700             }
701              
702 2         5 my $id;
703 2 50       9 if ( $body =~ m|([^<>]+)| ) {
704 2         6 $id = $1;
705             }
706             else {
707 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:contact-1.0}id': [facet 'minLength'] The value has a length of '1'; this underruns the allowed minimum length of '3'.', '2001', $cltrid );
708             }
709              
710 2         4 my $srv_url = $obj->{sock};
711 2         8 my $s = new IO::EPP::Test::Server( $srv_url );
712              
713 2 100       6 unless ( $s->data->{conts}{$id} ) {
714 1         5 return _fail_body( "Contact object cannot be found.", '2303', $cltrid );
715             }
716              
717 1 50       4 if ( $s->data->{conts}{$id}{statuses}{linked} ) {
718 0         0 return _fail_body( 'Contact object is linked to one or more domains.', '2305', $cltrid );
719             }
720              
721 1 50       4 if ( $s->data->{conts}{$id}{owner} ne $obj->{user} ) {
722 0         0 return _fail_body( 'Permission denied.', '2201', $cltrid );
723             }
724              
725 1         3 delete $s->data->{conts}->{$id};
726              
727 1         3 my $svtrid = get_svtrid();
728              
729 1         4 return _min_answ( '1000', $cltrid );
730             }
731              
732              
733             sub host_check {
734 1     1 0 3 my ( $obj, $body ) = @_;
735              
736 1         20 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
737              
738 1 50       4 return _fail_cltrid() unless $cltrid;
739              
740 1 50       7 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
741 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
742             }
743              
744 1 50       19 unless ( $body =~ s|^\s+||s ) {
745 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
746             }
747              
748 1 50       11 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
749 0         0 return _fail_body( 'XML schema validation failed: host:check', '2001', $cltrid );
750             }
751              
752 1 50       9 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
753 0         0 return _fail_body( 'XML schema validation failed: /host:check', '2001', $cltrid );
754             }
755              
756 1         9 my ( @hosts ) = $body =~ m|([^<>]+)|g;
757              
758 1 50       5 unless ( scalar @hosts ) {
759 0         0 return _fail_body( 'XML schema validation failed: host:cd', '2001', $cltrid );
760             }
761              
762 1         4 my $srv_url = $obj->{sock};
763 1         5 my $s = new IO::EPP::Test::Server( $srv_url );
764 1         3 my $answ_list = '';
765 1         11 foreach my $row ( @hosts ) {
766 3         16 my ( $ns ) = $row =~ m|([^<>]+)|;
767 3         9 $ns = lc $ns;
768              
769 3         5 my $reason = '';
770              
771 3 100       9 if ( $s->data->{nss}{$ns} ) {
    100          
772 1   50     4 $reason = $s->data->{nss}{$ns}{reason} || '';
773             }
774             elsif ( $ns !~ /^[0-9a-z\.\-]+$/ ) {
775 1         4 my ( $c ) = $ns !~ /([^0-9a-z\.\-])/;
776 1         4 $reason = 'the following characters are not permitted: ''.$c.''';
777             }
778              
779 3 100       8 my $avail = $reason ? 0 : 1;
780              
781 3 100       10 $reason = "$reason" if $reason;
782              
783 3         19 $answ_list .= qq|$ns$reason|;
784             }
785              
786 1         3 my $svtrid = get_svtrid();
787              
788 1         8 return qq|
789            
790            
791            
792             Command completed successfully.
793            
794             $answ_list
795             $cltrid$svtrid
796            
797            
798             |;
799             }
800              
801              
802             sub host_create {
803 8     8 0 16 my ( $obj, $body ) = @_;
804              
805 8         41 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
806              
807 8 50       20 return _fail_cltrid() unless $cltrid;
808              
809 8 50       47 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
810 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
811             }
812              
813 8 50       49 unless ( $body =~ s|^\s+||s ) {
814 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
815             }
816              
817 8 50       45 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
818 0         0 return _fail_body( 'XML schema validation failed: host:create', '2001', $cltrid );
819             }
820              
821 8 50       56 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
822 0         0 return _fail_body( 'XML schema validation failed: /host:create', '2001', $cltrid );
823             }
824              
825 8         16 my ( $ns, $local_ns );
826 8 50       31 if ( $body =~ m|([0-9A-Za-z\-\.]+)| ) {
827 8         38 $ns = lc $1;
828             }
829             else {
830 0         0 return _fail_body( 'Host name is invalid.', '2004', $cltrid );
831             }
832              
833 8         20 my $srv_url = $obj->{sock};
834 8         35 my $s = new IO::EPP::Test::Server( $srv_url );
835 8         22 my $nss = $s->data->{nss};
836 8         18 my $doms = $s->data->{doms};
837              
838 8 100       23 if ( $nss->{$ns} ) {
839 1         3 return _fail_body( 'A host object with that hostname already exists.', '2302', $cltrid );
840             }
841              
842 7         28 my @v4 = $body =~ m|([^<>]+)|g;
843 7         20 my @v6 = $body =~ m|([^<>]+)|g;
844              
845 7         12 foreach my $dm ( keys %{$doms} ) {
  7         25  
846 23 100       255 if ( $ns =~ /\.$dm$/ ) {
847 7 100       36 if ( $doms->{$dm}{owner} ne $obj->{user} ) {
    100          
848 1         4 return _fail_body( 'You are not the sponsor for the parent domain of this host and cannot create subordinate host objects for it.', '2201', $cltrid );
849             }
850             elsif ( ( scalar( @v4 ) + scalar( @v6 ) ) == 0 ) {
851 2         9 return _fail_body( 'You need IPv4 or IPv6 address.', '2004', $cltrid );
852             }
853              
854 4         9 $local_ns = $dm;
855             }
856             }
857              
858 4         13 foreach my $v ( @v4 ) {
859 3 50       16 unless ( $v =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
860 0         0 return _fail_body( "IP address $v is not valid.", '2004', $cltrid );
861             }
862             }
863 4         9 foreach my $v ( @v6 ) {
864 1 50       6 unless ( $v =~ /^[0-9a-z:]{1,29}$/ ) {
865 1         5 return _fail_body( "IP address $v is not valid.", '2004', $cltrid );
866             }
867             }
868              
869 3         9 my ( $cre_date ) = get_dates();
870              
871 3         49 $nss->{$ns} = { avail => 0, reason => 'in use', statuses => { ok => '+' }, creater => $obj->{user}, owner => $obj->{user}, cre_date => $cre_date, addr_v4 => \@v4, addr_v6 => \@v6, roid => uc(md5_hex($ns.$cre_date)) . '-TEST' };
872              
873 3 50       13 if ( $local_ns ) {
874 3         41 $doms->{$local_ns}{hosts}{$ns} = '+';
875             }
876              
877 3         15 return _ok_answ( qq|$ns$cre_date|, $cltrid );
878             }
879              
880              
881             sub host_info {
882 2     2 0 4 my ( $obj, $body ) = @_;
883              
884 2         11 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
885              
886 2 50       6 return _fail_cltrid() unless $cltrid;
887              
888 2 50       13 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
889 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
890             }
891              
892 2 50       12 unless ( $body =~ s|^\s+||s ) {
893 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
894             }
895              
896 2 50       27 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
897 0         0 return _fail_body( 'XML schema validation failed: host:info', '2001', $cltrid );
898             }
899              
900 2 50       17 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
901 0         0 return _fail_body( 'XML schema validation failed: /host:info', '2001', $cltrid );
902             }
903              
904 2         4 my $ns;
905 2 50       9 if ( $body =~ m|([0-9A-Za-z\-\.]+)| ) {
906 2         8 $ns = lc $1;
907             }
908             else {
909 0         0 return _fail_body( 'Host name is invalid.', '2004', $cltrid );
910             }
911              
912 2         5 my $srv_url = $obj->{sock};
913 2         16 my $s = new IO::EPP::Test::Server( $srv_url );
914 2         7 my $nss = $s->data->{nss};
915              
916 2 100       8 unless ( $nss->{$ns} ) {
917 1         6 return _fail_body( "The host '$ns' does not exist", '2303', $cltrid );
918             }
919              
920 1         2 my $answ = '';
921 1         5 $answ .= "$ns";
922 1         4 $answ .= "$$nss{$ns}{roid}";
923 1         2 foreach my $st ( keys %{$$nss{$ns}{statuses}} ) {
  1         6  
924 1 50       5 if ( $$nss{$ns}{statuses}{$st} eq '+' ) {
925 1         5 $answ .= qq||;
926             }
927             else {
928 0         0 $answ .= qq|| . $$nss{$ns}{statuses}{$st} . '';
929             }
930             }
931 1         3 foreach my $v ( @{$$nss{$ns}{addr_v4}} ) {
  1         4  
932 1         4 $answ .= qq|$v|;
933             }
934 1         3 foreach my $v ( @{$$nss{$ns}{addr_v6}} ) {
  1         4  
935 0         0 $answ .= qq|$v|;
936             }
937 1         4 $answ .= "$$nss{$ns}{owner}";
938 1         4 $answ .= "$$nss{$ns}{creater}";
939 1         4 $answ .= "$$nss{$ns}{cre_date}";
940 1 50       4 $answ .= "$$nss{$ns}{upd_date}" if $$nss{$ns}{upd_date};
941 1         2 $answ .= '';
942              
943 1         4 return _ok_answ( $answ, $cltrid );
944             }
945              
946              
947             sub host_update {
948 3     3 0 8 my ( $obj, $body ) = @_;
949              
950 3         16 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
951              
952 3 50       9 return _fail_cltrid() unless $cltrid;
953              
954 3 50       18 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
955 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
956             }
957              
958 3 50       44 unless ( $body =~ s|^\s+||s ) {
959 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
960             }
961              
962 3 50       23 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
963 0         0 return _fail_body( 'XML schema validation failed: host:update', '2001', $cltrid );
964             }
965              
966 3 50       27 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
967 0         0 return _fail_body( 'XML schema validation failed: /host:update', '2001', $cltrid );
968             }
969              
970 3         7 my ( $ns, $local_ns );
971 3 50       12 if ( $body =~ m|([0-9A-Za-z\-\.]+)| ) {
972 3         10 $ns = lc $1;
973             }
974             else {
975 0         0 return _fail_body( 'Host name is invalid.', '2004', $cltrid );
976             }
977              
978 3         7 my $srv_url = $obj->{sock};
979 3         11 my $s = new IO::EPP::Test::Server( $srv_url );
980 3         7 my $nss = $s->data->{nss};
981              
982 3 100       10 unless ( $nss->{$ns} ) {
983 1         13 return _fail_body( "The host '$ns' does not exist", '2303', $cltrid );
984             }
985              
986 2 50       8 if ( $nss->{$ns}{owner} ne $obj->{user} ) {
987             # TODO: check main domain
988 0         0 return _fail_body( 'You are not authorised to modify this host object (you do not sponsor the parent domain).', '2201', $cltrid );
989             }
990              
991 2         5 my ( @a4, @a6, @d4, @d6, @ast, @dst );
992              
993 2         5 for my $act ( 'add', 'rem' ) {
994 3 100       42 if ( $body =~ m|(.+?)|s ) {
995 2         6 my $ab = $1;
996              
997 2         10 my @v4 = $ab =~ m|([^<>]+)|g;
998 2         7 my @v6 = $ab =~ m|([^<>]+)|g;
999              
1000 2         6 foreach my $v ( @v4 ) {
1001 1 50       6 unless ( $v =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
1002 0         0 return _fail_body( "IP address $v is not valid.", '2004', $cltrid );
1003             }
1004              
1005 1 50       4 if ( $act eq 'add' ) { push @a4, $v } else { push @d4, $v }
  1         5  
  0         0  
1006             }
1007              
1008 2         6 foreach my $v ( @v6 ) {
1009 1 50       6 unless ( $v =~ /^[0-9a-f:]{1,29}$/ ) {
1010 1         6 return _fail_body( "IP address $v is not valid.", '2004', $cltrid );
1011             }
1012              
1013 0 0       0 if ( $act eq 'add' ) { push @a6, $v } else { push @d6, $v }
  0         0  
  0         0  
1014             }
1015              
1016             # Centralnic ignored add/rem client* statuses for host
1017             }
1018             }
1019              
1020             # TODO: chg name
1021              
1022 1 50       5 if ( scalar @a4 ) {
1023 1         2 my %h = map { $_ => '+' } @{$nss->{$ns}{addr_v4}};
  1         6  
  1         4  
1024              
1025 1         5 $h{$_} = '+' for @a4;
1026              
1027 1         12 $nss->{$ns}{addr_v4} = [ sort keys %h ];
1028             }
1029              
1030 1 50       4 if ( scalar @a6 ) {
1031 0         0 my %h = map { $_ => '+' } @{$nss->{$ns}{addr_v6}};
  0         0  
  0         0  
1032              
1033 0         0 $h{$_} = '+' for @a6;
1034              
1035 0         0 $nss->{$ns}{addr_v6} = [ sort keys %h ];
1036             }
1037              
1038 1 50       4 if ( scalar @d4 ) {
1039 0         0 my %h = map { $_ => '+' } @{$nss->{$ns}{addr_v4}};
  0         0  
  0         0  
1040              
1041 0         0 delete( $h{$_} ) for @d4;
1042              
1043 0         0 $nss->{$ns}{addr_v4} = [ sort keys %h ];
1044             }
1045              
1046 1 50       3 if ( scalar @d6 ) {
1047 0         0 my %h = map { $_ => '+' } @{$nss->{$ns}{addr_v6}};
  0         0  
  0         0  
1048              
1049 0         0 delete( $h{$_} ) for @d6;
1050              
1051 0         0 $nss->{$ns}{addr_v6} = [ sort keys %h ];
1052             }
1053              
1054 1         4 my $svtrid = get_svtrid();
1055              
1056 1         3 return _min_answ( '1000', $cltrid );
1057             }
1058              
1059              
1060             sub host_delete {
1061 2     2 0 4 my ( $obj, $body ) = @_;
1062              
1063 2         12 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1064              
1065 2 50       6 return _fail_cltrid() unless $cltrid;
1066              
1067 2 50       14 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1068 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1069             }
1070              
1071 2 50       13 unless ( $body =~ s|^\s+||s ) {
1072 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1073             }
1074              
1075 2 50       12 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1076 0         0 return _fail_body( 'XML schema validation failed: host:delete', '2001', $cltrid );
1077             }
1078              
1079 2 50       28 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1080 0         0 return _fail_body( 'XML schema validation failed: /host:delete', '2001', $cltrid );
1081             }
1082              
1083 2         89 my $ns;
1084 2 50       14 if ( $body =~ m|([0-9A-Za-z\-\.]+)| ) {
1085 2         9 $ns = lc $1;
1086             }
1087             else {
1088 0         0 return _fail_body( 'Host name is invalid.', '2004', $cltrid );
1089             }
1090              
1091 2         4 my $srv_url = $obj->{sock};
1092 2         9 my $s = new IO::EPP::Test::Server( $srv_url );
1093 2         6 my $nss = $s->data->{nss};
1094              
1095 2 100       7 unless ( $nss->{$ns} ) {
1096 1         6 return _fail_body( "The host '$ns' does not exist", '2303', $cltrid );
1097             }
1098              
1099 1 50       79 if ( $nss->{$ns}{statuses}{linked} ) {
1100 0         0 return _fail_body( 'Host object is linked to one or more domains.', '2305', $cltrid );
1101             }
1102              
1103 1         8 my $doms = $s->data->{doms};
1104 1         3 foreach my $dm ( keys %{$doms} ) {
  1         5  
1105 2 100       32 if ( $ns =~ /\.$dm$/ ) {
1106 1         6 delete $doms->{$dm}{hosts}->{$ns};
1107             }
1108             }
1109              
1110 1 50       5 if ( $nss->{$ns}{owner} ne $obj->{user} ) {
1111 0         0 return _fail_body( 'Permission denied.', '2201', $cltrid );
1112             }
1113              
1114 1         5 delete $nss->{$ns};
1115              
1116 1         3 my $svtrid = get_svtrid();
1117              
1118 1         4 return _min_answ( '1000', $cltrid );
1119             }
1120              
1121              
1122             sub domain_check {
1123 2     2 0 7 my ( $obj, $body ) = @_;
1124              
1125 2         12 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1126              
1127 2 50       6 return _fail_cltrid() unless $cltrid;
1128              
1129 2 50       22 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1130 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1131             }
1132              
1133 2 50       15 unless ( $body =~ s|^\s+||s ) {
1134 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1135             }
1136              
1137 2 50       19 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1138 0         0 return _fail_body( 'XML schema validation failed: domain:check', '2001', $cltrid );
1139             }
1140              
1141 2 50       23 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1142 0         0 return _fail_body( 'XML schema validation failed: /domain:check', '2001', $cltrid );
1143             }
1144              
1145 2         30 my ( @domains ) = $body =~ m|([^<>]+)|g;
1146              
1147 2 50       6 unless ( scalar @domains ) {
1148 0         0 return _fail_body( 'XML schema validation failed: domain:cd', '2001', $cltrid );
1149             }
1150              
1151 2         6 my $srv_url = $obj->{sock};
1152 2         15 my $s = new IO::EPP::Test::Server( $srv_url );
1153 2         5 my $answ_list = '';
1154 2         5 foreach my $row ( @domains ) {
1155 20         77 my ( $dm ) = $row =~ m|([^<>]+)|;
1156 20         39 $dm = lc $dm;
1157              
1158 20         28 my $reason = '';
1159              
1160 20 100       43 if ( $s->data->{doms}{$dm} ) {
    100          
    50          
    100          
    100          
1161 2   100     3 $reason = $s->data->{doms}{$dm}{reason} || '';
1162             }
1163             elsif ( $dm !~ /^[0-9a-z\.\-]+$/ ) {
1164 1         5 my ( $c ) = $dm !~ /([^0-9a-z\.\-])/;
1165 1         4 $reason = 'the following characters are not permitted: ''.$c.''';
1166             }
1167             elsif ( $dm =~ /^reg/ ) { # reged
1168 0         0 $reason = 'in use';
1169             }
1170             elsif ( $dm =~ /^blo/ ) {
1171 1         3 $reason = 'blocked';
1172             }
1173             elsif ( $dm =~ /^ava/ ) {
1174             # available
1175             }
1176             else {
1177 15 100       42 $reason = int( rand( 10 ) ) == 1 ? 'in use' : ''; # 10% -- domains is not available
1178             }
1179              
1180 20 100       52 my $avail = $reason ? 0 : 1;
1181              
1182 20 100       41 unless ( $s->data->{doms}{$dm} ) {
1183 18 100 100     56 if ( $reason && $reason !~ /not permitted/ ) {
1184 4         25 $s->data->{doms}{$dm} = { avail => $avail, reason => $reason };
1185             }
1186             }
1187              
1188 20 100       43 $reason = "$reason" if $reason;
1189              
1190 20         67 $answ_list .= qq|$dm$reason|;
1191             }
1192              
1193 2         27 my $svtrid = get_svtrid();
1194              
1195 2         17 return qq|
1196            
1197            
1198            
1199             Command completed successfully.
1200            
1201             $answ_list
1202             $cltrid$svtrid
1203            
1204            
1205             |;
1206             }
1207              
1208              
1209             sub domain_create {
1210 12     12 0 20 my ( $obj, $body ) = @_;
1211              
1212 12         67 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1213              
1214 12 50       28 return _fail_cltrid() unless $cltrid;
1215              
1216 12 50       72 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1217 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1218             }
1219              
1220 12 50       67 unless ( $body =~ s|^\s+||s ) {
1221 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1222             }
1223              
1224 12 50       69 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1225 0         0 return _fail_body( 'XML schema validation failed: domain:create', '2001', $cltrid );
1226             }
1227              
1228 12 50       142 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1229 0         0 return _fail_body( 'XML schema validation failed: /domain:create', '2001', $cltrid );
1230             }
1231              
1232 12         25 my $dname;
1233 12 50       39 if ( $body =~ m|([^<>]+)| ) {
1234 12         41 $dname = lc $1;
1235             }
1236             else {
1237 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}name': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.', '2001', $cltrid );
1238             }
1239              
1240 12 100       34 if ( $dname =~ /([^0-9a-z\.\-])/ ) {
1241 1         7 return _fail_body( "'$dname' is not a valid domain name: the following characters are not permitted: '$1'", '2004', $cltrid );
1242             }
1243              
1244 11 100       42 if ( $dname !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
1245 1         7 return _fail_body( "'$dname' is not a valid domain name: suffix ... does not exist", '2004', $cltrid );
1246             }
1247              
1248 10         22 my $srv_url = $obj->{sock};
1249 10         38 my $s = new IO::EPP::Test::Server( $srv_url );
1250 10         27 my $conts = $s->data->{conts};
1251 10         22 my $nss = $s->data->{nss};
1252 10         19 my $doms = $s->data->{doms};
1253              
1254 10 100       28 if ( $doms->{$dname} ) {
1255 2         8 return _fail_body( "'$dname' is already registered.", '2302', $cltrid );
1256             }
1257              
1258 8         10 my $period;
1259 8 50       34 if ( $body =~ m|([^<>]+)| ) {
1260 8         17 $period = $1;
1261              
1262 8 50       20 if ( $period =~ /([^0-9])/ ) {
1263 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}period': '$period' is not a valid value of the atomic type '{urn:ietf:params:xml:ns:domain-1.0}pLimitType'." );
1264             }
1265             }
1266             else {
1267 0         0 $period = 1;
1268             }
1269              
1270 8 50 33     50 if ( $period < 1 or $period > 9 ) {
1271 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}period': [facet 'maxInclusive'] The value '100' is greater than the maximum value allowed ('9').", '2001', $cltrid );
1272             }
1273              
1274 8         12 my $reg_id;
1275 8 100       31 if ( $body =~ m|([^<>]+)| ) {
1276 7         15 $reg_id = $1;
1277              
1278 7 100       20 unless ( $conts->{$reg_id} ) {
1279 1         6 return _fail_body( "Specified registrant contact $reg_id is not registered here.", '2303', $cltrid );
1280             }
1281             }
1282             else {
1283 1         4 return _fail_body( 'The 'registrant' attribute is empty or missing', '2003', $cltrid );
1284             }
1285              
1286 6         22 my %cc = ( admin => {}, tech => {}, billing => {} );
1287 6         15 for my $t ( 'admin', 'tech', 'billing' ) {
1288 16         327 my @acs = $body =~ m|([^<>]+)|gs;
1289              
1290 16         44 foreach my $ac ( @acs ) {
1291 16 100       35 if ( $conts->{$ac} ) {
1292 15         49 $cc{$t}{$ac} = '+';
1293             }
1294             else {
1295 1         7 return _fail_body( "Specified $t contact $ac is not registered here.", '2303', $cltrid );
1296             }
1297             }
1298             }
1299              
1300 5         8 my $pw;
1301 5 50       29 if ( $body =~ m|\s*([^<>]+)\s*|s ) {
1302 5         12 $pw = $1;
1303             }
1304             else {
1305 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}authInfo': Missing child element(s). Expected is one of ( {urn:ietf:params:xml:ns:domain-1.0}pw, {urn:ietf:params:xml:ns:domain-1.0}ext ).', '2001', $cltrid );
1306             }
1307 5 100 66     23 if ( $pw and length( $pw ) < 16 ) {
1308 1         4 return _fail_body( 'authInfo code is invalid: password must be at least 16 characters', '2004', $cltrid );
1309             }
1310 4 50 66     39 unless ( $pw and $pw =~ /[A-Z]/ and $pw =~ /[a-z]/ and $pw =~ /[0-9]/ and $pw =~ /[!\@\$\%*_.:\-=+?#,"'\\\/&]/ ) {
      66        
      66        
      33        
1311 1         5 return _fail_body( 'authInfo code is invalid: password must contain a mix of uppercase and lowercase characters', '2004', $cltrid );
1312             }
1313              
1314 3         7 my %nss;
1315 3 50       16 if ( $body =~ m|(.+?)|s ) {
1316 3         10 my $hosts = $1;
1317              
1318 3         16 my @nss0 = $hosts =~ m|([^<>]+)|gs;
1319              
1320 3         7 foreach my $ns ( @nss0 ) {
1321 5 100       14 unless ( $nss->{$ns} ) {
1322 1         6 return _fail_body( "Cannot find host object '$ns'", '2303', $cltrid );
1323             }
1324              
1325 4         11 $nss{$ns} = '+';
1326             }
1327             }
1328              
1329 2         7 my ( $cre_date, $exp_date ) = get_dates( 1 );
1330              
1331             $doms->{$dname} = {
1332             registrant => $reg_id,
1333             admin => $cc{admin},
1334             tech => $cc{tech},
1335             billing => $cc{billing},
1336             nss => \%nss,
1337             cre_date => $cre_date,
1338             upd_date => $cre_date,
1339             exp_date => $exp_date,
1340             authInfo => $pw,
1341             roid => uc(md5_hex($dname.$cre_date)).'-TEST',
1342             statuses => { },
1343             creater => $obj->{user},
1344             owner => $obj->{user},
1345             updater => $obj->{user},
1346 2         36 avail => 0,
1347             reason => 'in use',
1348             };
1349              
1350 2         8 $conts->{$reg_id}{statuses}{linked}++;
1351              
1352 2 100       8 if ( $conts->{$reg_id}{statuses}{ok} ) {
1353 1         2 delete $conts->{$reg_id}{statuses}{ok};
1354 1         4 $conts->{$reg_id}{statuses}{serverDeleteProhibited} = '+';
1355             }
1356              
1357 2         53 for my $t ( 'admin', 'tech', 'billing' ) {
1358              
1359 6         10 foreach my $c ( keys %{$cc{$t}} ) {
  6         19  
1360 6         12 $conts->{$c}{statuses}{linked}++;
1361              
1362 6 100       14 if ( $conts->{$c}{statuses}{ok} ) {
1363 3         5 delete $conts->{$c}{statuses}{ok};
1364 3         7 $conts->{$c}{statuses}{serverDeleteProhibited} = '+';
1365             }
1366             }
1367             }
1368              
1369 2         6 foreach my $ns ( keys %nss ) {
1370 4         10 $nss->{$ns}{statuses}{linked}++;
1371              
1372 4 50       12 if ( $nss->{$ns}{statuses}{ok} ) {
1373 0         0 delete $nss->{$ns}{statuses}{ok};
1374 0         0 $nss->{$ns}{statuses}{serverDeleteProhibited} = '+';
1375             }
1376             }
1377              
1378 2         12 return _ok_answ( qq|$dname$cre_date$exp_date|, $cltrid );
1379             }
1380              
1381              
1382             sub domain_info {
1383 4     4 0 11 my ( $obj, $body ) = @_;
1384              
1385 4         23 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1386              
1387 4 50       12 return _fail_cltrid() unless $cltrid;
1388              
1389 4 50       26 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1390 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1391             }
1392              
1393 4 50       26 unless ( $body =~ s|^\s+||s ) {
1394 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1395             }
1396              
1397 4 50       27 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1398 0         0 return _fail_body( 'XML schema validation failed: domain:info', '2001', $cltrid );
1399             }
1400              
1401 4 50       28 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1402 0         0 return _fail_body( 'XML schema validation failed: /domain:info', '2001', $cltrid );
1403             }
1404              
1405 4         9 my $dname;
1406 4 50       18 if ( $body =~ m|([^<>]+)| ) {
1407 4         14 $dname = lc $1;
1408             }
1409             else {
1410 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}name': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.', '2001', $cltrid );
1411             }
1412              
1413 4 50       15 if ( $dname =~ /([^0-9a-z\.\-])/ ) {
1414 0         0 return _fail_body( "'$dname' is not a valid domain name: the following characters are not permitted: '$1'", '2004', $cltrid );
1415             }
1416              
1417 4 50       18 if ( $dname !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
1418 0         0 return _fail_body( "'$dname' is not a valid domain name: suffix ... does not exist", '2004', $cltrid );
1419             }
1420              
1421 4         12 my $srv_url = $obj->{sock};
1422 4         17 my $s = new IO::EPP::Test::Server( $srv_url );
1423 4         13 my $doms = $s->data->{doms};
1424              
1425 4 100       11 unless ( $s->data->{doms}{$dname} ) {
1426 1         7 return _fail_body( "The domain '$dname' does not exist", '2303', $cltrid );
1427             }
1428              
1429 3         9 my $dm = $s->data->{doms}{$dname};
1430              
1431 3         9 my $answ = qq|$dname|;
1432 3         11 $answ .= "$$dm{roid}";
1433 3 100       5 unless ( scalar( keys %{$$dm{statuses}} ) ) {
  3         12  
1434 2         4 $answ .= qq||;
1435             }
1436             else {
1437 1         2 for my $st ( keys %{$$dm{statuses}} ) {
  1         5  
1438 1 50       5 if ( $$dm{statuses}{$st} eq '+' ) {
1439 1         5 $answ .= qq||;
1440             }
1441             else {
1442 0         0 $answ .= qq|| . $$dm{statuses}{$st} . '';
1443             }
1444             }
1445             }
1446 3         11 $answ .= "$$dm{registrant}";
1447 3         6 for my $t ( 'tech', 'admin', 'billing' ) {
1448 9         14 for my $c ( keys %{$$dm{$t}} ) {
  9         23  
1449 9         24 $answ .= qq|$c|;
1450             }
1451             }
1452 3 50 50     12 if ( $$dm{nss} && scalar( keys %{$$dm{nss}} ) ) {
  3         13  
1453 3         6 $answ .= '';
1454 3         4 foreach my $ns ( keys %{$$dm{nss}} ) {
  3         8  
1455 6         15 $answ .= "$ns";
1456             }
1457 3         6 $answ .= '';
1458             }
1459 3 50 100     11 if ( $$dm{hosts} && scalar( keys %{$$dm{hosts}} ) ) {
  1         5  
1460 1         3 foreach my $host ( sort keys %{$$dm{hosts}} ) {
  1         9  
1461 2         6 $answ .= "$host";
1462             }
1463             }
1464             # centralnic does not show authinfo to anybody
1465 3         9 $answ .= "$$dm{owner}";
1466 3         9 $answ .= "$$dm{creater}";
1467 3         8 $answ .= "$$dm{cre_date}";
1468 3         6 $answ .= "$$dm{updater}";
1469 3         7 $answ .= "$$dm{upd_date}";
1470 3         10 $answ .= "$$dm{exp_date}";
1471 3 50       9 $answ .= "$$dm{trans_date}" if $dm->{trans_date};
1472 3         5 $answ .= '';
1473              
1474 3         9 return _ok_answ( $answ, $cltrid );
1475             }
1476              
1477              
1478             sub domain_renew {
1479 5     5 0 10 my ( $obj, $body ) = @_;
1480              
1481 5         24 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1482              
1483 5 50       13 return _fail_cltrid() unless $cltrid;
1484              
1485 5 50       29 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1486 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1487             }
1488              
1489 5 50       29 unless ( $body =~ s|^\s+||s ) {
1490 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1491             }
1492              
1493 5 50       30 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1494 0         0 return _fail_body( 'XML schema validation failed: domain:renew', '2001', $cltrid );
1495             }
1496              
1497 5 50       38 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1498 0         0 return _fail_body( 'XML schema validation failed: /domain:renew', '2001', $cltrid );
1499             }
1500              
1501 5         8 my $dname;
1502 5 50       19 if ( $body =~ m|([^<>]+)| ) {
1503 5         18 $dname = lc $1;
1504             }
1505             else {
1506 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}name': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.', '2001', $cltrid );
1507             }
1508              
1509 5 50       13 if ( $dname =~ /([^0-9a-z\.\-])/ ) {
1510 0         0 return _fail_body( "'$dname' is not a valid domain name: the following characters are not permitted: '$1'", '2004', $cltrid );
1511             }
1512              
1513 5 50       19 if ( $dname !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
1514 0         0 return _fail_body( "'$dname' is not a valid domain name: suffix ... does not exist", '2004', $cltrid );
1515             }
1516              
1517 5         11 my $srv_url = $obj->{sock};
1518 5         18 my $s = new IO::EPP::Test::Server( $srv_url );
1519 5         14 my $doms = $s->data->{doms};
1520              
1521 5 50       11 unless ( $s->data->{doms}{$dname} ) {
1522 0         0 return _fail_body( "The domain '$dname' does not exist", '2303', $cltrid );
1523             }
1524              
1525 5         11 my $dm = $s->data->{doms}{$dname};
1526              
1527 5         11 for my $s ( 'clientRenewProhibited', 'serverRenewProhibited' ) {
1528 10 100       35 if ( $dm->{statuses}{$s} ) {
1529 1         7 return _fail_body( "Domain cannot be renewed ($s)", 2304, $cltrid );
1530             }
1531             }
1532              
1533 4         7 my $period = 1;
1534 4 50       28 if ( $body =~ m|(\d+)| ) {
1535 4         12 $period = $1;
1536              
1537 4 100       12 if ( $period > 9 ) {
1538 1         6 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}period': [facet 'maxInclusive'] The value '$period' is greater than the maximum value allowed ('9').", '2001', $cltrid );
1539             }
1540             }
1541              
1542 3         5 my $edt;
1543 3 100       14 if ( $body =~ m|(\d\d\d\d-\d\d-\d\d)| ) {
1544 2         5 $edt = $1;
1545             }
1546             else {
1547 1         4 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}curExpDate': 'xxx' is not a valid value of the atomic type 'xs:date'.", '2001', $cltrid );
1548             }
1549              
1550 2         8 my ( $old_exp_date ) = $dm->{exp_date} =~ /^(\d\d\d\d-\d\d-\d\d)/;
1551 2 100       8 if ( $old_exp_date ne $edt ) {
1552 1         3 return _fail_body( 'Expiry date is not correct.', '2004', $cltrid );
1553             }
1554              
1555 1         7 $dm->{exp_date} =~ s/^(\d+)/$1+$period/e;
  1         6  
1556 1         4 my $new_exp_date = $dm->{exp_date};
1557              
1558 1         4 my $svtrid = get_svtrid();
1559              
1560 1         11 return qq|
1561            
1562            
1563             Command completed successfully.
1564            
1565              
1566            
1567            
1568             $dname
1569             $new_exp_date
1570            
1571            
1572            
1573             $cltrid
1574             $svtrid
1575            
1576            
1577             |;
1578             =rem
1579            
1580            
1581            
1582             Command completed successfully.
1583            
1584              
1585            
1586            
1587             xxx.ru.com
1588             2022-07-18T23:59:59.0Z
1589            
1590            
1591             USD18.00
1592            
1593             f919bef2e68b168e5d39bf91aff6fa6e
1594             CNIC-7295E4F58291FFD21B1702346BA9D70F25952BD03CF3780ECF0DA0D8285
1595            
1596            
1597            
1598             =cut
1599             }
1600              
1601              
1602             sub domain_update {
1603 20     20 0 39 my ( $obj, $body ) = @_;
1604              
1605 20         106 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1606              
1607 20 50       44 return _fail_cltrid() unless $cltrid;
1608              
1609 20 50       113 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1610 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1611             }
1612              
1613 20 50       114 unless ( $body =~ s|^\s+||s ) {
1614 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1615             }
1616              
1617 20 50       121 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1618 0         0 return _fail_body( 'XML schema validation failed: domain:update', '2001', $cltrid );
1619             }
1620              
1621 20 50       173 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1622 0         0 return _fail_body( 'XML schema validation failed: /domain:update', '2001', $cltrid );
1623             }
1624              
1625 20         35 my $dname;
1626 20 50       79 if ( $body =~ m|([^<>]+)| ) {
1627 20         72 $dname = lc $1;
1628             }
1629             else {
1630 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}name': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.', '2001', $cltrid );
1631             }
1632              
1633 20 50       56 if ( $dname =~ /([^0-9a-z\.\-])/ ) {
1634 0         0 return _fail_body( "'$dname' is not a valid domain name: the following characters are not permitted: '$1'", '2004', $cltrid );
1635             }
1636              
1637 20 50       68 if ( $dname !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
1638 0         0 return _fail_body( "'$dname' is not a valid domain name: suffix ... does not exist", '2004', $cltrid );
1639             }
1640              
1641 20         47 my $srv_url = $obj->{sock};
1642 20         72 my $s = new IO::EPP::Test::Server( $srv_url );
1643 20         51 my $conts = $s->data->{conts};
1644 20         42 my $nss = $s->data->{nss};
1645 20         38 my $doms = $s->data->{doms};
1646              
1647 20 100       41 unless ( $s->data->{doms}{$dname} ) {
1648 1         5 return _fail_body( "The domain '$dname' does not exist", '2303', $cltrid );
1649             }
1650              
1651 19         39 my $dm = $s->data->{doms}{$dname};
1652              
1653 19 100       50 if ( $dm->{statuses}{serverUpdateProhibited} ) {
1654 1         3 return _fail_body( 'The domain name cannot be updated (serverUpdateProhibited).', '2304', $cltrid );
1655             }
1656              
1657 18 100       40 my $no_upd = $dm->{statuses}{clientUpdateProhibited} ? 1 : 0;
1658              
1659 18 100       68 if ( $body =~ m|(.+?)|s ) {
1660 6         16 my $u = $1;
1661              
1662 6         21 my @sts = $u =~ m|
1663              
1664 6         16 foreach my $st ( @sts ) {
1665 1 50 33     8 if ( $no_upd && $st eq 'clientUpdateProhibited' ) {
1666 1         12 $no_upd = 0;
1667             }
1668             }
1669             }
1670              
1671 18 100       40 if ( $no_upd ) {
1672 1         4 return _fail_body( 'The domain name cannot be updated (clientUpdateProhibited).', '2304', $cltrid );
1673             }
1674              
1675              
1676 17         40 my %add;
1677             my %rem;
1678 17         0 my %chg;
1679              
1680             # For NSS Registry at first adds everything, then deletes -- it is already checked
1681 17 100       61 if ( $body =~ m|(.+?)|s ) {
1682 9         26 my $add = $1;
1683              
1684             # CentralNIC not save the status reason
1685 9         31 my @sts = $add =~ /
1686              
1687 9         21 foreach my $st ( @sts ) {
1688 4 100       13 unless ( $statuses{$st} ) {
1689 1         7 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}status', attribute 's': [facet 'enumeration'] The value '$st' is not an element of the set {'clientDeleteProhibited', 'clientHold', 'clientRenewProhibited', 'clientTransferProhibited', 'clientUpdateProhibited', 'inactive', 'ok', 'pendingCreate', 'pendingDelete', 'pendingRenew', 'pendingTransfer', 'pendingUpdate', 'serverDeleteProhibited', 'serverHold', 'serverRenewProhibited', 'serverTransferProhibited', 'serverUpdateProhibited'}.", '2001', $cltrid );
1690             }
1691              
1692 3 100       9 if ( $dm->{statuses}{$st} ) {
1693 1         6 return _fail_body( "$st is already set on this domain.", '2004', $cltrid );
1694             }
1695              
1696 2         3 push @{$add{statuses}}, $st;
  2         9  
1697             }
1698              
1699 7         14 foreach my $t ( 'admin', 'tech', 'billing' ) {
1700 21 100       392 if ( $add =~ m|([^<>]+)| ) {
1701 2         9 $add{$t} = $1;
1702              
1703 2 50       11 unless ( $conts->{$add{$t}} ) {
1704 0         0 return _fail_body( "Cannot add $t contact $add{$t} contact not found.", '2303', $cltrid );
1705             }
1706             }
1707             }
1708              
1709 7 100       32 if ( $add =~ m|(.+?)|s ) {
1710 3         8 my $ns = $1;
1711              
1712 3         15 my @hosts = $ns =~ m|([^<>]+)|g;
1713              
1714 3         9 $add{nss} = {};
1715              
1716 3         7 foreach my $h ( @hosts ) {
1717 3 100       12 if ( $nss->{$h} ) {
1718 2         7 $add{nss}{$h} = '+';
1719             }
1720             else {
1721 1         6 return _fail_body( "Cannot find host object '$h'", '2303', $cltrid );
1722             }
1723             }
1724             }
1725             }
1726              
1727 14 100       62 if ( $body =~ m|(.+?)|s ) {
1728 6         18 my $rem = $1;
1729              
1730 6         16 my @sts = $rem =~ m|
1731              
1732 6         13 foreach my $st ( @sts ) {
1733 1 50       5 unless ( $statuses{$st} ) {
1734 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}status', attribute 's': [facet 'enumeration'] The value '$st' is not an element of the set {'clientDeleteProhibited', 'clientHold', 'clientRenewProhibited', 'clientTransferProhibited', 'clientUpdateProhibited', 'inactive', 'ok', 'pendingCreate', 'pendingDelete', 'pendingRenew', 'pendingTransfer', 'pendingUpdate', 'serverDeleteProhibited', 'serverHold', 'serverRenewProhibited', 'serverTransferProhibited', 'serverUpdateProhibited'}.", '2001', $cltrid );
1735             }
1736              
1737 1 50       4 unless ( $dm->{statuses}{$st} ) {
1738 0         0 return _fail_body( "$st is not set on this domain.", '2004', $cltrid );
1739             }
1740              
1741 1         2 push @{$rem{statuses}}, $st;
  1         5  
1742             }
1743              
1744 6         12 foreach my $t ( 'admin', 'tech', 'billing' ) {
1745 18 100       335 if ( $rem =~ m|([^<>]+)| ) {
1746 2         9 $rem{$t} = $1;
1747              
1748 2 50       8 unless ( $conts->{$rem{$t}} ) {
1749 0         0 return _fail_body( "Cannot remove $t contact $rem{$t}: contact not found.", '2303', $cltrid );
1750             }
1751              
1752 2 50       10 unless ( $dm->{$t}{$rem{$t}} ) {
1753 0         0 return _fail_body( "Invalid contact association type '$t'", '2004', $cltrid );
1754             }
1755             }
1756             }
1757              
1758 6 100       30 if ( $rem =~ m|(.+?)|s ) {
1759 3         8 my $ns = $1;
1760              
1761 3         14 my @hosts = $ns =~ m|([^<>]+)|g;
1762              
1763 3         8 $rem{nss} = {};
1764              
1765 3         8 foreach my $h ( @hosts ) {
1766 3 100       10 if ( $add{nss}{$h} ) {
1767 1         3 delete $add{nss}{$h};
1768 1         4 next;
1769             }
1770              
1771 2 100       8 if ( $dm->{nss}{$h} ) {
1772 1         5 $rem{nss}{$h} = '+';
1773             }
1774             else {
1775 1         5 return _fail_body( "The host $h is not linked to this domain name.", '2303', $cltrid );
1776             }
1777             }
1778             }
1779             }
1780              
1781 13         26 foreach my $t ( 'admin', 'tech', 'billing' ) {
1782 37 100 100     91 if ( $add{$t} and not $rem{$t} ) {
1783 1         7 return _fail_body( "Cannot assign a new $t contact without removing current tech contact.", '2004', $cltrid );
1784             }
1785              
1786 36 100 100     124 if ( not $add{$t} and $rem{$t} ) {
1787 1         6 return _fail_body( "Invalid contact association type '$t'", '2004', $cltrid );
1788             }
1789             }
1790              
1791 11 100       48 if ( $body =~ m|(.+?)|s ) {
1792 5         16 my $chg = $1;
1793              
1794 5 100       17 if ( $chg =~ m|([^<>]+)| ) {
1795 2         7 $chg{registrant} = $1;
1796              
1797 2 100       9 unless ( $conts->{$chg{registrant}} ) {
1798 1         5 return _fail_body( "Contact $chg{registrant} does not exist, cannot change registrant.", '2303', $cltrid );
1799             }
1800             }
1801              
1802 4 100       21 if ( $chg =~ m|authInfo.+([^<>]*).+authInfo|s ) {
1803 3         8 my $pw = $1;
1804              
1805 3 100 66     15 if ( $pw and length( $pw ) < 16 ) {
1806 1         4 return _fail_body( 'authInfo code is invalid: password must be at least 16 characters', '2004', $cltrid );
1807             }
1808              
1809 2 50 66     25 unless ( $pw and $pw =~ /[A-Z]/ and $pw =~ /[a-z]/ and $pw =~ /[0-9]/ and $pw =~ /[!\@\$\%*_.:\-=+?#,"'\\\/&]/ ) {
      66        
      66        
      33        
1810 1         4 return _fail_body( 'authInfo code is invalid: password must contain a mix of uppercase and lowercase characters', '2004', $cltrid );
1811             }
1812              
1813 1         6 $chg{authInfo} = $pw;
1814             }
1815             }
1816              
1817             # at first there is adding!!!
1818 8 100       26 if ( scalar( keys %add ) ) {
1819 5 100       16 if ( $add{statuses} ) {
1820 2         4 foreach my $st ( @{$add{statuses}} ) {
  2         5  
1821 2         6 $dm->{statuses}{$st} = '+';
1822             }
1823             }
1824              
1825 5         11 foreach my $t ( 'admin', 'tech', 'billing' ) {
1826 15 100       34 if ( $add{$t} ) {
1827 1         4 $dm->{$t}{$add{$t}} = '+';
1828              
1829 1         5 $conts->{$add{$t}}{statuses}{linked}++;
1830              
1831 1 50       6 if ( $conts->{$add{$t}}{statuses}{ok} ) {
1832 1         4 delete $conts->{$add{$t}}{statuses}{ok};
1833 1         3 $conts->{$add{$t}}{statuses}{serverDeleteProhibited} = '+';
1834             }
1835             }
1836             }
1837              
1838 5 100       12 if ( $add{nss} ) {
1839 2         4 foreach my $ns ( keys %{$add{nss}} ) {
  2         9  
1840 1         3 $dm->{nss}{$ns} = '+';
1841              
1842 1         4 $nss->{$ns}{statuses}{linked}++;
1843              
1844 1 50       6 if ( $nss->{$ns}{statuses}{ok} ) {
1845 1         3 delete $nss->{$ns}{statuses}{ok};
1846 1         3 $nss->{$ns}{statuses}{serverDeleteProhibited} = '+';
1847             }
1848             }
1849             }
1850             }
1851              
1852 8 100       21 if ( scalar( keys %rem ) ) {
1853 4 100       24 if ( $rem{statuses} ) {
1854 1         3 foreach my $st ( @{$rem{statuses}} ) {
  1         4  
1855 1         3 delete $dm->{statuses}->{$st};
1856             }
1857             }
1858              
1859 4         9 foreach my $t ( 'admin', 'tech', 'billing' ) {
1860 12 100       29 if ( $rem{$t} ) {
1861 1         3 delete $dm->{$t}{$rem{$t}};
1862              
1863 1         5 $conts->{$rem{$t}}{statuses}{linked}--;
1864              
1865 1 50       4 if ( $conts->{$rem{$t}}{statuses}{linked} <= 0 ) {
1866 0         0 delete $conts->{$rem{$t}}{statuses}{linked};
1867              
1868 0         0 $conts->{$rem{$t}}{statuses}{ok} = '+';
1869 0         0 delete $conts->{$rem{$t}}{statuses}{serverDeleteProhibited};
1870             }
1871             }
1872             }
1873              
1874 4 100       10 if ( $rem{nss} ) {
1875 2         5 foreach my $ns ( keys %{$rem{nss}} ) {
  2         7  
1876 1         3 delete $dm->{nss}->{$ns};
1877              
1878 1         4 $nss->{$ns}{statuses}{linked}--;
1879              
1880 1 50       4 if ( $nss->{$ns}{statuses}{linked} <= 0 ) {
1881 1         3 delete $nss->{$ns}{statuses}{linked};
1882              
1883 1         3 $nss->{$ns}{statuses}{ok} = '+';
1884 1         3 delete $nss->{$ns}{statuses}{serverDeleteProhibited};
1885             }
1886             }
1887             }
1888             }
1889              
1890 8 100       19 if ( $chg{registrant} ) {
1891 1         7 $conts->{$dm->{registrant}}{statuses}{linked}--;
1892              
1893 1 50       6 if ( $conts->{$dm->{registrant}}{statuses}{linked} <= 0 ) {
1894 0         0 delete $conts->{$dm->{registrant}}{statuses}{linked};
1895              
1896 0         0 $conts->{$dm->{registrant}}{statuses}{ok} = '+';
1897 0         0 delete $conts->{$dm->{registrant}}{statuses}{serverDeleteProhibited};
1898             }
1899              
1900 1         3 $dm->{registrant} = $chg{registrant};
1901              
1902 1         4 $conts->{$chg{registrant}}{statuses}{linked}++;
1903              
1904 1 50       5 if ( $conts->{$chg{registrant}}{statuses}{ok} ) {
1905 1         4 delete $conts->{$chg{registrant}}{statuses}{ok};
1906 1         4 $conts->{$chg{registrant}}{statuses}{serverDeleteProhibited} = '+';
1907             }
1908             }
1909              
1910 8 100       22 $dm->{authInfo} = $chg{authInfo} if $chg{authInfo};
1911              
1912 8         17 my $svtrid = get_svtrid();
1913              
1914 8         27 return _min_answ( '1000', $cltrid );
1915             }
1916              
1917              
1918             sub domain_delete {
1919 4     4 0 8 my ( $obj, $body ) = @_;
1920              
1921 4         21 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
1922              
1923 4 50       11 return _fail_cltrid() unless $cltrid;
1924              
1925 4 50       24 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1926 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
1927             }
1928              
1929 4 50       23 unless ( $body =~ s|^\s+||s ) {
1930 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
1931             }
1932              
1933 4 50       25 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
1934 0         0 return _fail_body( 'XML schema validation failed: domain:delete', '2001', $cltrid );
1935             }
1936              
1937 4 50       26 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
1938 0         0 return _fail_body( 'XML schema validation failed: /domain:delete', '2001', $cltrid );
1939             }
1940              
1941 4         8 my $dname;
1942 4 50       16 if ( $body =~ m|([^<>]+)| ) {
1943 4         16 $dname = lc $1;
1944             }
1945             else {
1946 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}name': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.', '2001', $cltrid );
1947             }
1948              
1949 4 50       12 if ( $dname =~ /([^0-9a-z\.\-])/ ) {
1950 0         0 return _fail_body( "'$dname' is not a valid domain name: the following characters are not permitted: '$1'", '2004', $cltrid );
1951             }
1952              
1953 4 50       18 if ( $dname !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
1954 0         0 return _fail_body( "'$dname' is not a valid domain name: suffix ... does not exist", '2004', $cltrid );
1955             }
1956              
1957 4         24 my $srv_url = $obj->{sock};
1958 4         15 my $s = new IO::EPP::Test::Server( $srv_url );
1959 4         9 my $conts = $s->data->{conts};
1960 4         9 my $nss = $s->data->{nss};
1961 4         9 my $doms = $s->data->{doms};
1962              
1963 4 100       15 unless ( $doms->{$dname} ) {
1964 1         7 return _fail_body( "The domain '$dname' does not exist", '2303', $cltrid );
1965             }
1966              
1967 3         6 my $dm = $doms->{$dname};
1968              
1969 3 100       12 unless ( $dm->{reason} eq 'in use' ) {
1970 1         5 return _fail_body( "The domain '$dname' does not exist", '2303', $cltrid );
1971             }
1972              
1973 2         7 foreach my $st ( 'clientDeleteProhibited', 'serverDeleteProhibited', 'clientUpdateProhibited', 'serverUpdateProhibited' ) {
1974 8 50       20 if ( $dm->{statuses}{$st} ) {
1975 0         0 return _fail_body( "The domain name cannot be $statuses{$st} ($st).", '2304', $cltrid );
1976             }
1977             }
1978              
1979 2 100       7 if ( $dm->{hosts} ) {
1980 1         2 foreach my $h ( keys %{$dm->{hosts}} ) {
  1         5  
1981 2 100       8 if ( $nss->{$h}{statuses}{linked} ) {
1982 1         6 return _fail_body( "Domain host $h is linked to one or more domains.", '2305', $cltrid );
1983             }
1984             }
1985             }
1986              
1987 1 50       6 if ( $dm->{hosts} ) {
1988 0         0 foreach my $h ( keys %{$dm->{hosts}} ) {
  0         0  
1989 0         0 delete $nss->{$h};
1990             }
1991             }
1992              
1993 1         5 $conts->{$dm->{registrant}}{statuses}{linked}--;
1994              
1995 1 50       6 if ( $conts->{$dm->{registrant}}{statuses}{linked} <= 0 ) {
1996 1         4 delete $conts->{$dm->{registrant}}{statuses}{linked};
1997 1         3 delete $conts->{$dm->{registrant}}{statuses}{serverDeleteProhibited};
1998 1         4 $conts->{$dm->{registrant}}{statuses}{ok} = '+';
1999             }
2000              
2001 1         4 foreach my $t ( 'admin', 'tech', 'billing' ) {
2002 3         4 foreach my $c ( keys %{$dm->{$t}} ) {
  3         11  
2003 3         8 $conts->{$c}{statuses}{linked}--;
2004              
2005 3 100       9 if ( $conts->{$c}{statuses}{linked} <= 0 ) {
2006 1         3 delete $conts->{$c}{statuses}{linked};
2007 1         3 delete $conts->{$c}{statuses}{serverDeleteProhibited};
2008 1         3 $conts->{$c}{statuses}{ok} = '+';
2009             }
2010             }
2011             }
2012              
2013 1         3 foreach my $ns ( keys %{$dm->{nss}} ) {
  1         5  
2014 2         5 $nss->{$ns}{statuses}{linked}--;
2015              
2016 2 50       6 if ( $nss->{$ns}{statuses}{linked} <= 0 ) {
2017 2         4 delete $nss->{$ns}{statuses}{linked};
2018 2         3 delete $nss->{$ns}{statuses}{serverDeleteProhibited};
2019 2         5 $nss->{$ns}{statuses}{ok} = '+';
2020             }
2021             }
2022              
2023 1         3 undef $dm;
2024 1         8 delete $doms->{$dname};
2025              
2026 1         4 return _min_answ( '1000', $cltrid );
2027             }
2028              
2029              
2030             sub domain_transfer {
2031 7     7 0 15 my ( $obj, $body ) = @_;
2032              
2033 7         35 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
2034              
2035 7 50       71 return _fail_cltrid() unless $cltrid;
2036              
2037 7 50       43 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
2038 0         0 return _fail_body( 'XML schema validation failed: ', '2001', $cltrid );
2039             }
2040              
2041 7 50       40 unless ( $body =~ s|^\s+||s ) {
2042 0         0 return _fail_body( 'XML schema validation failed: Element '{uurn:ietf:params:xml:ns:epp-1.0}epp': No matching global declaration available for the validation root.', '2001', $cltrid );
2043             }
2044              
2045 7         28 my $op;
2046 7 50       35 if ( $body =~ // ) {
2047 7         22 $op = $1;
2048             }
2049             else {
2050 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:epp-1.0}transfer', attribute 'op': [facet 'enumeration'] The value 'xxxx' is not an element of the set {'approve', 'cancel', 'query', 'reject', 'request'}.', '2001', $cltrid );
2051             }
2052              
2053 7 50       40 unless ( $body =~ s|^\s+\s+]+>\s+||s ) {
2054 0         0 return _fail_body( 'XML schema validation failed: domain:transfer', '2001', $cltrid );
2055             }
2056              
2057 7 50       51 unless ( $body =~ s|\s+\s+\s+[^<>]+\s+\s+\s*$||s ) {
2058 0         0 return _fail_body( 'XML schema validation failed: /domain:transfer', '2001', $cltrid );
2059             }
2060              
2061 7         12 my $dname;
2062 7 50       26 if ( $body =~ m|([^<>]+)| ) {
2063 7         21 $dname = lc $1;
2064             }
2065             else {
2066 0         0 return _fail_body( 'XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}name': [facet 'minLength'] The value has a length of '0'; this underruns the allowed minimum length of '1'.', '2001', $cltrid );
2067             }
2068              
2069 7 50       23 if ( $dname =~ /([^0-9a-z\.\-])/ ) {
2070 0         0 return _fail_body( "'$dname' is not a valid domain name: the following characters are not permitted: '$1'", '2004', $cltrid );
2071             }
2072              
2073 7 50       25 if ( $dname !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
2074 0         0 return _fail_body( "'$dname' is not a valid domain name: suffix ... does not exist", '2004', $cltrid );
2075             }
2076              
2077 7         25 my $srv_url = $obj->{sock};
2078 7         27 my $s = new IO::EPP::Test::Server( $srv_url );
2079 7         18 my $doms = $s->data->{doms};
2080              
2081 7 100       18 unless ( $doms->{$dname} ) {
2082 1         5 return _fail_body( "The domain '$dname' cannot be found.", '2303', $cltrid );
2083             }
2084              
2085 6         12 my $dm = $doms->{$dname};
2086              
2087 6 50 66     28 if ( $op eq 'cancel' or $op eq 'reject' or $op eq 'approve' ) {
      66        
2088 2 100       8 unless ( $dm->{statuses}{pendingTransfer} ) {
2089 1         5 return _fail_body( 'There are no pending transfer requests for this object.', '2301', $cltrid );
2090             }
2091             }
2092              
2093 5 100       13 if ( $op eq 'query' ) {
2094 1 50       6 unless ( $dm->{statuses}{pendingTransfer} ) {
2095 0         0 return _fail_body( 'You cannot view the details of this transfer.', '2201', $cltrid );
2096             }
2097              
2098 1 50 33     8 unless ( $dm->{owner} eq $obj->{user} or $dm->{transfer}{new_owner} eq $obj->{user} ) {
2099 0         0 return _fail_body( 'You cannot view the details of this transfer.', '2201', $cltrid );
2100             }
2101              
2102 1         3 my $from = $dm->{owner};
2103 1         1 my $to = $dm->{transfer}{new_owner};
2104              
2105 1         3 my $exp_date = $dm->{exp_date};
2106 1         3 my $period = $dm->{transfer}{period};
2107 1         6 $exp_date =~ s/^(\d+)/$1+$period/e;
  1         6  
2108              
2109 1         4 my $tr_dt = $dm->{transfer}{tr_date};
2110 1         2 my $q_dt = $dm->{transfer}{q_date};
2111              
2112              
2113 1         8 return _ok_answ( qq|flowerlab.onlinepending$to$q_dt$from$tr_dt$exp_date|, $cltrid );
2114             }
2115              
2116 4 100       8 if ( $op eq 'request' ) {
2117 3 100       9 if ( $dm->{owner} eq $obj->{user} ) {
2118 1         5 return _fail_body( 'You are already the sponsor for this domain', '2304', $cltrid );
2119             }
2120              
2121 2         6 foreach my $st ( 'clientTransferProhibited', 'clientUpdateProhibited', 'serverTransferProhibited', 'serverUpdateProhibited' ) {
2122 8 50       20 if ( $dm->{statuses}{$st} ) {
2123 0         0 return _fail_body( "The domain name cannot be $statuses{$st} ($st).", '2304', $cltrid );
2124             }
2125             }
2126             }
2127              
2128 3 100       9 if ( $op eq 'cancel' ) {
2129 1 50       6 if ( $dm->{transfer}{new_owner} eq $obj->{user} ) {
2130 1         3 delete $dm->{transfer};
2131 1         4 delete $dm->{statuses}{pendingTransfer};
2132              
2133 1         6 return _min_answ( '1000', $cltrid );
2134             }
2135              
2136 0         0 return _fail_body( 'You cannot cancel this transfer.', '2201', $cltrid );
2137             }
2138              
2139 2 50       5 if ( $op eq 'reject' ) {
2140 0 0       0 if ( $dm->{owner} eq $obj->{user} ) {
2141 0         0 delete $dm->{transfer};
2142 0         0 delete $dm->{statuses}{pendingTransfer};
2143              
2144 0         0 return _min_answ( '1000', $cltrid );
2145             }
2146              
2147 0         0 return _fail_body( 'You cannot reject this transfer.', '2201', $cltrid );
2148             }
2149              
2150 2 50       7 if ( $op eq 'approve' ) {
2151 0 0       0 if ( $dm->{owner} eq $obj->{user} ) {
2152 0         0 $dm->{owner} = $dm->{transfer}{new_owner};
2153 0         0 my $p = $dm->{transfer}{period};
2154 0         0 $dm->{exp_date} =~ s/^(\d+)/$1+$p/e;
  0         0  
2155              
2156 0         0 delete $dm->{transfer};
2157 0         0 delete $dm->{statuses}{pendingTransfer};
2158              
2159 0         0 return _min_answ( '1000', $cltrid );
2160             }
2161              
2162 0         0 return _fail_body( 'You cannot approve this transfer.', '2201', $cltrid );
2163             }
2164              
2165 2         4 my $period = 1;
2166 2 50       11 if ( $body =~ m|(\d+)| ) {
2167 2         5 $period = $1;
2168              
2169 2 50       6 if ( $period > 9 ) {
2170 0         0 return _fail_body( "XML schema validation failed: Element '{urn:ietf:params:xml:ns:domain-1.0}period': [facet 'maxInclusive'] The value '$period' is greater than the maximum value allowed ('9').", '2001', $cltrid );
2171             }
2172             }
2173              
2174 2 50       13 if ( $body =~ m|authInfo.+([^<>]+).+authInfo|s ) {
2175 2         5 my $pw = $1;
2176              
2177 2 100       10 if ( $pw ne $dm->{authInfo} ) {
2178 1         4 return _fail_body( 'Invalid authorisation code.', '2202', $cltrid );
2179             }
2180             }
2181              
2182 1         3 my $from = $dm->{owner};
2183 1         2 my $to = $obj->{user};
2184              
2185 1         3 my $exp_date = $dm->{exp_date};
2186 1         7 $exp_date =~ s/^(\d+)/$1+$period/e;
  1         6  
2187 1         4 my ( $q_dt ) = get_dates();
2188 1         4 my $tr_dt = $q_dt;
2189 1         8 $tr_dt =~ s/^(\d+)/$1+1/e;
  1         5  
2190              
2191             $dm->{transfer} = {
2192             period => $period,
2193             new_owner => $obj->{user},
2194 1         8 q_date => $q_dt,
2195             tr_date => $tr_dt,
2196             };
2197              
2198 1         3 $dm->{statuses}{pendingTransfer} = '+';
2199              
2200 1         5 my $svtrid = get_svtrid();
2201              
2202 1         11 return qq|Command completed OK; action pending$dnamepending$to$q_dt$from$tr_dt$exp_date$cltrid$svtrid|;
2203             }
2204              
2205              
2206             sub poll {
2207 1     1 0 4 my ( $obj, $body ) = @_;
2208              
2209 1         6 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
2210              
2211 1 50       5 return _fail_cltrid() unless $cltrid;
2212              
2213 1         4 my $svtrid = get_svtrid();
2214              
2215 1         4 return qq|
2216            
2217            
2218            
2219             There are no messages for you!
2220            
2221            
2222             $cltrid
2223             $svtrid
2224            
2225            
2226             |;
2227             }
2228              
2229              
2230             sub logout {
2231 49     49 0 81 my ( $body ) = @_;
2232              
2233 49 50       416 unless ( $body =~ s|^<\?xml[^<>]+\?>\s+]+>||s ) {
2234 0         0 _fail_body( 'XML schema validation failed: ', '2001' );
2235             }
2236              
2237 49 50       269 unless ( $body =~ m|(.+?)|s ) {
2238 0         0 die "closed connection\n";
2239             }
2240              
2241 49         104 my $svtrid = get_svtrid();
2242              
2243 49         228 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|s;
2244              
2245 49 50       123 if ( $cltrid ) {
2246 49         103 return _min_answ( '1500', $cltrid );
2247             }
2248              
2249 0           return _fail_cltrid();
2250             }
2251              
2252             1;