File Coverage

blib/lib/IO/EPP/Test/VerisignCore.pm
Criterion Covered Total %
statement 730 881 82.8
branch 327 482 67.8
condition 99 185 53.5
subroutine 33 36 91.6
pod 0 20 0.0
total 1189 1604 74.1


line stmt bran cond sub pod time code
1             package IO::EPP::Test::VerisignCore;
2              
3             =encoding utf8
4              
5             =head1 NAME
6              
7             IO::EPP::Test::VerisignCore
8              
9             =head1 SYNOPSIS
10              
11             Call IO::EPP::Verisign with parameter "test_mode=1"
12              
13             =head1 DESCRIPTION
14              
15             Module for testing IO::EPP::Verisign,
16             emulates answers of Verisign Core Server
17              
18             =head1 AUTHORS
19              
20             Vadim Likhota
21              
22             =cut
23              
24 1     1   7 use Digest::MD5 qw(md5 md5_hex);
  1         2  
  1         55  
25              
26 1     1   6 use IO::EPP::Verisign;
  1         1  
  1         19  
27 1     1   5 use IO::EPP::Test::Server;
  1         2  
  1         30  
28              
29 1     1   6 use strict;
  1         1  
  1         19  
30 1     1   5 use warnings;
  1         1  
  1         31  
31              
32 1     1   6 no utf8; # !!!
  1         2  
  1         5  
