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   6 use Digest::MD5 qw(md5 md5_hex);
  1         2  
  1         61  
25              
26 1     1   5 use IO::EPP::Verisign;
  1         1  
  1         16  
27 1     1   4 use IO::EPP::Test::Server;
  1         1  
  1         15  
28              
29 1     1   4 use strict;
  1         2  
  1         17  
30 1     1   23 use warnings;
  1         3  
  1         34  
31              
32 1     1   5 no utf8; # !!!
  1         2  
  1         6  
33              
34             sub req {
35 166     166 0 253 my ( $obj, $out_data, $info ) = @_;
36              
37 166         186 my $in_data;
38              
39 166 100 100     2924 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         65 $in_data = hello( $out_data );
41             }
42             elsif ( $out_data and $out_data =~ m|| ) {
43 28         55 $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         37 $in_data = host_check( $obj, $out_data );
50             }
51             elsif ( $out_data and $out_data =~ m|
52 9         20 $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         27 $in_data = host_update( $obj, $out_data );
59             }
60             elsif ( $out_data and $out_data =~ m|
61 3         9 $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         41 $in_data = domain_info( $obj, $out_data );
71             }
72             elsif ( $out_data and $out_data =~ m|
73 6         16 $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         15 $in_data = domain_delete( $obj, $out_data );
80             }
81             elsif ( $out_data and $out_data =~ m|| ) {
82 28         100 $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         386 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 1698 my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime(time);
109              
110 76         223 $year += 1900;
111 76         95 $mon += 1;
112              
113 76         342 my $dt1 = sprintf( '%0004d-%02d-%02dT%02d:%02d:%02d.0Z', $year, $mon, $mday, $hour, $min, $sec );
114              
115 76         174 return $dt1;
116             }
117              
118             sub add_5d {
119 28     28 0 37 my ( $dt ) = @_;
120              
121 28         127 my ( $y, $m, $d ) = $dt =~ /^(\d{4})-(\d{2})-(\d{2})/;
122              
123 28         46 $d += 5;
124 28         34 $m += 0;
125              
126 28 50 0     122 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     142 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     57 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     40 if ( $m == 2 && $y % 4 != 0 and $d > 28 ) {
      33        
142 0         0 $d -= 28;
143 0         0 $m++;
144             }
145              
146 28 50       54 if ( $m == 13 ) {
147 0         0 $m = 1;
148 0         0 $y++;
149             }
150              
151 28 50       39 $d = '0'.$d if $d < 10;
152 28 50       52 $m = '0'.$m if $m < 10;
153              
154 28         134 $dt =~ s/^(\d{4}-\d{2}-\d{2})/$y-$m-$d/;
155              
156 28         124 return $dt;
157             }
158              
159             sub add_y {
160 2     2 0 6 my ( $dt, $y ) = @_;
161              
162 2         9 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     73 if ( $dt =~ /^\d{4}-02-29/ and $y % 4 != 0 ) {
169 0         0 $dt =~ s/-02-29/-03-01/;
170             }
171              
172 2         7 return $dt;
173             }
174              
175              
176             sub get_svtrid {
177 138     138 0 272 my $i = int( rand( 9999999999 ) );
178 138         176 my $j = int( rand( 9999999 ) );
179 138         152 my $k = int( rand( 999999 ) );
180              
181 138         349 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   7 my ( $err ) = @_;
196              
197 3         8 my $svtrid = get_svtrid();
198              
199 3         20 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   66 my ( $cltrid, $code, $msg ) = @_;
213              
214 29         49 my $svtrid = get_svtrid();
215              
216 29         173 return qq|$msg$cltrid$svtrid|;
217             }
218              
219             sub _fail_answ_with_reason {
220 21     21   53 my ( $cltrid, $code, $msg, $reason ) = @_;
221              
222 21         39 my $svtrid = get_svtrid();
223              
224 21         156 return qq|$msg$reason$cltrid$svtrid|;
225             }
226              
227              
228             sub _ok_answ {
229 13     13   36 my ( $cltrid, $answ, $ext ) = @_;
230              
231 13 100       29 if ( $ext ) {
232 7         24 $ext = "$ext";
233             }
234             else {
235 6         10 $ext = '';
236             }
237              
238 13         25 my $svtrid = get_svtrid();
239              
240 13         115 return qq|Command completed successfully$answ$ext$cltrid$svtrid|;
241             }
242              
243             sub _ok_answ2 {
244 2     2   7 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         16 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         23 my $svtrid = get_svtrid();
279              
280 13         85 return qq|Command completed successfully$cltrid$svtrid|;
281             }
282              
283              
284             sub _check_dom_dates {
285 25     25   40 my ( $s, $dname ) = @_;
286              
287 25         47 my $dom = $s->data->{doms}{$dname};
288              
289 25         43 my $now = get_date();
290              
291 25 50 33     115 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       74 if ( $dom->{statuses}{pendingDelete} ) {
302             # check on redemption time
303 5         11 my $end_del_date = add_5d( add_5d( $dom->{del_date} ) );
304              
305 5 50       12 if ( $now gt $end_del_date ) {
306 0         0 delete $s->{doms}{$dname};
307             }
308              
309 5 100       14 if ( $dom->{statuses}{pendingRestore} ) {
310 2         4 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 62 my $dt = get_date();
322              
323 29         187 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 47 my ( $body ) = @_;
329              
330 28 50       185 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       180 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       811 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       124 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       739 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       124 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         187 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|;
367              
368 28 50       72 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       698 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         98 my ( $login ) = $body =~ m|([0-9A-Za-z_\-]+)|;
381              
382 28 50       60 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         79 my ( $pass ) = $body =~ m|([0-9A-Za-z!\@\$\%*_.:=+?#,"'\-{}\[\]\(\)]+)|;
388              
389 28 50 33     110 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         51 my $svtrid = get_svtrid();
396              
397 28 50       62 if ( $pass eq 'fail-pass' ) {
398 0         0 return qq|Authentication error$cltrid$svtrid|;
399             }
400              
401 28         87 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   131 my ( $body_ref ) = @_;
414              
415 81 50       461 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       484 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       1384 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       313 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       1206 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         357 my ( $cltrid ) = $$body_ref =~ m|([0-9A-Za-z\-]+)|;
446              
447 81 50       138 if ( $cltrid ) {
448 81         1136 $$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       320 unless ( $$body_ref =~ m{dot(COM|NET|EDU)} ) {
457 0         0 return _fail_namestore( $cltrid );
458             }
459              
460 81 50       980 unless ( $$body_ref =~ s|\s*]+>.+||s ) {
461 0         0 return _fail_namestore( $cltrid );
462             }
463              
464 81         132 my $cmd;
465 81 50       355 if ( $$body_ref =~ s/<(check|create|info|renew|update|delete)>\s*//s ) {
466 81         186 $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       1290 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         119 my $type;
481 81 50       1263 if ( $$body_ref =~ s/\s*<(host|domain):$cmd[^<>]+>\s*//s ) {
482 81         170 $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       867 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         250 return ( 0, $cltrid );
497             }
498              
499              
500             sub host_check {
501 1     1 0 3 my ( $obj, $body ) = @_;
502              
503 1         4 my @chb = _check_body( \$body );
504              
505 1         2 my $cltrid;
506              
507 1 50       8 if ( $chb[0] ) {
508 0         0 return @chb;
509             }
510             else {
511 1         2 $cltrid = $chb[1];
512             }
513              
514 1         10 my ( @hosts ) = $body =~ m|([^<>]+)|g;
515              
516 1 50       4 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         2 my $srv_url = $obj->{sock};
523 1         7 my $s = new IO::EPP::Test::Server( $srv_url );
524 1         2 my $answ_list = '';
525 1         2 foreach my $row ( @hosts ) {
526 5         16 my ( $ns ) = $row =~ m|([^<>]+)|;
527 5         10 $ns = lc $ns;
528              
529 5         5 my $avail = 1;
530              
531 5 50       10 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         22 $answ_list .= qq|$ns|;
539             }
540              
541 1         6 return _ok_answ( $cltrid, qq|$answ_list| );
542             }
543              
544              
545             sub host_create {
546 9     9 0 13 my ( $obj, $body ) = @_;
547              
548 9         48 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
549              
550 9         20 my @chb = _check_body( \$body );
551              
552 9         12 my $cltrid;
553              
554 9 50       19 if ( $chb[0] ) {
555 0         0 return @chb;
556             }
557             else {
558 9         11 $cltrid = $chb[1];
559             }
560              
561 9         13 my ( $ns, $dname );
562              
563 9 50       30 if ( $body =~ m|([^<>]+)| ) {
564 9         22 $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       29 unless ( $ns =~ /^[0-9a-z][0-9a-z\-\.]*[0-9a-z]\.[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
573 1         5 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         18 my $srv_url = $obj->{sock};
579 8         23 my $s = new IO::EPP::Test::Server( $srv_url );
580              
581 8         18 my $nss = $s->data->{nss};
582 8         14 my $doms = $s->data->{doms};
583              
584 8 100       19 if ( $nss->{$ns} ) {
585 2 100       7 if ( $nss->{$ns}{owner} eq $obj->{user} ) {
586 1         4 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         21 my ( $tld ) = $ns =~ /\.([0-9a-z\-]+)$/;
594              
595 6         14 my @v4;
596             my @v6;
597              
598 6 100       16 if ( $tld =~ /^(com|net|edu)$/ ) {
599             # need ip & Co
600 5         17 ( $dname ) = $ns =~ /\.([0-9a-z\-]+\.[a-z]+)$/;
601              
602 5 100       14 unless ( $doms->{$dname} ) {
603 1         4 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         13 @v4 = $body =~ m|([^<>]+)|g;
611 4         11 @v6 = $body =~ m|([^<>]+)|g;
612              
613 4 100       12 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       7 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         9 my $cre_date = get_date();
630              
631 3         16 my $roid = md5_hex($ns.$cre_date);
632 3         23 $roid =~ s/[a-f]//ig;
633              
634 3         5 my %v4;
635 3         13 $v4{$_} = '+' for @v4;
636 3         4 my %v6;
637 3         7 $v6{$_} = '+' for @v6;
638              
639 3         30 $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       9 if ( $dname ) {
642 2         8 $doms->{$dname}{hosts}{$ns} = '+';
643             }
644              
645 3         15 return _ok_answ( $cltrid, qq|$ns$cre_date| );
646             }
647              
648              
649              
650             sub host_info {
651 4     4 0 8 my ( $obj, $body ) = @_;
652              
653 4         9 my @chb = _check_body( \$body );
654              
655 4         5 my $cltrid;
656              
657 4 50       9 if ( $chb[0] ) {
658 0         0 return @chb;
659             }
660             else {
661 4         5 $cltrid = $chb[1];
662             }
663              
664 4         5 my $ns;
665              
666 4 50       15 if ( $body =~ m|([^<>]+)| ) {
667 4         9 $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       14 unless ( $ns =~ /^[0-9a-z][0-9a-z\-\.]*[0-9a-z]\.[0-9a-z][0-9a-z\-]*[0-9a-z]$/ ) {
676 1         5 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         7 my $srv_url = $obj->{sock};
682 3         10 my $s = new IO::EPP::Test::Server( $srv_url );
683              
684 3 100       6 unless ( $s->data->{nss}{$ns} ) {
685 1         4 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         4 return _fail_answ( $cltrid, '2201', 'Authorization error' );
692             }
693              
694 1         2 my $answ = '';
695 1         3 $answ .= "$ns";
696 1         4 $answ .= "" . $host->{roid} . "";
697 1         1 for my $st ( keys %{$host->{statuses}} ) {
  1         5  
698 1         3 $answ .= qq||;
699             }
700 1         2 for my $ip4 ( sort keys %{$host->{addr_v4}} ) {
  1         6  
701 1         4 $answ .= qq|$ip4|;
702             }
703 1         2 for my $ip6 ( sort keys %{$host->{addr_v6}} ) {
  1         3  
704 1         4 $answ .= qq|$ip6|;
705             }
706 1         3 $answ .= "$$host{owner}";
707 1         2 $answ .= "$$host{creater}";
708 1         4 $answ .= "$$host{cre_date}";
709 1 50       4 if ( $host->{updater} ) {
710 0         0 $answ .= "$$host{updater}";
711             }
712             else {
713 1         3 $answ .= "$$host{creater}";
714             }
715 1 50       3 if ( $host->{upd_date} ) {
716 0         0 $answ .= "$$host{upd_date}";
717             }
718             else {
719 1         5 $answ .= "$$host{cre_date}";
720             }
721 1         2 $answ .= '';
722              
723 1         4 return _ok_answ( $cltrid, $answ );
724             }
725              
726              
727              
728             sub host_update {
729 13     13 0 20 my ( $obj, $body ) = @_;
730              
731 13         26 my @chb = _check_body( \$body );
732              
733 13         17 my $cltrid;
734              
735 13 50       20 if ( $chb[0] ) {
736 0         0 return @chb;
737             }
738             else {
739 13         21 $cltrid = $chb[1];
740             }
741              
742 13         15 my $ns;
743              
744 13 50       43 if ( $body =~ m|([^<>]+)| ) {
745 13         28 $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       42 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         23 my $srv_url = $obj->{sock};
760 13         38 my $s = new IO::EPP::Test::Server( $srv_url );
761              
762 13 100       26 unless ( $s->data->{nss}{$ns} ) {
763 1         4 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
764             }
765              
766 12         30 my $host = $s->data->{nss}{$ns};
767              
768 12 100       27 if ( $host->{owner} ne $obj->{user} ) {
769 1         4 return _fail_answ( $cltrid, '2201', 'Authorization error' );
770             }
771              
772             # first check data
773 11         14 my ( @a4, @a6, @d4, @d6, @ast, @dst );
774              
775 11         22 for my $act ( 'add', 'rem' ) {
776 17 100       218 if ( $body =~ m|(.+?)|s ) {
777 12         28 my $ab = $1;
778              
779 12         33 my @v4 = $ab =~ m|([^<>]+)|g;
780 12         25 my @v6 = $ab =~ m|([^<>]+)|g;
781              
782 12         21 foreach my $v ( @v4 ) {
783 5 50       17 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       6 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         5 push @a4, $v;
793             }
794             else {
795 3 100       7 unless ( $host->{addr_v4}{$v} ) {
796 1         4 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$v addr not found" );
797             }
798              
799 2         6 push @d4, $v;
800             }
801             }
802              
803 10         13 foreach my $v ( @v6 ) {
804 2 100       10 unless ( $v =~ /^[0-9a-f:]{1,29}$/ ) {
805 1         4 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
806             }
807              
808 1 50       3 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         30 my @st = $ab =~ m||g;
825              
826 9         19 foreach my $st ( @st ) {
827 6 100       23 if ( $st !~ /^(clientDeleteProhibited|clientUpdateProhibited|linked|ok|pendingCreate|pendingDelete|pendingTransfer|pendingUpdate| serverDeleteProhibited|serverUpdateProhibited)$/ ) {
828 1         7 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       15 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       12 if ( $act eq 'add' ) {
836 2 100       7 if ( $host->{statuses}{$st} ) {
837 1         5 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     29 if ( ( scalar( @a4 ) + scalar( @a6 ) ) == 0 and ( scalar( @d4 ) + scalar( @d6 ) > 0 ) ) {
854 1 50       3 if ( ( scalar( @d4 ) + scalar( @d6 ) ) == ( scalar( keys %{$host->{addr_v4}} ) + scalar( keys %{$host->{addr_v6}} ) ) ) {
  1         4  
  1         4  
855 1         5 return _fail_answ( $cltrid, '2003', 'Required parameter missing' );
856             }
857             }
858              
859 3 50 33     15 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         7 $host->{addr_v4}{$_} = '+' for @a4;
898              
899 3         5 $host->{addr_v6}{$_} = '+' for @a6;
900              
901 3         7 $host->{statuses}{$_} = '+' for @ast;
902              
903 3         6 delete $host->{addr_v4}{$_} for @d4;
904              
905 3         6 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         8 my @chb = _check_body( \$body );
917              
918 3         4 my $cltrid;
919              
920 3 50       8 if ( $chb[0] ) {
921 0         0 return @chb;
922             }
923             else {
924 3         4 $cltrid = $chb[1];
925             }
926              
927 3         4 my $ns;
928              
929 3 50       14 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       12 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         7 my $srv_url = $obj->{sock};
945 3         11 my $s = new IO::EPP::Test::Server( $srv_url );
946              
947 3 100       15 unless ( $s->data->{nss}{$ns} ) {
948 1         6 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
949             }
950              
951 2         6 my $host = $s->data->{nss}{$ns};
952              
953 2 100       10 if ( $host->{owner} ne $obj->{user} ) {
954 1         4 return _fail_answ( $cltrid, '2201', 'Authorization error' );
955             }
956              
957 1 50       5 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       5 if ( $ns =~ /\b(com|net|edu)$/ ) {
964 1         6 ( $dname ) = $ns =~ /\.([0-9a-z\-]+\.[a-z]+)$/;
965              
966 1         3 my $doms = $s->data->{doms};
967              
968 1         4 delete $doms->{$dname}{hosts}{$ns};
969             }
970              
971 1         3 delete $s->data->{nss}{$ns};
972              
973 1         3 my $svtrid = get_svtrid();
974              
975 1         5 return _min_answ( $cltrid );
976             }
977              
978              
979             sub domain_check {
980 1     1 0 3 my ( $obj, $body ) = @_;
981              
982 1         3 my @chb = _check_body( \$body );
983              
984 1         2 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         9 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         6 my $s = new IO::EPP::Test::Server( $srv_url );
1001 1         5 my $doms = $s->data->{doms};
1002              
1003 1         3 my $answ_list = '';
1004 1         3 foreach my $row ( @domains ) {
1005 6         17 my ( $dm ) = $row =~ m|([^<>]+)|;
1006              
1007 6         11 my ( $avail, $reason );
1008              
1009 6 50       35 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         2 $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       11 $avail = int( rand( 10 ) ) > 1 ? 1 : 0; # 10% are not avail
1023              
1024 4 100       6 if ( $avail ) {
1025 3         4 $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         1 $avail = 0;
1036 1         2 $reason = 'Not an authoritative TLD';
1037             }
1038              
1039 6         17 $answ_list .= qq|$dm$reason|;
1040             }
1041              
1042 1         18 return _ok_answ( $cltrid, qq|$answ_list| );
1043             }
1044              
1045              
1046             sub domain_create {
1047 9     9 0 12 my ( $obj, $body ) = @_;
1048              
1049 9         47 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1050 9         24 my ( $lang ) = $body =~ m|]+">([A-Z]{3})|;
1051              
1052 9         20 my @chb = _check_body( \$body );
1053              
1054 9         13 my $cltrid;
1055              
1056 9 50       16 if ( $chb[0] ) {
1057 0         0 return @chb;
1058             }
1059             else {
1060 9         12 $cltrid = $chb[1];
1061             }
1062              
1063 9         9 my $dname;
1064 9 50       31 if ( $body =~ m|([^<>]*)| ) {
1065 9         20 $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       17 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       28 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1076 1         5 return _fail_answ_with_reason( $cltrid, '2005', 'Parameter value syntax error', 'Domain name contains an invalid DNS character' );
1077             }
1078              
1079 8         21 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1080              
1081 8 100       20 if ( $tld ne lc( $subProduct ) ) {
1082 2         5 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Subproduct ID does not match the domain TLD' );
1083             }
1084              
1085 6         8 my $period;
1086 6 50       18 if ( $body =~ m|([^<>]*)| ) {
1087 6         11 $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     26 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       14 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       10 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       12 if ( $period > 10 ) {
1106 1         5 return _fail_answ( $cltrid, '2306', 'Parameter value policy error' );
1107             }
1108              
1109 5         5 my @nss;
1110 5 100       17 if ( $body =~ m|(.+)|s ) {
1111 2         4 my $nss = $1;
1112              
1113 2         11 my @rows = $body =~ m|(.*)|g;
1114              
1115 2         5 foreach my $row ( @rows ) {
1116 4 50       7 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       18 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         9 push @nss, $row;
1125             }
1126             }
1127              
1128 5         6 my $authinfo;
1129 5 50       18 if ( $body =~ m|(.*)|s ) {
1130 5         12 my $row = $1;
1131              
1132 5 50 33     22 if ( $row && $row =~ m|(.*)|s ) {
1133 5         9 $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     35 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         8 my $srv_url = $obj->{sock};
1152 4         15 my $s = new IO::EPP::Test::Server( $srv_url );
1153 4         8 my $hosts = $s->data->{nss};
1154 4         8 my $doms = $s->data->{doms};
1155              
1156 4 100 66     15 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     10 if ( $doms->{$dname} || $dname =~ /^reg/ ) {
1161 1         3 return _fail_answ( $cltrid, '2302', 'Object exists' );
1162             }
1163              
1164 2         4 my %nss;
1165 2         3 foreach my $ns ( @nss ) {
1166 3 100       8 unless ( $hosts->{$ns} ) {
1167 1         5 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         4 my $cre_date = get_date();
1174 1         5 my $exp_date = add_y( $cre_date, 1 );
1175              
1176 1         9 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         16 avail => 0,
1191             reason => 'Domain exists',
1192             };
1193              
1194 1         4 foreach my $ns ( keys %nss ) {
1195 2         7 $hosts->{$ns}{statuses}{linked}++;
1196             }
1197              
1198 1         8 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 25 my ( $obj, $body ) = @_;
1210              
1211 10         57 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1212              
1213 10         41 my @chb = _check_body( \$body );
1214              
1215 10         17 my $cltrid;
1216              
1217 10 50       20 if ( $chb[0] ) {
1218 0         0 return @chb;
1219             }
1220             else {
1221 10         15 $cltrid = $chb[1];
1222             }
1223              
1224 10         15 my ( $show_hosts, $dname );
1225 10 50       57 if ( $body =~ m|([^<>]*)| ) {
1226 10 50       25 $show_hosts = lc $2 if $2;
1227 10         26 $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       34 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       32 if ( $tld ne lc( $subProduct ) ) {
1244 1         5 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value syntax error', 'Incorrect NameStore Extension' );
1245             }
1246              
1247 8         16 my $srv_url = $obj->{sock};
1248 8         34 my $s = new IO::EPP::Test::Server( $srv_url );
1249              
1250 8 100       19 unless ( $s->data->{doms}{$dname} ) {
1251 1         4 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1252             }
1253              
1254 7         22 _check_dom_dates( $s, $dname );
1255              
1256 7 50       22 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       20 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         13 my $answ = '';
1268 7         32 $answ .= "" . uc( $dname ) . "";
1269 7         18 $answ .= ''.$dm->{roid}.'';
1270 7         10 $answ .= qq|| for ( sort keys %{$dm->{statuses}} );
  7         46  
1271 7 50       12 if ( scalar( keys %{$dm->{nss}} ) ) {
  7         20  
1272 7         13 $answ .= '';
1273              
1274 7         10 foreach my $ns ( sort keys %{$dm->{nss}} ) {
  7         109  
1275 14         28 $answ .= "$ns";
1276             }
1277              
1278 7         14 $answ .= '';
1279             }
1280 7 50 33     23 if ( !$show_hosts or $show_hosts ne 'none' ) {
1281 7         11 foreach my $host ( sort keys %{$dm->{hosts}} ) {
  7         14  
1282 3         6 $answ .= "$host";
1283             }
1284             }
1285 7         18 $answ .= "$$dm{owner}";
1286 7         17 $answ .= "$$dm{creater}";
1287 7         16 $answ .= "$$dm{cre_date}";
1288 7         14 $answ .= "$$dm{updater}";
1289 7         17 $answ .= "$$dm{upd_date}";
1290 7         67 $answ .= "$$dm{exp_date}";
1291 7 50       17 $answ .= "$$dm{tr_date}" if $dm->{tr_date};
1292 7         19 $answ .= "$$dm{authInfo}";
1293 7         10 $answ .= '';
1294              
1295 7         10 my $rgp = '';
1296 7         11 my $now = get_date();
1297              
1298 7         22 my $c5d = add_5d( $$dm{cre_date} );
1299 7 50       20 if ( $now lt $c5d ) {
1300 7         18 $rgp .= 'endDate=' . $c5d . '';
1301             }
1302              
1303 7 100       31 my $r5d = $$dm{ren_date} ? add_5d( $$dm{ren_date} ) : '';
1304 7 100 66     27 if ( $r5d and $now lt $r5d ) {
1305 5         15 $rgp .= 'endDate=' . $r5d . '';
1306             }
1307              
1308 7 50       16 my $t5d = $$dm{tr_date} ? add_5d( $$dm{tr_date} ) : '';
1309 7 50 33     17 if ( $t5d and $now lt $t5d ) {
1310 0         0 $rgp .= 'endDate=' . $t5d . '';
1311             }
1312              
1313 7 50       18 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       19 if ( $dm->{statuses}{pendingDelete} ) {
1319 2         5 my $d5d = add_5d( $dm->{del_date} );
1320              
1321 2 50       6 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       14 if ( $rgp ) {
1333 7         28 $rgp = qq|$rgp|;
1334             }
1335              
1336 7         21 return _ok_answ( $cltrid, $answ, $rgp );
1337             }
1338              
1339              
1340              
1341             sub domain_renew {
1342 6     6 0 9 my ( $obj, $body ) = @_;
1343              
1344 6         57 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       11 if ( $chb[0] ) {
1351 0         0 return @chb;
1352             }
1353             else {
1354 6         10 $cltrid = $chb[1];
1355             }
1356              
1357 6         7 my $dname;
1358 6 50       20 if ( $body =~ m|([^<>]*)| ) {
1359 6         16 $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       13 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       29 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1370 1         5 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1371             }
1372              
1373 5         14 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1374              
1375 5 50       16 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         6 my $user_edt;
1380 5 50       17 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         9 my ( $yy, $mm, $dd );
1388 5 50       20 if ( $user_edt =~ /(\d{4})-(\d{2})-(\d{2})/ ) {
1389 5         12 ( $yy, $mm, $dd ) = ( $1, $2, $3 );
1390             }
1391              
1392 5 100 33     67 unless ( $yy && $yy >= 1000 && $yy <= 9999 and $mm && $mm <= 13 and $dd && $dd <= 31 ) {
      33        
      66        
      66        
      33        
      66        
1393 1         7 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         5 my $period;
1397 4 50       15 if ( $body =~ m|(\d+)| ) {
1398 4         8 $period = $1;
1399             }
1400             else {
1401 0         0 $period = 1;
1402             }
1403              
1404 4 100 66     14 if ( $period < 1 || $period > 10 ) {
1405 1         3 return _fail_answ( $cltrid, '2306', 'Parameter value policy error' );
1406             }
1407              
1408 3         8 my $srv_url = $obj->{sock};
1409 3         12 my $s = new IO::EPP::Test::Server( $srv_url );
1410              
1411 3 50       9 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         7 my $dm = $s->data->{doms}{$dname};
1422              
1423 3 50       9 if ( $dm->{owner} ne $obj->{user} ) {
1424 0         0 return _fail_answ( $cltrid, '2201', 'Authorization error' );
1425             }
1426              
1427 3 50 33     17 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         13 my ( $edt ) = $dm->{exp_date} =~ /^(\d{4}-\d{2}-\d{2})/;
1436              
1437 2 100       6 if ( $user_edt ne $edt ) {
1438 1         3 return _fail_answ( $cltrid, '2004', 'Wrong curExpDate provided' );
1439             }
1440              
1441 1         3 my $now = get_date();
1442              
1443 1         6 my ( $y0 ) = $now =~ /^(\d{4})/;
1444 1         4 my ( $y1 ) = $dm->{exp_date} =~ /^(\d{4})/;
1445              
1446 1 50       4 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         4 $dm->{exp_date} = add_y( $dm->{exp_date}, $period );
1452              
1453 1         2 my $answ = qq|
1454             |;
1455 1         4 $answ .= " " . uc( $dname ) . "\n";
1456 1         4 $answ .= " " . $dm->{exp_date} . "\n";
1457 1         2 $answ .= " \n";
1458              
1459 1         4 return _ok_answ2( $cltrid, $answ );
1460             }
1461              
1462              
1463             sub domain_update {
1464 19     19 0 30 my ( $obj, $body ) = @_;
1465              
1466 19         100 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1467              
1468 19         27 my $rgp = '';
1469 19 100       76 if ( $body =~ m|]+>\s*(.+)\s*|s ) { $rgp = $1; }
  2         7  
1470              
1471 19         43 my @chb = _check_body( \$body );
1472              
1473 19         26 my $cltrid;
1474              
1475 19 50       60 if ( $chb[0] ) {
1476 0         0 return @chb;
1477             }
1478             else {
1479 19         27 $cltrid = $chb[1];
1480             }
1481              
1482 19         21 my $dname;
1483 19 50       63 if ( $body =~ m|([^<>]*)| ) {
1484 19         46 $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       32 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       57 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         54 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1499              
1500 18 100       48 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         35 my %add;
1505             my %rem;
1506 17         0 my %chg;
1507              
1508 17 100       81 if ( $body =~ m|\s*(.+)\s*|s ) {
1509 7         15 my $add = $1;
1510              
1511 7 50       21 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         18 my @sts = $add =~ m|()|s;
1516              
1517 7         17 for my $row ( @sts ) {
1518 1         3 my ( $st, $reason );
1519              
1520 1 50       6 if ( $row =~ m|| ) {
1521 1         3 $st = $1;
1522 1         3 $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         5 $add{statuses}{$st} = $reason;
1530             }
1531              
1532 7         14 undef @sts;
1533              
1534 7         21 @sts = $add =~ m|([^<>]*)|s;
1535              
1536 7         11 for my $row ( @sts ) {
1537 2         3 my ( $st, $reason );
1538              
1539 2 50       9 if ( $row =~ m|([^<>]*)| ) {
1540 2         4 $st = $1;
1541 2   50     5 $reason = $2 || '+';
1542             }
1543              
1544 2 100       7 unless ( $statuses{$st} ) {
1545 1         8 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       25 if ( $add =~ m|(.+)|s ) {
1552 4         10 my $nss = $1;
1553              
1554 4         16 my @nss = $nss =~ m|([^<>]*)|s;
1555              
1556 4         7 my @hosts;
1557 4         7 for my $row ( @nss ) {
1558 4 50       17 if ( $row =~ m|([^<>]+)| ) {
1559 4         12 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         8 for my $ns ( @hosts ) {
1567 4 50       13 if ( $ns =~ /^[0-9a-z.\-]+$/ ) {
1568 4         16 $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       58 if ( $body =~ m|\s*(.+)\s*|s ) {
1578 4         12 my $rem = $1;
1579              
1580 4 50       14 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         14 my @sts = $rem =~ m|(]*>)|s;
1585              
1586 4         10 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       5 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         4 $rem{statuses}{$st} = '+';
1598             }
1599              
1600 4 100       31 if ( $rem =~ m|(.+)|s ) {
1601 3         6 my $nss = $1;
1602              
1603 3         11 my @nss = $nss =~ m|([^<>]*)|s;
1604              
1605 3         7 my @hosts;
1606 3         5 for my $row ( @nss ) {
1607 3 50       10 if ( $row =~ m|([^<>]+)| ) {
1608 3         19 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         7 for my $ns ( @hosts ) {
1616 3 50       12 if ( $ns =~ /^[0-9a-z.\-]+$/ ) {
1617 3         12 $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       43 if ( $body =~ m|\s*(.+)\s*|s ) {
1627 4         10 my $chg = $1;
1628              
1629 4 100       10 if ( $chg =~ /domain:registrant/ ) {
1630 1         6 return _fail_answ_with_reason( $cltrid, '2102', 'Unimplemented option', "Subproduct dot".$subProduct." does NOT support contacts." );
1631             }
1632              
1633 3 50       13 if ( $chg =~ m|([^<>]*)|s ) {
1634 3         4 my $key = $1;
1635              
1636 3 100 66     17 unless ( $key and length( $key ) >= 16 and length( $key ) <= 48 ) {
      66        
1637 1         4 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Invalid Auth Info' );
1638             }
1639              
1640 2 50 66     18 unless ( $key =~ /[a-z]/ and $key =~ /[A-Z]/ and $key =~ /[0-9]/ and $key =~ /["'.,\-\[\]\\|\/!?\$\%\@*()+=_{}:;]/ ) {
      66        
      33        
1641 1         5 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', 'Invalid Auth Info' );
1642             }
1643              
1644 1         4 $chg{authInfo} = $key;
1645             }
1646             }
1647              
1648 13 100 100     51 unless ( scalar( keys %add ) + scalar( keys %rem ) + scalar( keys %chg ) or $rgp ) {
1649 1         3 return _fail_answ_with_reason( $cltrid, '2003', 'Required parameter missing', 'empty non-extended update is not allowed' );
1650             }
1651              
1652 12         49 my $s = new IO::EPP::Test::Server( $obj->{sock} );
1653              
1654 12 100       27 unless ( $s->data->{doms}{$dname} ) {
1655 1         3 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1656             }
1657              
1658 11         30 _check_dom_dates( $s, $dname );
1659              
1660 11 50       31 unless ( $s->data->{doms}{$dname} ) {
1661 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1662             }
1663              
1664 11         23 my $dom = $s->data->{doms}{$dname};
1665 11         21 my $nss = $s->data->{nss};
1666              
1667 11 50       30 if ( $dom->{owner} ne $obj->{user} ) {
1668 0         0 return _fail_answ( $cltrid, '2201', 'Authorization error' );
1669             }
1670              
1671 11 100       20 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       16 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         4 $dom->{statuses}{pendingRestore} = '+';
1689 1         2 $dom->{upd_date} = get_date();
1690              
1691 1         4 return _min_answ( $cltrid );
1692             }
1693              
1694 1 50       5 if ( $rgp =~ /restore op="report"/ ) {
1695 1 50       4 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       6 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         3 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     48 if ( $dom->{statuses}{serverUpdateProhibited} or $dom->{statuses}{clientUpdateProhibited} and not $rem{statuses}{clientUpdateProhibited} ) {
      66        
1718 1         17 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1719             }
1720              
1721 8         14 foreach my $st ( keys %{$add{statuses}} ) {
  8         32  
1722 1 50       5 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         13 foreach my $st ( keys %{$rem{statuses}} ) {
  8         20  
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         15 foreach my $ns ( keys %{$add{nss}} ) {
  8         25  
1734 3 100       9 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       7 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         13 foreach my $ns ( keys %{$rem{nss}} ) {
  7         18  
1744 3 100       11 unless ( $dom->{nss}{$ns} ) {
1745 1         12 return _fail_answ_with_reason( $cltrid, '2306', 'Parameter value policy error', "$ns ns not found" );
1746             }
1747             }
1748              
1749             # order not change!
1750 6         9 $dom->{statuses}{$_} = $add{statuses}{$_} foreach keys %{$add{statuses}};
  6         19  
1751              
1752 6         8 delete $dom->{statuses}{$_} foreach keys %{$rem{statuses}};
  6         13  
1753              
1754 6 100 100     20 if ( $dom->{statuses}{ok} and scalar( keys %{$dom->{statuses}} ) > 1 ) {
  5         32  
1755 1         2 delete $dom->{statuses}{ok};
1756             }
1757              
1758 6 100       9 unless ( scalar( keys %{$dom->{statuses}} ) ) {
  6         20  
1759 1         3 $dom->{statuses}{ok} = '+';
1760             }
1761              
1762 6         7 foreach my $ns ( keys %{$add{nss}} ) {
  6         16  
1763 2         5 $dom->{nss}{$ns} = '+';
1764              
1765 2         7 $nss->{$ns}{statuses}{linked}++;
1766             }
1767              
1768 6         9 foreach my $ns ( keys %{$rem{nss}} ) {
  6         13  
1769 2         4 delete $dom->{nss}{$ns};
1770              
1771 2         5 $nss->{$ns}{statuses}{linked}--;
1772              
1773 2 50       8 delete $nss->{$ns}{statuses}{linked} if $nss->{$ns}{statuses}{linked} == 0;
1774             }
1775              
1776 6 100       17 $dom->{authInfo} = $chg{authInfo} if $chg{authInfo};
1777              
1778 6         11 $dom->{upd_date} = get_date();
1779 6         15 $dom->{updater} = $obj->{user};
1780              
1781 6         18 return _min_answ( $cltrid );
1782             }
1783              
1784              
1785             sub domain_delete {
1786 6     6 0 12 my ( $obj, $body ) = @_;
1787              
1788 6         33 my ( $subProduct ) = $body =~ m|dot([A-Z]+)|;
1789              
1790 6         15 my @chb = _check_body( \$body );
1791              
1792 6         10 my $cltrid;
1793              
1794 6 50       12 if ( $chb[0] ) {
1795 0         0 return @chb;
1796             }
1797             else {
1798 6         9 $cltrid = $chb[1];
1799             }
1800              
1801 6         6 my $dname;
1802 6 50       21 if ( $body =~ m|([^<>]*)| ) {
1803 6         13 $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       11 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       21 unless ( $dname =~ /^[0-9a-z][0-9a-z\-]*[0-9a-z]\.[0-9a-z][0-9a-z\-]+[0-9a-z]$/ ) {
1814 1         6 return _fail_answ( $cltrid, '2005', 'Parameter value syntax error' );
1815             }
1816              
1817 5         15 my ( $tld ) = $dname =~ /\.([0-9a-z\-]+)$/;
1818              
1819 5 50       13 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         47 my $s = new IO::EPP::Test::Server( $obj->{sock} );
1824              
1825 5 100       10 unless ( $s->data->{doms}{$dname} ) {
1826 1         4 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1827             }
1828              
1829 4         10 _check_dom_dates( $s, $dname );
1830              
1831 4 50       12 unless ( $s->data->{doms}{$dname} ) {
1832 0         0 return _fail_answ( $cltrid, '2303', 'Object does not exist' );
1833             }
1834              
1835 4         10 my $dom = $s->data->{doms}{$dname};
1836 4         10 my $nss = $s->data->{nss};
1837              
1838 4 100       12 if ( $dom->{owner} ne $obj->{user} ) {
1839 1         3 return _fail_answ( $cltrid, '2201', 'Authorization error' );
1840             }
1841              
1842 3 50       7 if ( $dom->{hosts} ) {
1843              
1844 3         5 for my $h ( keys %{$dom->{hosts}} ) {
  3         9  
1845              
1846 3 100       10 if ( $nss->{$h}{statuses}{linked} ) {
1847 1         4 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     22 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         5 return _fail_answ( $cltrid, '2304', 'Object status prohibits operation' );
1854             }
1855              
1856 1         3 for my $ns ( keys %{$dom->{hosts}} ) {
  1         3  
1857 1 50       4 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         2 $dom->{del_date} = $dom->{upd_date} = get_date();
1868 1         3 $dom->{updater} = $obj->{user};
1869              
1870 1         3 return _min_answ( $cltrid );
1871             }
1872              
1873              
1874             sub logout {
1875 28     28 0 54 my ( $body ) = @_;
1876              
1877 28 50       165 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       165 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       175 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       99 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       134 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         103 my ( $cltrid ) = $body =~ m|([0-9A-Za-z\-]+)|;
1908              
1909 28 50       56 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       99 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         53 my $svtrid = get_svtrid();
1922              
1923 28         76 return qq|Command completed successfully; ending session$cltrid$svtrid|;
1924             }
1925              
1926             1;