33              
34             sub req {
35 166     166 0 329 my ( $obj, $out_data, $info ) = @_;
36              
37 166         229 my $in_data;
38              
39 166 100 100     3454 if ( !$out_data or $out_data =~ m|]+/>| ) {
    100 66        
    50 33        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    100 66        
    50 33        
40 29         52 $in_data = hello( $out_data );
41             }
42             elsif ( $out_data and $out_data =~ m|| ) {
43 28         60 $in_data = login( $out_data );
44             }
45             elsif ( $out_data and $out_data =~ m|
46 0         0 $in_data = contacts();
47             }
48             elsif ( $out_data and $out_data =~ m|
49 1         3 $in_data = host_check( $obj, $out_data );
50             }
51             elsif ( $out_data and $out_data =~ m|
52 9         27 $in_data = host_create( $obj, $out_data );
53             }
54             elsif ( $out_data and $out_data =~ m|
55 4         10 $in_data = host_info( $obj, $out_data );
56             }
57             elsif ( $out_data and $out_data =~ m|
58 13         35 $in_data = host_update( $obj, $out_data );
59             }
60             elsif ( $out_data and $out_data =~ m|
61 3         7 $in_data = host_delete( $obj, $out_data );
62             }
63             elsif ( $out_data and $out_data =~ m|
64 1         4 $in_data = domain_check( $obj, $out_data );
65             }
66             elsif ( $out_data and $out_data =~ m|
67 9         23 $in_data = domain_create( $obj, $out_data );
68             }
69             elsif ( $out_data and $out_data =~ m|
70 10         26 $in_data = domain_info( $obj, $out_data );
71             }
72             elsif ( $out_data and $out_data =~ m|
73 6         20 $in_data = domain_renew( $obj, $out_data );
74             }
75             elsif ( $out_data and $out_data =~ m|
76 19         50 $in_data = domain_update( $obj, $out_data );
77             }
78             elsif ( $out_data and $out_data =~ m|
79 6         18 $in_data = domain_delete( $obj, $out_data );
80             }
81             elsif ( $out_data and $out_data =~ m|| ) {
82 28         68 $in_data = logout( $out_data );
83             }
84             else {
85 0         0 print "FAIL $info!\n";
86 0         0 die $out_data;
87             }
88              
89 166         475 return $in_data;
90             }
91              
92              
93             our %statuses = (
94             clientHold => '+',
95             clientRenewProhibited => 'renewed',
96             clientDeleteProhibited => 'deleted',
97             clientUpdateProhibited => 'updated',
98             clientTransferProhibited => 'transfered',
99             serverHold => '+',
100             serverRenewProhibited => 'renewed',
101             serverDeleteProhibited => 'deleted',
102             serverUpdateProhibited => 'updated',
103             serverTransferProhibited => 'transfered',
104             );
105              
106              
107             sub get_date {
108 76     76 0 1758 my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time);
109              
110 76         251 $year += 1900;
111 76         121 $mon += 1;
112              
113 76         372 my $dt1 = sprintf( '%0004d-%02d-%02dT%02d:%02d:%02d.0Z', $year, $mon, $mday, $hour, $min, $sec );
114              
115 76         213 return $dt1;
116             }
117              
118             sub add_5d {
119 28     28 0 52 my ( $dt ) = @_;
120              
121 28         140 my ( $y, $m, $d ) = $dt =~ /^(\d{4})-(\d{2})-(\d{2})/;
122              
123 28         59 $d += 5;
124 28         43 $m += 0;
125              
126 28 50 0     118 if ( $m == 1 || $m == 3 || $m == 5 || $m == 7 || $m == 8 || $m == 10 || $m == 12 and $d > 31 ) {
      33        
127 0         0 $d -= 31;
128 0         0 $m++;
129             }
130              
131 28 50 33     151 if ( $m == 4 || $m == 6 || $m == 9 || $m == 11 and $d > 30 ) {
      33        
132 0         0 $d -= 30;
133 0         0 $m++;
134             }
135              
136 28 0 33     58 if ( $m == 2 && $y % 4 == 0 and $d > 29 ) {
      33        
137 0         0 $d -= 29;
138 0         0 $m++;
139             }
140              
141 28 0 33     53 if ( $m == 2 && $y % 4 != 0 and $d > 28 ) {
      33        
142 0         0 $d -= 28;
143 0         0 $m++;
144             }
145              
146 28 50       55 if ( $m == 13 ) {
147 0         0 $m = 1;
148 0         0 $y++;
149             }
150              
151 28 50       53 $d = '0'.$d if $d < 10;
152 28 50       60 $m = '0'.$m if $m < 10;
153              
154 28         153 $dt =~ s/^(\d{4}-\d{2}-\d{2})/$y-$m-$d/;
155              
156 28         86 return $dt;
157             }
158              
159             sub add_y {
160 2     2 0 6 my ( $dt, $y ) = @_;
161              
162 2         60 my ( $y0 ) = $dt =~ /^(\d{4})/;
163              
164 2         6 $y0 += $y;
165              
166 2         9 $dt =~ s/^(\d{4})/$y0/;
167              
168 2 50 33     9 if ( $dt =~ /^\d{4}-02-29/ and $y % 4 != 0 ) {
169 0         0 $dt =~ s/-02-29/-03-01/;
170             }
171              
172 2         6 return $dt;
173             }
174              
175              
176             sub get_svtrid {
177 138     138 0 328 my $i = int( rand( 9999999999 ) );
178 138         210 my $j = int( rand( 9999999 ) );
179 138         202 my $k = int( rand( 999999 ) );
180              
181 138         424 return $i . '-' . $j . $k;
182             }
183              
184              
185             sub _fail_schema {
186 0     0   0 my ( $err ) = @_;
187              
188 0         0 my $svtrid = get_svtrid();
189              
190 0         0 return qq|Command syntax errorXML Schema Validation Error: [SAXException] org.xml.sax.SAXException: EPPXMLErrorHandler.error() :
191             $err$svtrid|;
192             }
193              
194             sub _fail_schema2 {
195 3     3   8 my ( $err ) = @_;
196              
197 3         5 my $svtrid = get_svtrid();
198              
199 3         18 return qq|Command syntax errorXML Schema Validation Error: $err$svtrid|;
200             }
201              
202              
203             sub _fail_namestore {
204 0     0   0 my ( $cltrid ) = @_;
205              
206 0         0 my $svtrid = get_svtrid();
207              
208 0         0 return qq|Parameter value policy errorNameStore Extension not providedSpecified sub-product does not exist$cltrid$svtrid|
209             }
210              
211             sub _fail_answ {
212 29     29   62 my ( $cltrid, $code, $msg ) = @_;
213              
214 29         54 my $svtrid = get_svtrid();
215              
216 29         180 return qq|$msg$cltrid$svtrid|;
217             }
218              
219             sub _fail_answ_with_reason {
220 21     21   50 my ( $cltrid, $code, $msg, $reason ) = @_;
221              
222 21         43 my $svtrid = get_svtrid();
223              
224 21         160 return qq|$msg$reason$cltrid$svtrid|;
225             }
226              
227              
228             sub _ok_answ {
229 13     13   30 my ( $cltrid, $answ, $ext ) = @_;
230              
231 13 100       26 if ( $ext ) {
232 7         17 $ext = "$ext";
233             }
234             else {
235 6         11 $ext = '';
236             }
237              
238 13         23 my $svtrid = get_svtrid();
239              
240 13         114 return qq|Command completed successfully$answ$ext$cltrid$svtrid|;
241             }
242              
243             sub _ok_answ2 {
244 2     2   20 my ( $cltrid, $answ, $ext ) = @_;
245              
246 2 50       6 if ( $ext ) {
247 0         0 $ext = qq|
248            
249             $ext
250             |;
251             }
252             else {
253 2         5 $ext = '';
254             }
255              
256 2         4 my $svtrid = get_svtrid();
257              
258 2         15 return qq|
259            
260            
261             Command completed successfully
262            
263            
264             $answ
265             $ext
266            
267             $cltrid
268             $svtrid
269            
270            
271            
272             |;
273             }
274              
275             sub _min_answ {
276 13     13   26 my ( $cltrid ) = @_;;
277              
278 13         24 my $svtrid = get_svtrid();
279              
280 13         90 return qq|Command completed successfully$cltrid$svtrid|;
281             }
282              
283              
284             sub _check_dom_dates {
285 25     25   50 my ( $s, $dname ) = @_;
286              
287 25         54 my $dom = $s->data->{doms}{$dname};
288              
289 25         48 my $now = get_date();
290              
291 25 50 33     146 if ( $now gt $dom->{exp_date} and not $dom->{statuses}{pendingDelete} ) {
292             # check on autoRenew
293 0         0 my $end_auto_renew = add_5d( $dom->{exp_date} );
294              
295 0 0       0 if ( $end_auto_renew gt $now ) {
296 0         0 $dom->{exp_date} = add_y( $dom->{exp_date} );
297 0         0 print "updated exp_date\n";
298             }
299             }
300              
301 25 100       88 if ( $dom->{statuses}{pendingDelete} ) {
302             # check on redemption time
303 5         12 my $end_del_date = add_5d( add_5d( $dom->{del_date} ) );
304              
305 5 50       13 if ( $now gt $end_del_date ) {
306 0         0 delete $s->{doms}{$dname};
307             }
308              
309 5 100       17 if ( $dom->{statuses}{pendingRestore} ) {
310 2         7 my $end_rest_date = add_5d( $dom->{upd_date} );
311              
312 2 50       8 if ( $now gt $end_rest_date ) {
313 0         0 delete $dom->{statuses}{pendingRestore};
314             }
315             }
316             }
317             }
318              
319              
320             sub hello {
321 29     29 0 57 my $dt = get_date();
322              
323 29         183 return qq|VeriSign Com/Net EPP Registration Server$dt1.0enurn:ietf:params:xml:ns:domain-1.0urn:ietf:params:xml:ns:contact-1.0urn:ietf:params:xml:ns:host-1.0http://www.verisign.com/epp/registry-1.0http://www.verisign.com/epp/lowbalance-poll-1.0http://www.verisign.com/epp/rgp-poll-1.0urn:ietf:params:xml:ns:secDNS-1.1http://www.verisign.com/epp/whoisInf-1.0http://www.verisign.com/epp/idnLang-1.0urn:ietf:params:xml:ns:coa-1.0http://www.verisign-grs.com/epp/namestoreExt-1.1http://www.verisign.com/epp/sync-1.0http://www.verisign.com/epp/relatedDomain-1.0urn:ietf:params:xml:ns:verificationCode-1.0urn:ietf:params:xml:ns:launch-1.0urn:ietf:params:xml:ns:rgp-1.0urn:ietf:params:xml:ns:changePoll-1.0|;
324             }
325              
326              
327             sub login {
328 28     28 0 53 my ( $body ) = @_;
329              
330 28 50       194 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
331 0         0 return _fail_schema( q|Line....: 1
332             Column..: 2
333             Message.: : The markup in the document preceding the root element must be well-formed.| );
334             }
335              
336 28 50       196 unless ( $body =~ s|^\s+||s ) {
337 0         0 return _fail_schema( q|Line....: 2
338             Column..: 173
339             Message.: : cvc-complex-type.3.2.2: Attribute 'xxx' is not allowed to appear in element 'epp'.| );
340             }
341              
342 28 50       1008 unless ( $body =~ s|\s*\s*||s ) {
343 0         0 return _fail_schema( q|Line....: 11111
344             Column..: 6
345             Message.: : The end-tag for element type "epp" must end with a '>' delimiter.| );
346             }
347              
348 28 50       129 unless ( $body =~ s|\s*||s ) {
349 0         0 return _fail_schema( q|Line....: 3
350             Column..: 12
351             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'xxxxxx'. One of '{"urn:ietf:params:xml:ns:epp-1.0":greeting, "urn:ietf:params:xml:ns:epp-1.0":hello, "urn:ietf:params:xml:ns:epp-1.0":command, "urn:ietf:params:xml:ns:epp-1.0":response, "urn:ietf:params:xml:ns:epp-1.0":extension}' is expected.| );
352             }
353              
354 28 50       931 unless ( $body =~ s|\s*||s ) {
355 0         0 return _fail_schema( q|Line....: 22222
356             Column..: 11
357             Message.: : The end-tag for element type "command" must end with a '>' delimiter.| );
358             }
359              
360 28 50       121 unless ( $body =~ s|\s*||s ) {
361 0         0 return _fail_schema( q|Line....: 4
362             Column..: 11
363             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'xxxxxx'. One of '{"urn:ietf:params:xml:ns:epp-1.0":check, "urn:ietf:params:xml:ns:epp-1.0":create, "urn:ietf:params:xml:ns:epp-1.0":delete, "urn:ietf:params:xml:ns:epp-1.0":info, "urn:ietf:params:xml:ns:epp-1.0":login, "urn:ietf:params:xml:ns:epp-1.0":logout, "urn:ietf:params:xml:ns:epp-1.0":poll, "urn:ietf:params:xml:ns:epp-1.0":renew, "urn:ietf:params:xml:ns:epp-1.0":transfer, "urn:ietf:params:xml:ns:epp-1.0":update}' is expected.| );
364             }
365              
366 28         198 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|;
367              
368 28 50       66 unless ( $cltrid ) {
369 0         0 return _fail_schema( q|Line....: 11111
370             Column..: 22222
371             Message.: : cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '3' for type 'trIDStringType'.| );
372             }
373              
374 28 50       834 unless ( $body =~ s|\s*.+$||s ) {
375 0         0 return _fail_schema( q|Line....: 27
376             Column..: 10
377             Message.: : The end-tag for element type "login" must end with a '>' delimiter.| );
378             }
379              
380 28         103 my ( $login ) = $body =~ m|([0-9A-Za-z_\-]+)|;
381              
382 28 50       56 return q|Line....: 5
383             Column..: 17
384             Message.: : cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '3' for type 'clIDType'.|
385             unless $login;
386              
387 28         92 my ( $pass ) = $body =~ m|([0-9A-Za-z!\@\$\%*_.:=+?#,"'\-{}\[\]\(\)]+)|;
388              
389 28 50 33     117 if ( !$pass || length( $pass ) < 6 ) {
390 0         0 return q|Line....: 6
391             Column..: 13
392             Message.: : cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '6' for type 'pwType'.|;
393             }
394              
395 28         57 my $svtrid = get_svtrid();
396              
397 28 50       58 if ( $pass eq 'fail-pass' ) {
398 0         0 return qq|Authentication error$cltrid$svtrid|;
399             }
400              
401 28         89 return qq|Welcome user.$cltrid$svtrid|;
402             }
403              
404              
405             sub contacts {
406 0     0 0 0 my $svtrid = get_svtrid();
407              
408 0         0 return qq|Parameter value policy errorSub product dotCOM does NOT support contact11111$svtrid|;
409             }
410              
411              
412             sub _check_body {
413 81     81   144 my ( $body_ref ) = @_;
414              
415 81 50       533 unless ( $$body_ref =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
416 0         0 return _fail_schema( q|Line....: 1
417             Column..: 2
418             Message.: : The markup in the document preceding the root element must be well-formed.| );
419             }
420              
421 81 50       568 unless ( $$body_ref =~ s|^\s+||s ) {
422 0         0 return _fail_schema( q|Line....: 2
423             Column..: 173
424             Message.: : cvc-complex-type.3.2.2: Attribute 'xxx' is not allowed to appear in element 'epp'.| );
425             }
426              
427 81 50       1691 unless ( $$body_ref =~ s|\s*\s*||s ) {
428 0         0 return _fail_schema( q|Line....: 11111
429             Column..: 6
430             Message.: : The end-tag for element type "epp" must end with a '>' delimiter.| );
431             }
432              
433 81 50       362 unless ( $$body_ref =~ s|\s*||s ) {
434 0         0 return _fail_schema( q|Line....: 3
435             Column..: 12
436             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'xxxxxx'. One of '{"urn:ietf:params:xml:ns:epp-1.0":greeting, "urn:ietf:params:xml:ns:epp-1.0":hello, "urn:ietf:params:xml:ns:epp-1.0":command, "urn:ietf:params:xml:ns:epp-1.0":response, "urn:ietf:params:xml:ns:epp-1.0":extension}' is expected.| );
437             }
438              
439 81 50       1528 unless ( $$body_ref =~ s|\s*||s ) {
440 0         0 return _fail_schema( q|Line....: 22222
441             Column..: 11
442             Message.: : The end-tag for element type "command" must end with a '>' delimiter.| );
443             }
444              
445 81         435 my ( $cltrid ) = $$body_ref =~ m|([0-9A-Za-z\-]+)|;
446              
447 81 50       179 if ( $cltrid ) {
448 81         1427 $$body_ref =~ s|\s*[^<>]+\s*||s
449             }
450             else {
451 0         0 return _fail_schema( q|Line....: 11111
452             Column..: 22222
453             Message.: : cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '3' for type 'trIDStringType'.| );
454             }
455              
456 81 50       386 unless ( $$body_ref =~ m{dot(COM|NET|EDU)} ) {
457 0         0 return _fail_namestore( $cltrid );
458             }
459              
460 81 50       1224 unless ( $$body_ref =~ s|\s*]+>.+||s ) {
461 0         0 return _fail_namestore( $cltrid );
462             }
463              
464 81         133 my $cmd;
465 81 50       382 if ( $$body_ref =~ s/<(check|create|info|renew|update|delete)>\s*//s ) {
466 81         238 $cmd = $1;
467             }
468             else {
469 0         0 return _fail_schema( q|Line....: 4
470             Column..: 11
471             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'xxxxxx'. One of '{"urn:ietf:params:xml:ns:epp-1.0":check, "urn:ietf:params:xml:ns:epp-1.0":create, "urn:ietf:params:xml:ns:epp-1.0":delete, "urn:ietf:params:xml:ns:epp-1.0":info, "urn:ietf:params:xml:ns:epp-1.0":login, "urn:ietf:params:xml:ns:epp-1.0":logout, "urn:ietf:params:xml:ns:epp-1.0":poll, "urn:ietf:params:xml:ns:epp-1.0":renew, "urn:ietf:params:xml:ns:epp-1.0":transfer, "urn:ietf:params:xml:ns:epp-1.0":update}' is expected.| );
472             }
473              
474 81 50       1499 unless ( $$body_ref =~ s|\s*.+$||s ) {
475 0         0 return _fail_schema( qq|Line....: 22222
476             Column..: 10
477             Message.: : The end-tag for element type "$cmd" must end with a '>' delimiter.| );
478             }
479              
480 81         144 my $type;
481 81 50       1426 if ( $$body_ref =~ s/\s*<(host|domain):$cmd[^<>]+>\s*//s ) {
482 81         194 $type = $1;
483             }
484             else {
485 0         0 return _fail_schema( q|Line....: 5
486             Column..: 128
487             Message.: : cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'xxxxxx'.| );
488             }
489              
490 81 50       1051 unless ( $$body_ref =~ s|\s*\s*||s ) {
491 0         0 return _fail_schema( qq|Line....: 7
492             Column..: 16
493             Message.: : The end-tag for element type "$type:$cmd" must end with a '>' delimiter.| );
494             }
495              
496 81         298 return ( 0, $cltrid );
497             }
498              
499              
500             sub host_check {
501 1     1 0 2 my ( $obj, $body ) = @_;
502              
503 1         3 my @chb = _check_body( \$body );
504              
505 1         1 my $cltrid;
506              
507 1 50       3 if ( $chb[0] ) {
508 0         0 return @chb;
509             }
510             else {
511 1         2 $cltrid = $chb[1];
512             }
513              
514 1         23 my ( @hosts ) = $body =~ m|([^<>]+)|g;
515              
516 1 50       3 unless ( scalar @hosts ) {
517 0         0 _fail_schema( q|Line....: 7
518             Column..: 17
519             Message.: : cvc-complex-type.2.4.b: The content of element 'host:check' is not complete. One of '{"urn:ietf:params:xml:ns:host-1.0":name}' is expected.| );
520             }
521              
522 1         3 my $srv_url = $obj->{sock};
523 1         6 my $s = new IO::EPP::Test::Server( $srv_url );
524 1         2 my $answ_list = '';
525 1         2 foreach my $row ( @hosts ) {
526 5         21 my ( $ns ) = $row =~ m|([^<>]+)|;
527 5         11 $ns = lc $ns;
528              
529 5         7 my $avail = 1;
530              
531 5 50       13 if ( $s->data->{nss}{$ns} ) {
    100          
532 0         0 $avail = 0;
533             }
534             elsif ( $ns !~ /^[0-9a-z\.\-]+\.[0-9a-z\-]+$/ ) {
535 2         3 $avail = 0;
536             }
537              
538 5         25 $answ_list .= qq|$ns|;
539             }
540              
541 1         4 return _ok_answ( $cltrid, qq|$answ_list| );
542             }
543              
544              
545             sub host_create {
546 9     9 0 16 my ( $obj, $body ) = @_;
547              
548 9         55 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
549              
550 9         27 my @chb = _check_body( \$body );
551              
552 9         17 my $cltrid;
553              
554 9 50       18 if ( $chb[0] ) {
555 0         0 return @chb;
556             }
557             else {
558 9         13 $cltrid = $chb[1];
559             }
560              
561 9         13 my ( $ns, $dname );
562              
563 9 50       34 if ( $body =~ m|([^<>]+)| ) {
564 9         24 $ns = lc $1;
565             }
566             else {
567 0         0 return _fail_schema( q|Line....: 6
568             Column..: 17
569             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'host:name'. One of '{"urn:ietf:params:xml:ns:host-1.0":name}' is expected.| );
570             }
571              
572 9 100       36 unless ( $ns =~ /^[0-9a-z][0-9a-z\-\.]*[0-9a-z]\.[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
573 1         3 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
574             }
575              
576             # need error for unknown tld: _fail_answ( $cltrid, '2305', 'Object association prohibits operation' )
577              
578 8         17 my $srv_url = $obj->{sock};
579 8         32 my $s = new IO::EPP::Test::Server( $srv_url );
580              
581 8         20 my $nss = $s->data->{nss};
582 8         17 my $doms = $s->data->{doms};
583              
584 8 100       21 if ( $nss->{$ns} ) {
585 2 100       7 if ( $nss->{$ns}{owner} eq $obj->{user} ) {
586 1         3 return _fail_answ( $cltrid, '2302', 'Object exists' );
587             }
588             else {
589 1         2 return _fail_answ( $cltrid, '2201', 'Authorization error' );
590             }
591             }
592              
593 6         26 my ( $tld ) = $ns =~ /\.([0-9a-z\-]+)$/;
594              
595 6         11 my @v4;
596             my @v6;
597              
598 6 100       18 if ( $tld =~ /^(com|net|edu)$/ ) {
599             # need ip & Co
600 5         19 ( $dname ) = $ns =~ /\.([0-9a-z\-]+\.[a-z]+)$/;
601              
602 5 100       13 unless ( $doms->{$dname} ) {
603 1         3 return _fail_answ( $cltrid, '2305', 'Object association prohibits operation' );
604             }
605              
606 4 50       13 if ( $doms->{$dname}{owner} ne $obj->{user} ) {
607 0         0 return _fail_answ( $cltrid, '2201', 'Authorization error' );
608             }
609              
610 4         14 @v4 = $body =~ m|([^<>]+)|g;
611 4         12 @v6 = $body =~ m|([^<>]+)|g;
612              
613 4 100       13 if ( scalar( @v4 ) + scalar( @v6 ) == 0 ) {
614 1         3 return _fail_answ( $cltrid, '2003', 'Required parameter missing' );
615             }
616              
617 3         7 foreach my $v ( @v4 ) {
618 2 50       10 unless ( $v =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
619 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
620             }
621             }
622 3         6 foreach my $v ( @v6 ) {
623 2 100       9 unless ( $v =~ /^[0-9a-z:]{1,29}$/ ) {
624 1         3 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
625             }
626             }
627             }
628              
629 3         6 my $cre_date = get_date();
630              
631 3         17 my $roid = md5_hex($ns.$cre_date);
632 3         24 $roid =~ s/[a-f]//ig;
633              
634 3         6 my %v4;
635 3         11 $v4{$_} = '+' for @v4;
636 3         4 my %v6;
637 3         7 $v6{$_} = '+' for @v6;
638              
639 3         25 $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 => $roid . '_HOST_CNE-VRSN' };
640              
641 3 100       10 if ( $dname ) {
642 2         7 $doms->{$dname}{hosts}{$ns} = '+';
643             }
644              
645 3         11 return _ok_answ( $cltrid, qq|$ns$cre_date| );
646             }
647              
648              
649              
650             sub host_info {
651 4     4 0 7 my ( $obj, $body ) = @_;
652              
653 4         10 my @chb = _check_body( \$body );
654              
655 4         8 my $cltrid;
656              
657 4 50       10 if ( $chb[0] ) {
658 0         0 return @chb;
659             }
660             else {
661 4         6 $cltrid = $chb[1];
662             }
663              
664 4         6 my $ns;
665              
666 4 50       16 if ( $body =~ m|([^<>]+)| ) {
667 4         13 $ns = lc $1;
668             }
669             else {
670 0         0 return _fail_schema( q|Line....: 6
671             Column..: 17
672             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'host:name'. One of '{"urn:ietf:params:xml:ns:host-1.0":name}' is expected.| );
673             }
674              
675 4 100       17 unless ( $ns =~ /^[0-9a-z][0-9a-z\-\.]*[0-9a-z]\.[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
676 1         3 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
677             }
678              
679             # need error for unknown tld: _fail_answ( $cltrid, '2305', 'Object association prohibits operation' )
680              
681 3         6 my $srv_url = $obj->{sock};
682 3         13 my $s = new IO::EPP::Test::Server( $srv_url );
683              
684 3 100       8 unless ( $s->data->{nss}{$ns} ) {
685 1         3 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
686             }
687              
688 2         5 my $host = $s->data->{nss}{$ns};
689              
690 2 100       7 if ( $host->{owner} ne $obj->{user} ) {
691 1         3 return _fail_answ( $cltrid, '2201', 'Authorization error' );
692             }
693              
694 1         3 my $answ = '';
695 1         3 $answ .= "$ns";
696 1         3 $answ .= "" . $host->{roid} . "";
697 1         2 for my $st ( keys %{$host->{statuses}} ) {
  1         4  
698 1         3 $answ .= qq||;
699             }
700 1         2 for my $ip4 ( sort keys %{$host->{addr_v4}} ) {
  1         8  
701 1         3 $answ .= qq|$ip4|;
702             }
703 1         2 for my $ip6 ( sort keys %{$host->{addr_v6}} ) {
  1         2  
704 1         4 $answ .= qq|$ip6|;
705             }
706 1         2 $answ .= "$$host{owner}";
707 1         3 $answ .= "$$host{creater}";
708 1         3 $answ .= "$$host{cre_date}";
709 1 50       3 if ( $host->{updater} ) {
710 0         0 $answ .= "$$host{updater}";
711             }
712             else {
713 1         2 $answ .= "$$host{creater}";
714             }
715 1 50       3 if ( $host->{upd_date} ) {
716 0         0 $answ .= "$$host{upd_date}";
717             }
718             else {
719 1         3 $answ .= "$$host{cre_date}";
720             }
721 1         2 $answ .= '';
722              
723 1         2 return _ok_answ( $cltrid, $answ );
724             }
725              
726              
727              
728             sub host_update {
729 13     13 0 25 my ( $obj, $body ) = @_;
730              
731 13         29 my @chb = _check_body( \$body );
732              
733 13         24 my $cltrid;
734              
735 13 50       27 if ( $chb[0] ) {
736 0         0 return @chb;
737             }
738             else {
739 13         17 $cltrid = $chb[1];
740             }
741              
742 13         22 my $ns;
743              
744 13 50       44 if ( $body =~ m|([^<>]+)| ) {
745 13         36 $ns = lc $1;
746             }
747             else {
748 0         0 return _fail_schema( q|Line....: 6
749             Column..: 17
750             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'host:name'. One of '{"urn:ietf:params:xml:ns:host-1.0":name}' is expected.| );
751             }
752              
753 13 50       47 unless ( $ns =~ /^[0-9a-z][0-9a-z\-\.]*[0-9a-z]\.[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
754 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
755             }
756              
757             # need error for unknown tld: _fail_answ( $cltrid, '2305', 'Object association prohibits operation' )
758              
759 13         33 my $srv_url = $obj->{sock};
760 13         50 my $s = new IO::EPP::Test::Server( $srv_url );
761              
762 13 100       29 unless ( $s->data->{nss}{$ns} ) {
763 1         3 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
764             }
765              
766 12         36 my $host = $s->data->{nss}{$ns};
767              
768 12 100       32 if ( $host->{owner} ne $obj->{user} ) {
769 1         3 return _fail_answ( $cltrid, '2201', 'Authorization error' );
770             }
771              
772             # first check data
773 11         23 my ( @a4, @a6, @d4, @d6, @ast, @dst );
774              
775 11         21 for my $act ( 'add', 'rem' ) {
776 17 100       246 if ( $body =~ m|(.+?)|s ) {
777 12         35 my $ab = $1;
778              
779 12         36 my @v4 = $ab =~ m|([^<>]+)|g;
780 12         29 my @v6 = $ab =~ m|([^<>]+)|g;
781              
782 12         24 foreach my $v ( @v4 ) {
783 5 50       20 unless ( $v =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
784 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
785             }
786              
787 5 100       13 if ( $act eq 'add' ) {
788 2 100       7 if ( $host->{addr_v4}{$v} ) {
789 1         6 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$v addr is already associated" );
790             }
791              
792 1         3 push @a4, $v;
793             }
794             else {
795 3 100       9 unless ( $host->{addr_v4}{$v} ) {
796 1         5 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$v addr not found" );
797             }
798              
799 2         5 push @d4, $v;
800             }
801             }
802              
803 10         16 foreach my $v ( @v6 ) {
804 2 100       8 unless ( $v =~ /^[0-9a-f:]{1,29}$/ ) {
805 1         3 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
806             }
807              
808 1 50       6 if ( $act eq 'add' ) {
809 0 0       0 if ( $host->{addr_v6}{$v} ) {
810 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$v addr is already associated" );
811             }
812              
813 0         0 push @a6, $v;
814             }
815             else {
816 1 50       5 unless ( $host->{addr_v6}{$v} ) {
817 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$v addr not found" );
818             }
819              
820 1         3 push @d6, $v;
821             }
822             }
823              
824 9         29 my @st = $ab =~ m||g;
825              
826 9         21 foreach my $st ( @st ) {
827 6 100       25 if ( $st !~ /^(clientDeleteProhibited|clientUpdateProhibited|linked|ok|pendingCreate|pendingDelete|pendingTransfer|pendingUpdate| serverDeleteProhibited|serverUpdateProhibited)$/ ) {
828 1         5 return _fail_schema2( qq|Line: 8, Column: 46, Message: cvc-enumeration-valid: Value '$st' is not facet-valid with respect to enumeration '[clientDeleteProhibited, clientUpdateProhibited, linked, ok, pendingCreate, pendingDelete, pendingTransfer, pendingUpdate, serverDeleteProhibited, serverUpdateProhibited]'. It must be a value from the enumeration.| );
829             }
830              
831 5 100       19 if ( $st !~ /^(clientDeleteProhibited|clientUpdateProhibited)$/ ) {
832 1         3 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "request contains no actual object updates" );
833             }
834              
835 4 100       11 if ( $act eq 'add' ) {
836 2 100       5 if ( $host->{statuses}{$st} ) {
837 1         7 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$st status is already associated" );
838             }
839              
840 1         4 push @ast, $st;
841             }
842             else {
843 2 100       7 unless ( $host->{statuses}{$st} ) {
844 1         5 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$st status not found" );
845             }
846              
847 1         4 push @dst, $st;
848             }
849             }
850             }
851             }
852              
853 4 100 100     20 if ( ( scalar( @a4 ) + scalar( @a6 ) ) == 0 and ( scalar( @d4 ) + scalar( @d6 ) > 0 ) ) {
854 1 50       1 if ( ( scalar( @d4 ) + scalar( @d6 ) ) == ( scalar( keys %{$host->{addr_v4}} ) + scalar( keys %{$host->{addr_v6}} ) ) ) {
  1         3  
  1         3  
855 1         7 return _fail_answ( $cltrid, '2003', 'Required parameter missing' );
856             }
857             }
858              
859 3 50 33     16 if ( $body =~ m|| or $body =~ m|| ) {
860 0         0 return _fail_schema2( qq|Line: 13, Column: 16, Message: cvc-complex-type.2.4.b: The content of element 'host:chg' is not complete. One of '{"urn:ietf:params:xml:ns:host-1.0":name}' is expected.| )
861             }
862              
863             # TODO: chg name
864             =rem
865             2019-12-29 05:01:50 SRS::Comm::Provider::EPP::Base::epp_log:95
866             pid: 2559
867             update_ns request:
868            
869            
870            
871            
872            
873             ns2.medinavai.com
874             ns2.medinavai.com.deletednss.com
875            
876            
877            
878             879             1.1 namestoreExt-1.1.xsd">
880             dotCOM
881            
882            
883             25d436e52c40ae318b831e52350d8352
884            
885            
886              
887             2019-12-29 05:01:50 SRS::Comm::Provider::EPP::Base::epp_log:95
888             pid: 2559
889             req_time: 0.1559
890             update_ns answer:
891             Command completed successfully25d436e52c40ae318b831e52350d8352
892             vTRID>4521195083-1577584910758-20475271877
893             =cut
894             # after update
895              
896             # only first add, after delete: so the registy works
897 3         8 $host->{addr_v4}{$_} = '+' for @a4;
898              
899 3         4 $host->{addr_v6}{$_} = '+' for @a6;
900              
901 3         7 $host->{statuses}{$_} = '+' for @ast;
902              
903 3         7 delete $host->{addr_v4}{$_} for @d4;
904              
905 3         5 delete $host->{addr_v6}{$_} for @d6;
906              
907 3         7 delete $host->{statuses}{$_} for @dst;
908              
909 3         7 return _min_answ( $cltrid );
910             }
911              
912              
913             sub host_delete {
914 3     3 0 6 my ( $obj, $body ) = @_;
915              
916 3         7 my @chb = _check_body( \$body );
917              
918 3         5 my $cltrid;
919              
920 3 50       7 if ( $chb[0] ) {
921 0         0 return @chb;
922             }
923             else {
924 3         4 $cltrid = $chb[1];
925             }
926              
927 3         5 my $ns;
928              
929 3 50       12 if ( $body =~ m|([^<>]+)| ) {
930 3         8 $ns = lc $1;
931             }
932             else {
933 0         0 return _fail_schema( q|Line....: 6
934             Column..: 17
935             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'host:name'. One of '{"urn:ietf:params:xml:ns:host-1.0":name}' is expected.| );
936             }
937              
938 3 50       13 unless ( $ns =~ /^[0-9a-z][0-9a-z\-\.]*[0-9a-z]\.[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
939 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
940             }
941              
942             # need error for unknown tld: _fail_answ( $cltrid, '2305', 'Object association prohibits operation' )
943              
944 3         8 my $srv_url = $obj->{sock};
945 3         11 my $s = new IO::EPP::Test::Server( $srv_url );
946              
947 3 100       17 unless ( $s->data->{nss}{$ns} ) {
948 1         3 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
949             }
950              
951 2         5 my $host = $s->data->{nss}{$ns};
952              
953 2 100       6 if ( $host->{owner} ne $obj->{user} ) {
954 1         3 return _fail_answ( $cltrid, '2201', 'Authorization error' );
955             }
956              
957 1 50       4 if ( $host->{statuses}{linked} ) {
958 0         0 return _fail_answ( $cltrid, '2305', 'Object association prohibits operation' );
959             }
960              
961 1         2 my $dname;
962              
963 1 50       6 if ( $ns =~ /\b(com|net|edu)$/ ) {
964 1         5 ( $dname ) = $ns =~ /\.([0-9a-z\-]+\.[a-z]+)$/;
965              
966 1         3 my $doms = $s->data->{doms};
967              
968 1         3 delete $doms->{$dname}{hosts}{$ns};
969             }
970              
971 1         3 delete $s->data->{nss}{$ns};
972              
973 1         2 my $svtrid = get_svtrid();
974              
975 1         3 return _min_answ( $cltrid );
976             }
977              
978              
979             sub domain_check {
980 1     1 0 2 my ( $obj, $body ) = @_;
981              
982 1         3 my @chb = _check_body( \$body );
983              
984 1         3 my $cltrid;
985              
986 1 50       4 if ( $chb[0] ) {
987 0         0 return @chb;
988             }
989             else {
990 1         2 $cltrid = $chb[1];
991             }
992              
993 1         11 my ( @domains ) = $body =~ m|([^<>]+)|g;
994              
995 1 50       4 unless ( scalar @domains ) {
996 0         0 return _fail_body( 'domain:name' );
997             }
998              
999 1         3 my $srv_url = $obj->{sock};
1000 1         5 my $s = new IO::EPP::Test::Server( $srv_url );
1001 1         3 my $doms = $s->data->{doms};
1002              
1003 1         3 my $answ_list = '';
1004 1         2 foreach my $row ( @domains ) {
1005 6         22 my ( $dm ) = $row =~ m|([^<>]+)|;
1006              
1007 6         10 my ( $avail, $reason );
1008              
1009 6 50       38 if ( $doms->{$dm} ) {
    100          
    50          
    100          
1010 0         0 $avail = $doms->{$dm}{avail};
1011 0         0 $reason = $doms->{$dm}{reason};
1012             }
1013             elsif ( $dm !~ /^[0-9-a-z\-]+\.[a-z]+$/ ) {
1014 1         2 $avail = 0;
1015 1         11 $reason = 'Invalid Domain Name';
1016             }
1017             elsif ( $dm =~ /^reg*\.(com|net|edu)$/ ) { # reged
1018 0         0 $avail = 0;
1019 0         0 $reason = 'Domain exists';
1020             }
1021             elsif ( $dm =~ /\.(com|net|edu)$/ ) {
1022 4 100       12 $avail = int( rand( 10 ) ) > 1 ? 1 : 0; # 10% are not avail
1023              
1024 4 100       8 if ( $avail ) {
1025 3         5 $reason = '';
1026             }
1027             else {
1028 1         2 $reason = 'Domain exists';
1029              
1030 1         3 $doms->{$dm}{avail} = 0;
1031 1         3 $doms->{$dm}{reason} = 'Domain exists';
1032             }
1033             }
1034             else {
1035 1         2 $avail = 0;
1036 1         2 $reason = 'Not an authoritative TLD';
1037             }
1038              
1039 6         20 $answ_list .= qq|$dm$reason|;
1040             }
1041              
1042 1         13 return _ok_answ( $cltrid, qq|$answ_list| );
1043             }
1044              
1045              
1046             sub domain_create {
1047 9     9 0 16 my ( $obj, $body ) = @_;
1048              
1049 9         54 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1050 9         28 my ( $lang ) = $body =~ m|]+">([A-Z]{3})|;
1051              
1052 9         24 my @chb = _check_body( \$body );
1053              
1054 9         16 my $cltrid;
1055              
1056 9 50       19 if ( $chb[0] ) {
1057 0         0 return @chb;
1058             }
1059             else {
1060 9         14 $cltrid = $chb[1];
1061             }
1062              
1063 9         15 my $dname;
1064 9 50       30 if ( $body =~ m|([^<>]*)| ) {
1065 9         26 $dname = lc $1;
1066             }
1067             else {
1068 0         0 return _fail_schema2( q|Line: 8, Column: 21, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":names}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":name}' is expected.| );
1069             }
1070              
1071 9 50       20 unless ( $dname ) {
1072 0         0 return _fail_schema2( q|Line: 8, Column: 34, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| );
1073             }
1074              
1075 9 100       32 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1076 1         4 return _fail_answ_with_reason( $cltrid, '2005', 'Parameter value syntax error', 'Domain name contains an invalid DNS character' );
1077             }
1078              
1079 8         27 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1080              
1081 8 100       24 if ( $tld ne lc( $subProduct ) ) {
1082 2         6 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Subproduct ID does not match the domain TLD' );
1083             }
1084              
1085 6         10 my $period;
1086 6 50       20 if ( $body =~ m|([^<>]*)| ) {
1087 6         14 $period = $1;
1088             }
1089             else {
1090 0         0 return _fail_schema2( q|Line: 9, Column: 32, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":xxxxxx}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":period, "urn:ietf:params:xml:ns:domain-1.0":ns, "urn:ietf:params:xml:ns:domain-1.0":registrant, "urn:ietf:params:xml:ns:domain-1.0":contact, "urn:ietf:params:xml:ns:domain-1.0":authInfo}' is expected.| );
1091             }
1092              
1093 6 50 33     30 unless ( $period and $period =~ /^[0-9]+$/) {
1094 0         0 return _fail_schema2( qq|Line: 9, Column: 47, Message: cvc-datatype-valid.1.2.1: '$period' is not a valid value for 'integer'.| );
1095             }
1096              
1097 6 50       17 if ( $period < 1 ) {
1098 0         0 return _fail_schema2( qq|Line: 9, Column: 48, Message: cvc-minInclusive-valid: Value '$period' is not facet-valid with respect to minInclusive '1' for type 'pLimitType'.| );
1099             }
1100              
1101 6 50       14 if ( $period > 99 ) {
1102 0         0 return _fail_schema2( qq|Line: 9, Column: 50, Message: cvc-maxInclusive-valid: Value '$period' is not facet-valid with respect to maxInclusive '99' for type 'pLimitType'.| );
1103             }
1104              
1105 6 100       13 if ( $period > 10 ) {
1106 1         5 return _fail_answ( $cltrid, '2306', 'Parameter value policy error' );
1107             }
1108              
1109 5         8 my @nss;
1110 5 100       16 if ( $body =~ m|(.+)|s ) {
1111 2         5 my $nss = $1;
1112              
1113 2         12 my @rows = $body =~ m|(.*)|g;
1114              
1115 2         5 foreach my $row ( @rows ) {
1116 4 50       9 unless ( $row ) {
1117 0         0 return _fail_schema2( q|12, Column: 42, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| ) ;
1118             }
1119              
1120 4 50       19 if ( $row !~ /^([0-9a-z][0-9a-z\-]*[0-9a-z]\.)+[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
1121 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1122             }
1123              
1124 4         10 push @nss, $row;
1125             }
1126             }
1127              
1128 5         8 my $authinfo;
1129 5 50       21 if ( $body =~ m|(.*)|s ) {
1130 5         11 my $row = $1;
1131              
1132 5 50 33     25 if ( $row && $row =~ m|(.*)|s ) {
1133 5         11 $authinfo = $1;
1134              
1135 5 50       9 unless ( $authinfo ) {
1136 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Auth Info not provided' );
1137             }
1138              
1139 5 50 66     38 unless ( $authinfo =~ /[A-Z]/ && $authinfo =~ /[a-z]/ && $authinfo =~ /[0-9]/ && $authinfo =~ /[!\@\$\%*_.:\-=+?#,"'\\\/<>\[\]\{\}]/ ) {
      66        
      33        
1140 1         3 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Invalid Auth Info' );
1141             }
1142             }
1143             else {
1144 0         0 return _fail_schema2( q|Line: 15, Column: 25, Message: cvc-complex-type.2.4.b: The content of element 'domain:authInfo' is not complete. One of '{"urn:ietf:params:xml:ns:domain-1.0":pw, "urn:ietf:params:xml:ns:domain-1.0":ext}' is expected.| );
1145             }
1146             }
1147             else {
1148 0         0 return _fail_schema2( q|Line: 14, Column: 21, Message: cvc-complex-type.2.4.b: The content of element 'domain:create' is not complete. One of '{"urn:ietf:params:xml:ns:domain-1.0":registrant, "urn:ietf:params:xml:ns:domain-1.0":contact, "urn:ietf:params:xml:ns:domain-1.0":authInfo}' is expected.| );
1149             }
1150              
1151 4         9 my $srv_url = $obj->{sock};
1152 4         17 my $s = new IO::EPP::Test::Server( $srv_url );
1153 4         10 my $hosts = $s->data->{nss};
1154 4         20 my $doms = $s->data->{doms};
1155              
1156 4 100 66     17 if ( $dname =~ /^xn--/ and !$lang ) {
1157 1         3 return _fail_answ_with_reason( $cltrid, '2003', 'Required parameter missing', 'Language Extension required for IDN label domain names.' );
1158             }
1159              
1160 3 100 66     13 if ( $doms->{$dname} || $dname =~ /^reg/ ) {
1161 1         5 return _fail_answ( $cltrid, '2302', 'Object exists' );
1162             }
1163              
1164 2         5 my %nss;
1165 2         3 foreach my $ns ( @nss ) {
1166 3 100       32 unless ( $hosts->{$ns} ) {
1167 1         6 return _fail_answ_with_reason( $cltrid, '2303', 'Object does not exist', "ns $ns does not exist" );
1168             }
1169              
1170 2         5 $nss{$ns} = '+';
1171             }
1172              
1173 1         3 my $cre_date = get_date();
1174 1         4 my $exp_date = add_y( $cre_date, 1 );
1175              
1176 1         6 my $roid = uc( md5_hex($dname.$cre_date) );
1177              
1178             $doms->{$dname} = {
1179             nss => \%nss,
1180             hosts => {},
1181             cre_date => $cre_date,
1182             upd_date => $cre_date,
1183             exp_date => $exp_date,
1184             authInfo => $authinfo,
1185             roid => $roid.'_DOMAIN_'.$subProduct.'-VRSN',
1186             statuses => { 'ok' => '+' },
1187             creater => $obj->{user},
1188             owner => $obj->{user},
1189             updater => $obj->{user},
1190 1         12 avail => 0,
1191             reason => 'Domain exists',
1192             };
1193              
1194 1         5 foreach my $ns ( keys %nss ) {
1195 2         5 $hosts->{$ns}{statuses}{linked}++;
1196             }
1197              
1198 1         6 return _ok_answ2( $cltrid, qq|
1199            
1200             $dname
1201             $cre_date
1202             $exp_date
1203            
1204             | );
1205             }
1206              
1207              
1208             sub domain_info {
1209 10     10 0 22 my ( $obj, $body ) = @_;
1210              
1211 10         59 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1212              
1213 10         32 my @chb = _check_body( \$body );
1214              
1215 10         20 my $cltrid;
1216              
1217 10 50       25 if ( $chb[0] ) {
1218 0         0 return @chb;
1219             }
1220             else {
1221 10         18 $cltrid = $chb[1];
1222             }
1223              
1224 10         17 my ( $show_hosts, $dname );
1225 10 50       49 if ( $body =~ m|([^<>]*)| ) {
1226 10 50       32 $show_hosts = lc $2 if $2;
1227 10         24 $dname = lc $3;
1228             }
1229             else {
1230 0         0 return _fail_schema2( q|Line: 8, Column: 21, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":names}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":name}' is expected.| );
1231             }
1232              
1233 10 50       21 unless ( $dname ) {
1234 0         0 return _fail_schema2( q|Line: 8, Column: 34, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| );
1235             }
1236              
1237 10 100       37 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1238 1         4 return _fail_answ_with_reason( $cltrid, '2005', 'Parameter value syntax error', 'Domain name contains an invalid DNS character' );
1239             }
1240              
1241 9         31 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1242              
1243 9 100       27 if ( $tld ne lc( $subProduct ) ) {
1244 1         4 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Incorrect NameStore Extension' );
1245             }
1246              
1247 8         19 my $srv_url = $obj->{sock};
1248 8         32 my $s = new IO::EPP::Test::Server( $srv_url );
1249              
1250 8 100       19 unless ( $s->data->{doms}{$dname} ) {
1251 1         3 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1252             }
1253              
1254 7         22 _check_dom_dates( $s, $dname );
1255              
1256 7 50       27 unless ( $s->data->{doms}{$dname} ) {
1257 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1258             }
1259              
1260              
1261 7         17 my $dm = $s->data->{doms}{$dname};
1262              
1263 7 50       21 if ( $dm->{owner} ne $obj->{user} ) {
1264 0         0 return _fail_answ_with_reason( $cltrid, '2201', 'Authorization error', 'Subordinate host info not available with partial info' );
1265             }
1266              
1267 7         11 my $answ = '';
1268 7         20 $answ .= "" . uc( $dname ) . "";
1269 7         15 $answ .= ''.$dm->{roid}.'';
1270 7         10 $answ .= qq|| for ( sort keys %{$dm->{statuses}} );
  7         41  
1271 7 50       14 if ( scalar( keys %{$dm->{nss}} ) ) {
  7         20  
1272 7         76 $answ .= '';
1273              
1274 7         12 foreach my $ns ( sort keys %{$dm->{nss}} ) {
  7         28  
1275 14         30 $answ .= "$ns";
1276             }
1277              
1278 7         14 $answ .= '';
1279             }
1280 7 50 33     17 if ( !$show_hosts or $show_hosts ne 'none' ) {
1281 7         9 foreach my $host ( sort keys %{$dm->{hosts}} ) {
  7         19  
1282 3         6 $answ .= "$host";
1283             }
1284             }
1285 7         17 $answ .= "$$dm{owner}";
1286 7         12 $answ .= "$$dm{creater}";
1287 7         15 $answ .= "$$dm{cre_date}";
1288 7         76 $answ .= "$$dm{updater}";
1289 7         19 $answ .= "$$dm{upd_date}";
1290 7         12 $answ .= "$$dm{exp_date}";
1291 7 50       14 $answ .= "$$dm{tr_date}" if $dm->{tr_date};
1292 7         15 $answ .= "$$dm{authInfo}";
1293 7         11 $answ .= '';
1294              
1295 7         10 my $rgp = '';
1296 7         14 my $now = get_date();
1297              
1298 7         22 my $c5d = add_5d( $$dm{cre_date} );
1299 7 50       21 if ( $now lt $c5d ) {
1300 7         15 $rgp .= 'endDate=' . $c5d . '';
1301             }
1302              
1303 7 100       22 my $r5d = $$dm{ren_date} ? add_5d( $$dm{ren_date} ) : '';
1304 7 100 66     27 if ( $r5d and $now lt $r5d ) {
1305 5         12 $rgp .= 'endDate=' . $r5d . '';
1306             }
1307              
1308 7 50       20 my $t5d = $$dm{tr_date} ? add_5d( $$dm{tr_date} ) : '';
1309 7 50 33     16 if ( $t5d and $now lt $t5d ) {
1310 0         0 $rgp .= 'endDate=' . $t5d . '';
1311             }
1312              
1313 7 50       15 if ( $now gt $dm->{exp_date} ) {
1314 0         0 my $ar5d = add_5d( $dm->{exp_date} );
1315 0         0 $rgp .= 'endDate=' . $ar5d . '';
1316             }
1317              
1318 7 100       16 if ( $dm->{statuses}{pendingDelete} ) {
1319 2         7 my $d5d = add_5d( $dm->{del_date} );
1320              
1321 2 50       7 if ( $now lt $d5d ) {
1322 2         6 $rgp .= 'endDate=' . $d5d . '';
1323             }
1324             else {
1325             # after redemption
1326 0         0 $d5d = add_5d( $d5d );
1327              
1328 0         0 $rgp .= 'endDate=' . $d5d . '';
1329             }
1330             }
1331              
1332 7 50       13 if ( $rgp ) {
1333 7         17 $rgp = qq|$rgp|;
1334             }
1335              
1336 7         18 return _ok_answ( $cltrid, $answ, $rgp );
1337             }
1338              
1339              
1340              
1341             sub domain_renew {
1342 6     6 0 11 my ( $obj, $body ) = @_;
1343              
1344 6         37 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1345              
1346 6         17 my @chb = _check_body( \$body );
1347              
1348 6         10 my $cltrid;
1349              
1350 6 50       13 if ( $chb[0] ) {
1351 0         0 return @chb;
1352             }
1353             else {
1354 6         12 $cltrid = $chb[1];
1355             }
1356              
1357 6         7 my $dname;
1358 6 50       24 if ( $body =~ m|([^<>]*)| ) {
1359 6         18 $dname = lc $1;
1360             }
1361             else {
1362 0         0 return _fail_schema2( q|Line: 8, Column: 21, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":names}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":name}' is expected.| );
1363             }
1364              
1365 6 50       14 unless ( $dname ) {
1366 0         0 return _fail_schema2( q|Line: 8, Column: 34, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| );
1367             }
1368              
1369 6 100       21 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1370 1         3 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1371             }
1372              
1373 5         21 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1374              
1375 5 50       27 if ( $tld ne lc( $subProduct ) ) {
1376 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Incorrect NameStore Extension' );
1377             }
1378              
1379 5         7 my $user_edt;
1380 5 50       20 if ( $body =~ m|(.+)| ) {
1381 5         11 $user_edt = $1;
1382             }
1383             else {
1384 0         0 return _fail_schema2( q|Line: 9, Column: 31, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":period}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":curExpDate}' is expected.| );
1385             }
1386              
1387 5         10 my ( $yy, $mm, $dd );
1388 5 50       19 if ( $user_edt =~ /(\d{4})-(\d{2})-(\d{2})/ ) {
1389 5         16 ( $yy, $mm, $dd ) = ( $1, $2, $3 );
1390             }
1391              
1392 5 100 33     57 unless ( $yy && $yy >= 1000 && $yy <= 9999 and $mm && $mm <= 13 and $dd && $dd <= 31 ) {
      33        
      66        
      66        
      33        
      66        
1393 1         5 return _fail_schema2( qq|Line: 7, Column: 54, Message: cvc-datatype-valid.1.2.1: '$user_edt' is not a valid value for 'date'.| );
1394             }
1395              
1396 4         8 my $period;
1397 4 50       15 if ( $body =~ m|(\d+)| ) {
1398 4         9 $period = $1;
1399             }
1400             else {
1401 0         0 $period = 1;
1402             }
1403              
1404 4 100 66     22 if ( $period < 1 || $period > 10 ) {
1405 1         4 return _fail_answ( $cltrid, '2306', 'Parameter value policy error' );
1406             }
1407              
1408 3         12 my $srv_url = $obj->{sock};
1409 3         13 my $s = new IO::EPP::Test::Server( $srv_url );
1410              
1411 3 50       7 unless ( $s->data->{doms}{$dname} ) {
1412 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1413             }
1414              
1415 3         10 _check_dom_dates( $s, $dname );
1416              
1417 3 50       11 unless ( $s->data->{doms}{$dname} ) {
1418 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1419             }
1420              
1421 3         8 my $dm = $s->data->{doms}{$dname};
1422              
1423 3 50       10 if ( $dm->{owner} ne $obj->{user} ) {
1424 0         0 return _fail_answ( $cltrid, '2201', 'Authorization error' );
1425             }
1426              
1427 3 50 33     22 if ( $dm->{statuses}{serverRenewProhibited} or $dm->{statuses}{clientRenewProhibited} or $dm->{statuses}{pendingDelete} ) {
      33        
1428 0         0 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1429             }
1430              
1431 3 100 66     10 if ( $$dm{ren_date} and add_5d( $$dm{ren_date} ) gt get_date() ) {
1432 1         5 return _fail_answ( $cltrid, '2004', 'Domain in renewPeriod' );
1433             }
1434              
1435 2         12 my ( $edt ) = $dm->{exp_date} =~ /^(\d{4}-\d{2}-\d{2})/;
1436              
1437 2 100       7 if ( $user_edt ne $edt ) {
1438 1         4 return _fail_answ( $cltrid, '2004', 'Wrong curExpDate provided' );
1439             }
1440              
1441 1         3 my $now = get_date();
1442              
1443 1         5 my ( $y0 ) = $now =~ /^(\d{4})/;
1444 1         4 my ( $y1 ) = $dm->{exp_date} =~ /^(\d{4})/;
1445              
1446 1 50       7 if ( $y1 - $y0 + $period > 10 ) {
1447 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Max RegistrationPeriod exceeded' );
1448             }
1449              
1450 1         3 $dm->{ren_date} = $now;
1451 1         3 $dm->{exp_date} = add_y( $dm->{exp_date}, $period );
1452              
1453 1         3 my $answ = qq|
1454             |;
1455 1         4 $answ .= " " . uc( $dname ) . "\n";
1456 1         4 $answ .= " " . $dm->{exp_date} . "\n";
1457 1         3 $answ .= " \n";
1458              
1459 1         3 return _ok_answ2( $cltrid, $answ );
1460             }
1461              
1462              
1463             sub domain_update {
1464 19     19 0 31 my ( $obj, $body ) = @_;
1465              
1466 19         117 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1467              
1468 19         39 my $rgp = '';
1469 19 100       84 if ( $body =~ m|]+>\s*(.+)\s*|s ) { $rgp = $1; }
  2         7  
1470              
1471 19         56 my @chb = _check_body( \$body );
1472              
1473 19         34 my $cltrid;
1474              
1475 19 50       38 if ( $chb[0] ) {
1476 0         0 return @chb;
1477             }
1478             else {
1479 19         31 $cltrid = $chb[1];
1480             }
1481              
1482 19         26 my $dname;
1483 19 50       73 if ( $body =~ m|([^<>]*)| ) {
1484 19         53 $dname = lc $1;
1485             }
1486             else {
1487 0         0 return _fail_schema2( q|Line: 8, Column: 21, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":names}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":name}' is expected.| );
1488             }
1489              
1490 19 50       38 unless ( $dname ) {
1491 0         0 return _fail_schema2( q|Line: 8, Column: 34, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| );
1492             }
1493              
1494 19 100       69 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1495 1         3 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1496             }
1497              
1498 18         62 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1499              
1500 18 100       47 if ( $tld ne lc( $subProduct ) ) {
1501 1         4 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Domainname is invalid' );
1502             }
1503              
1504 17         37 my %add;
1505             my %rem;
1506 17         0 my %chg;
1507              
1508 17 100       93 if ( $body =~ m|\s*(.+)\s*|s ) {
1509 7         20 my $add = $1;
1510              
1511 7 50       17 if ( $add =~ /domain:contact/ ) {
1512 0         0 return _fail_answ_with_reason( $cltrid, '2102', 'Unimplemented option', "Subproduct dot".$subProduct." does NOT support contacts." );
1513             }
1514              
1515 7         19 my @sts = $add =~ m|()|s;
1516              
1517 7         16 for my $row ( @sts ) {
1518 1         2 my ( $st, $reason );
1519              
1520 1 50       6 if ( $row =~ m|| ) {
1521 1         2 $st = $1;
1522 1         2 $reason = '+';
1523             }
1524              
1525 1 50       4 unless ( $statuses{$st} ) {
1526 0         0 return _fail_schema2( qq|Line: 8, Column: 52, Message: cvc-enumeration-valid: Value '$st' is not facet-valid with respect to enumeration '[clientDeleteProhibited, clientHold, clientRenewProhibited, clientTransferProhibited, clientUpdateProhibited, inactive, ok, pendingCreate, pendingDelete, pendingRenew, pendingTransfer, pendingUpdate, serverDeleteProhibited, serverHold, serverRenewProhibited, serverTransferProhibited, serverUpdateProhibited]'. It must be a value from the enumeration.| );
1527             }
1528              
1529 1         4 $add{statuses}{$st} = $reason;
1530             }
1531              
1532 7         13 undef @sts;
1533              
1534 7         20 @sts = $add =~ m|([^<>]*)|s;
1535              
1536 7         11 for my $row ( @sts ) {
1537 2         4 my ( $st, $reason );
1538              
1539 2 50       10 if ( $row =~ m|([^<>]*)| ) {
1540 2         5 $st = $1;
1541 2   50     6 $reason = $2 || '+';
1542             }
1543              
1544 2 100       7 unless ( $statuses{$st} ) {
1545 1         6 return _fail_schema2( qq|Line: 8, Column: 52, Message: cvc-enumeration-valid: Value '$st' is not facet-valid with respect to enumeration '[clientDeleteProhibited, clientHold, clientRenewProhibited, clientTransferProhibited, clientUpdateProhibited, inactive, ok, pendingCreate, pendingDelete, pendingRenew, pendingTransfer, pendingUpdate, serverDeleteProhibited, serverHold, serverRenewProhibited, serverTransferProhibited, serverUpdateProhibited]'. It must be a value from the enumeration.| );
1546             }
1547              
1548 1         4 $add{statuses}{$st} = $reason;
1549             }
1550              
1551 6 100       23 if ( $add =~ m|(.+)|s ) {
1552 4         9 my $nss = $1;
1553              
1554 4         16 my @nss = $nss =~ m|([^<>]*)|s;
1555              
1556 4         6 my @hosts;
1557 4         7 for my $row ( @nss ) {
1558 4 50       14 if ( $row =~ m|([^<>]+)| ) {
1559 4         13 push @hosts, lc $1;
1560             }
1561             else {
1562 0         0 return _fail_schema2( q|Line: 9, Column: 40, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| )
1563             }
1564             }
1565              
1566 4         7 for my $ns ( @hosts ) {
1567 4 50       12 if ( $ns =~ /^[0-9a-z.\-]+$/ ) {
1568 4         19 $add{nss}{$ns} = '+';
1569             }
1570             else {
1571 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1572             }
1573             }
1574             }
1575             }
1576              
1577 16 100       53 if ( $body =~ m|\s*(.+)\s*|s ) {
1578 4         11 my $rem = $1;
1579              
1580 4 50       22 if ( $rem =~ /domain:contact/ ) {
1581 0         0 return _fail_answ_with_reason( $cltrid, '2102', 'Unimplemented option', "Subproduct dot".$subProduct." does NOT support contacts." );
1582             }
1583              
1584 4         13 my @sts = $rem =~ m|(]*>)|s;
1585              
1586 4         9 for my $row ( @sts ) {
1587 1         2 my $st;
1588              
1589 1 50       7 if ( $row =~ m|| ) {
1590 1         3 $st = $1;
1591             }
1592              
1593 1 50       4 unless ( $statuses{$st} ) {
1594 0         0 return _fail_schema2( qq|Line: 9, Column: 52, Message: cvc-enumeration-valid: Value '$st' is not facet-valid with respect to enumeration '[clientDeleteProhibited, clientHold, clientRenewProhibited, clientTransferProhibited, clientUpdateProhibited, inactive, ok, pendingCreate, pendingDelete, pendingRenew, pendingTransfer, pendingUpdate, serverDeleteProhibited, serverHold, serverRenewProhibited, serverTransferProhibited, serverUpdateProhibited]'. It must be a value from the enumeration.| );
1595             }
1596              
1597 1         3 $rem{statuses}{$st} = '+';
1598             }
1599              
1600 4 100       19 if ( $rem =~ m|(.+)|s ) {
1601 3         7 my $nss = $1;
1602              
1603 3         13 my @nss = $nss =~ m|([^<>]*)|s;
1604              
1605 3         5 my @hosts;
1606 3         14 for my $row ( @nss ) {
1607 3 50       12 if ( $row =~ m|([^<>]+)| ) {
1608 3         10 push @hosts, lc $1;
1609             }
1610             else {
1611 0         0 return _fail_schema2( q|Line: 9, Column: 40, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| )
1612             }
1613             }
1614              
1615 3         6 for my $ns ( @hosts ) {
1616 3 50       10 if ( $ns =~ /^[0-9a-z.\-]+$/ ) {
1617 3         13 $rem{nss}{$ns} = '+';
1618             }
1619             else {
1620 0         0 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1621             }
1622             }
1623             }
1624             }
1625              
1626 16 100       62 if ( $body =~ m|\s*(.+)\s*|s ) {
1627 4         9 my $chg = $1;
1628              
1629 4 100       12 if ( $chg =~ /domain:registrant/ ) {
1630 1         7 return _fail_answ_with_reason( $cltrid, '2102', 'Unimplemented option', "Subproduct dot".$subProduct." does NOT support contacts." );
1631             }
1632              
1633 3 50       12 if ( $chg =~ m|([^<>]*)|s ) {
1634 3         7 my $key = $1;
1635              
1636 3 100 66     21 unless ( $key and length( $key ) >= 16 and length( $key ) <= 48 ) {
      66        
1637 1         3 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Invalid Auth Info' );
1638             }
1639              
1640 2 50 66     32 unless ( $key =~ /[a-z]/ and $key =~ /[A-Z]/ and $key =~ /[0-9]/ and $key =~ /["'.,\-\[\]\\|\/!?\$\%\@*()+=_{}:;]/ ) {
      66        
      33        
1641 1         4 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Invalid Auth Info' );
1642             }
1643              
1644 1         5 $chg{authInfo} = $key;
1645             }
1646             }
1647              
1648 13 100 100     47 unless ( scalar( keys %add ) + scalar( keys %rem ) + scalar( keys %chg ) or $rgp ) {
1649 1         4 return _fail_answ_with_reason( $cltrid, '2003', 'Required parameter missing', 'empty non-extended update is not allowed' );
1650             }
1651              
1652 12         56 my $s = new IO::EPP::Test::Server( $obj->{sock} );
1653              
1654 12 100       30 unless ( $s->data->{doms}{$dname} ) {
1655 1         3 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1656             }
1657              
1658 11         33 _check_dom_dates( $s, $dname );
1659              
1660 11 50       40 unless ( $s->data->{doms}{$dname} ) {
1661 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1662             }
1663              
1664 11         26 my $dom = $s->data->{doms}{$dname};
1665 11         23 my $nss = $s->data->{nss};
1666              
1667 11 50       27 if ( $dom->{owner} ne $obj->{user} ) {
1668 0         0 return _fail_answ( $cltrid, '2201', 'Authorization error' );
1669             }
1670              
1671 11 100       22 if ( $rgp ) {
1672 2 50       11 unless ( $rgp =~ /restore op="[a-z]+"/ ) {
1673 0         0 return _fail_schema2( q|Line: 17, Column: 33, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:rgp-1.0":xxxxxx}'. One of '{"urn:ietf:params:xml:ns:rgp-1.0":restore}' is expected.| );
1674             }
1675              
1676 2 100       8 if ( $rgp =~ /restore op="request"/ ) {
1677 1 50       4 unless ( $dom->{statuses}{pendingDelete} ) {
1678 0         0 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1679             }
1680              
1681 1         3 my $now = get_date();
1682 1         4 my $last_redem_date = add_5d( $dom->{del_date} );
1683              
1684 1 50       4 if ( $now gt $last_redem_date ) {
1685 0         0 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1686             }
1687              
1688 1         3 $dom->{statuses}{pendingRestore} = '+';
1689 1         4 $dom->{upd_date} = get_date();
1690              
1691 1         5 return _min_answ( $cltrid );
1692             }
1693              
1694 1 50       6 if ( $rgp =~ /restore op="report"/ ) {
1695 1 50       5 unless ( $dom->{statuses}{pendingRestore} ) {
1696 0         0 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1697             }
1698              
1699 1         2 delete $dom->{statuses}{pendingDelete};
1700 1         2 delete $dom->{statuses}{pendingRestore};
1701              
1702 1         3 for my $ns ( keys %{$dom->{nss}} ) {
  1         4  
1703 2 50       5 if ( $nss->{$ns} ) {
1704 2         5 $nss->{$ns}{statuses}{linked}++;
1705             }
1706             else {
1707 0         0 delete $dom->{nss}{$ns};
1708             }
1709             }
1710              
1711 1         5 return _min_answ( $cltrid );
1712             }
1713              
1714 0         0 return _fail_schema2( q|Line: 17, Column: 33, Message: cvc-enumeration-valid: Value 'xxxxxx' is not facet-valid with respect to enumeration '[request, report]'. It must be a value from the enumeration.| );
1715             }
1716              
1717 9 100 100     44 if ( $dom->{statuses}{serverUpdateProhibited} or $dom->{statuses}{clientUpdateProhibited} and not $rem{statuses}{clientUpdateProhibited} ) {
      66        
1718 1         5 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1719             }
1720              
1721 8         12 foreach my $st ( keys %{$add{statuses}} ) {
  8         33  
1722 1 50       4 if ( $dom->{statuses}{$st} ) {
1723 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$st status is already associated" );
1724             }
1725             }
1726              
1727 8         11 foreach my $st ( keys %{$rem{statuses}} ) {
  8         19  
1728 1 50       4 unless ( $dom->{statuses}{$st} ) {
1729 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$st status not found" );
1730             }
1731             }
1732              
1733 8         13 foreach my $ns ( keys %{$add{nss}} ) {
  8         19  
1734 3 100       19 unless ( $nss->{$ns} ) {
1735 1         6 return _fail_answ_with_reason( $cltrid, '2303', 'Object does not exist', "host $ns not found." );
1736             }
1737              
1738 2 50       5 if ( $dom->{nss}{$ns} ) {
1739 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$ns ns is already linked" );
1740             }
1741             }
1742              
1743 7         14 foreach my $ns ( keys %{$rem{nss}} ) {
  7         16  
1744 3 100       9 unless ( $dom->{nss}{$ns} ) {
1745 1         4 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$ns ns not found" );
1746             }
1747             }
1748              
1749             # order not change!
1750 6         8 $dom->{statuses}{$_} = $add{statuses}{$_} foreach keys %{$add{statuses}};
  6         14  
1751              
1752 6         12 delete $dom->{statuses}{$_} foreach keys %{$rem{statuses}};
  6         12  
1753              
1754 6 100 100     17 if ( $dom->{statuses}{ok} and scalar( keys %{$dom->{statuses}} ) > 1 ) {
  5         18  
1755 1         3 delete $dom->{statuses}{ok};
1756             }
1757              
1758 6 100       8 unless ( scalar( keys %{$dom->{statuses}} ) ) {
  6         15  
1759 1         3 $dom->{statuses}{ok} = '+';
1760             }
1761              
1762 6         9 foreach my $ns ( keys %{$add{nss}} ) {
  6         12  
1763 2         5 $dom->{nss}{$ns} = '+';
1764              
1765 2         6 $nss->{$ns}{statuses}{linked}++;
1766             }
1767              
1768 6         9 foreach my $ns ( keys %{$rem{nss}} ) {
  6         10  
1769 2         5 delete $dom->{nss}{$ns};
1770              
1771 2         4 $nss->{$ns}{statuses}{linked}--;
1772              
1773 2 50       7 delete $nss->{$ns}{statuses}{linked} if $nss->{$ns}{statuses}{linked} == 0;
1774             }
1775              
1776 6 100       16 $dom->{authInfo} = $chg{authInfo} if $chg{authInfo};
1777              
1778 6         12 $dom->{upd_date} = get_date();
1779 6         16 $dom->{updater} = $obj->{user};
1780              
1781 6         15 return _min_answ( $cltrid );
1782             }
1783              
1784              
1785             sub domain_delete {
1786 6     6 0 9 my ( $obj, $body ) = @_;
1787              
1788 6         40 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1789              
1790 6         19 my @chb = _check_body( \$body );
1791              
1792 6         25 my $cltrid;
1793              
1794 6 50       15 if ( $chb[0] ) {
1795 0         0 return @chb;
1796             }
1797             else {
1798 6         10 $cltrid = $chb[1];
1799             }
1800              
1801 6         9 my $dname;
1802 6 50       28 if ( $body =~ m|([^<>]*)| ) {
1803 6         16 $dname = lc $1;
1804             }
1805             else {
1806 0         0 return _fail_schema2( q|Line: 8, Column: 21, Message: cvc-complex-type.2.4.a: Invalid content was found starting with element '{"urn:ietf:params:xml:ns:domain-1.0":names}'. One of '{"urn:ietf:params:xml:ns:domain-1.0":name}' is expected.| );
1807             }
1808              
1809 6 50       15 unless ( $dname ) {
1810 0         0 return _fail_schema2( q|Line: 8, Column: 34, Message: cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '1' for type 'labelType'.| );
1811             }
1812              
1813 6 100       32 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1814 1         4 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1815             }
1816              
1817 5         20 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1818              
1819 5 50       14 if ( $tld ne lc( $subProduct ) ) {
1820 0         0 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Domainname is invalid' );
1821             }
1822              
1823 5         25 my $s = new IO::EPP::Test::Server( $obj->{sock} );
1824              
1825 5 100       13 unless ( $s->data->{doms}{$dname} ) {
1826 1         4 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1827             }
1828              
1829 4         12 _check_dom_dates( $s, $dname );
1830              
1831 4 50       14 unless ( $s->data->{doms}{$dname} ) {
1832 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1833             }
1834              
1835 4         9 my $dom = $s->data->{doms}{$dname};
1836 4         9 my $nss = $s->data->{nss};
1837              
1838 4 100       12 if ( $dom->{owner} ne $obj->{user} ) {
1839 1         4 return _fail_answ( $cltrid, '2201', 'Authorization error' );
1840             }
1841              
1842 3 50       9 if ( $dom->{hosts} ) {
1843              
1844 3         4 for my $h ( keys %{$dom->{hosts}} ) {
  3         10  
1845              
1846 3 100       10 if ( $nss->{$h}{statuses}{linked} ) {
1847 1         3 return _fail_answ_with_reason( $cltrid, '2305', 'Object association prohibits operation', 'domain has an active child host' );
1848             }
1849             }
1850             }
1851              
1852 2 100 33     23 if ( $dom->{statuses}{serverUpdateProhibited} or $dom->{statuses}{clientUpdateProhibited} or $dom->{statuses}{serverDeleteProhibited} or $dom->{statuses}{clientDeleteProhibited} or $dom->{statuses}{pendingDelete} ) {
      33        
      33        
      66        
1853 1         4 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1854             }
1855              
1856 1         3 for my $ns ( keys %{$dom->{hosts}} ) {
  1         5  
1857 1 50       5 if ( $nss->{$ns}{statuses}{linked} ) {
1858 0         0 $nss->{$ns}{statuses}{linked}--;
1859              
1860 0 0       0 if ( $nss->{$ns}{statuses}{linked} == 0 ) {
1861 0         0 delete $nss->{$ns}{statuses}{linked};
1862             }
1863             }
1864             }
1865              
1866 1         3 $dom->{statuses}{pendingDelete} = '+';
1867 1         3 $dom->{del_date} = $dom->{upd_date} = get_date();
1868 1         4 $dom->{updater} = $obj->{user};
1869              
1870 1         4 return _min_answ( $cltrid );
1871             }
1872              
1873              
1874             sub logout {
1875 28     28 0 52 my ( $body ) = @_;
1876              
1877 28 50       178 unless ( $body =~ s|^<\?xml version="1.0" encoding="UTF-8"\?>\s+||s ) {
1878 0         0 return _fail_schema( q|Line....: 1
1879             Column..: 2
1880             Message.: : The markup in the document preceding the root element must be well-formed.| );
1881             }
1882              
1883 28 50       177 unless ( $body =~ s|^\s+||s ) {
1884 0         0 return _fail_schema( q|Line....: 2
1885             Column..: 173
1886             Message.: : cvc-complex-type.3.2.2: Attribute 'xxx' is not allowed to appear in element 'epp'.| );
1887             }
1888              
1889 28 50       198 unless ( $body =~ s|\s*\s*||s ) {
1890 0         0 return _fail_schema( q|Line....: 11111
1891             Column..: 6
1892             Message.: : The end-tag for element type "epp" must end with a '>' delimiter.| );
1893             }
1894              
1895 28 50       112 unless ( $body =~ s|\s*||s ) {
1896 0         0 return _fail_schema( q|Line....: 3
1897             Column..: 12
1898             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'xxxxxx'. One of '{"urn:ietf:params:xml:ns:epp-1.0":greeting, "urn:ietf:params:xml:ns:epp-1.0":hello, "urn:ietf:params:xml:ns:epp-1.0":command, "urn:ietf:params:xml:ns:epp-1.0":response, "urn:ietf:params:xml:ns:epp-1.0":extension}' is expected.| );
1899             }
1900              
1901 28 50       140 unless ( $body =~ s|\s*||s ) {
1902 0         0 return _fail_schema( q|Line....: 22222
1903             Column..: 11
1904             Message.: : The end-tag for element type "command" must end with a '>' delimiter.| );
1905             }
1906              
1907 28         113 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|;
1908              
1909 28 50       63 unless ( $cltrid ) {
1910 0         0 return _fail_schema( q|Line....: 11111
1911             Column..: 22222
1912             Message.: : cvc-minLength-valid: Value '' with length = '0' is not facet-valid with respect to minLength '3' for type 'trIDStringType'.| );
1913             }
1914              
1915 28 50       101 unless ( $body =~ s|\s*||s ) {
1916 0         0 return _fail_schema( q|Line....: 4
1917             Column..: 13
1918             Message.: : cvc-complex-type.2.4.a: Invalid content was found starting with element 'xxxxxx'. One of '{"urn:ietf:params:xml:ns:epp-1.0":check, "urn:ietf:params:xml:ns:epp-1.0":create, "urn:ietf:params:xml:ns:epp-1.0":delete, "urn:ietf:params:xml:ns:epp-1.0":info, "urn:ietf:params:xml:ns:epp-1.0":login, "urn:ietf:params:xml:ns:epp-1.0":logout, "urn:ietf:params:xml:ns:epp-1.0":poll, "urn:ietf:params:xml:ns:epp-1.0":renew, "urn:ietf:params:xml:ns:epp-1.0":transfer, "urn:ietf:params:xml:ns:epp-1.0":update}' is expected.| );
1919             }
1920              
1921 28         60 my $svtrid = get_svtrid();
1922              
1923 28         78 return qq|Command completed successfully; ending session$cltrid$svtrid|;
1924             }
1925              
1926             1;