File Coverage

blib/lib/Net/DRI/Protocol/EPP/Extensions/AFNIC/Domain.pm
Criterion Covered Total %
statement 15 166 9.0
branch 0 64 0.0
condition 0 26 0.0
subroutine 5 26 19.2
pod 0 21 0.0
total 20 303 6.6


line stmt bran cond sub pod time code
1             ## Domain Registry Interface, AFNIC EPP Domain extensions
2             ##
3             ## Copyright (c) 2008-2010,2012,2013,2016 Patrick Mevzek . All rights reserved.
4             ##
5             ## This file is part of Net::DRI
6             ##
7             ## Net::DRI is free software; you can redistribute it and/or modify
8             ## it under the terms of the GNU General Public License as published by
9             ## the Free Software Foundation; either version 2 of the License, or
10             ## (at your option) any later version.
11             ##
12             ## See the LICENSE file that comes with this distribution for more details.
13             ####################################################################################################
14              
15             package Net::DRI::Protocol::EPP::Extensions::AFNIC::Domain;
16              
17 1     1   888 use strict;
  1         1  
  1         23  
18 1     1   3 use warnings;
  1         0  
  1         19  
19 1     1   4 use feature 'state';
  1         1  
  1         64  
20              
21 1     1   3 use Net::DRI::Util;
  1         1  
  1         14  
22 1     1   3 use Net::DRI::Exception;
  1         1  
  1         1741  
23              
24             =pod
25              
26             =head1 NAME
27              
28             Net::DRI::Protocol::EPP::Extensions::AFNIC::Domain - AFNIC (.FR/.RE/.TF/.WF/.PM/.YT) EPP Domain extensions for Net::DRI
29              
30             =head1 DESCRIPTION
31              
32             Please see the README file for details.
33              
34             =head1 SUPPORT
35              
36             For now, support questions should be sent to:
37              
38             Enetdri@dotandco.comE
39              
40             Please also see the SUPPORT file in the distribution.
41              
42             =head1 SEE ALSO
43              
44             Ehttp://www.dotandco.com/services/software/Net-DRI/E
45              
46             =head1 AUTHOR
47              
48             Patrick Mevzek, Enetdri@dotandco.comE
49              
50             =head1 COPYRIGHT
51              
52             Copyright (c) 2008-2010,2012,2013,2016 Patrick Mevzek .
53             All rights reserved.
54              
55             This program is free software; you can redistribute it and/or modify
56             it under the terms of the GNU General Public License as published by
57             the Free Software Foundation; either version 2 of the License, or
58             (at your option) any later version.
59              
60             See the LICENSE file that comes with this distribution for more details.
61              
62             =cut
63              
64             ####################################################################################################
65              
66             sub register_commands
67             {
68 0     0 0   my ($class,$version)=@_;
69 0           state $rops = { domain => {
70             create => [ \&create, undef ],
71             update => [ \&update, undef ],
72             transfer_request => [ \&transfer_request, undef ],
73             trade_request => [ \&trade_request, \&trade_parse ],
74             trade_query => [ \&trade_query, \&trade_parse ],
75             trade_cancel => [ \&trade_cancel, undef ],
76             recover_request => [ \&recover_request, \&recover_parse],
77             check => [ undef, \&check_parse],
78             check_multi => [ undef, \&check_parse],
79             info => [ undef, \&info_parse],
80             }
81             };
82              
83 0           return $rops;
84             }
85              
86             ####################################################################################################
87              
88             sub build_command_extension
89             {
90 0     0 0   my ($mes,$epp,$tag)=@_;
91 0           return $mes->command_extension_register($tag,sprintf('xmlns:frnic="%s" xsi:schemaLocation="%s %s"',$mes->nsattrs('frnic')));
92             }
93              
94             sub build_domain
95             {
96 0     0 0   my ($domain)=@_;
97 0 0 0       Net::DRI::Exception->die(1,'protocol/EPP',2,'Domain name needed') unless defined($domain) && $domain;
98 0 0         Net::DRI::Exception->die(1,'protocol/EPP',10,'Invalid domain name: '.$domain) unless Net::DRI::Util::is_hostname($domain);
99 0           return ['frnic:name',$domain];
100             }
101              
102             sub build_registrant
103             {
104 0     0 0   my ($rd)=@_;
105 0 0         Net::DRI::Exception::usererr_invalid_parameters('AFNIC needs contacts for domain operations') unless Net::DRI::Util::has_contact($rd);
106 0           my @t=$rd->{contact}->get('registrant');
107 0 0 0       Net::DRI::Exception::usererr_invalid_parameters('AFNIC needs one contact of type registrant') unless (@t==1 && Net::DRI::Util::isa_contact($t[0],'Net::DRI::Data::Contact::AFNIC'));
108 0           $t[0]->validate_registrant();
109 0 0         Net::DRI::Exception::usererr_invalid_parameters('Registrant contact must have an id') unless length $t[0]->srid();
110 0           return ['frnic:registrant',$t[0]->srid()];
111             }
112              
113             sub build_cltrid
114             {
115 0     0 0   my ($mes)=@_;
116 0           return (['frnic:clTRID',$mes->cltrid()]);
117             }
118              
119             sub verify_contacts
120             {
121 0     0 0   my $rd=shift;
122 0 0         Net::DRI::Exception::usererr_invalid_parameters('AFNIC needs contacts for domain operations') unless Net::DRI::Util::has_contact($rd);
123 0           my @t=$rd->{contact}->get('admin');
124 0 0 0       Net::DRI::Exception::usererr_invalid_parameters('AFNIC needs one contact of type admin, and only one') unless (@t==1 && Net::DRI::Util::isa_contact($t[0],'Net::DRI::Data::Contact::AFNIC'));
125 0           @t=grep { Net::DRI::Util::isa_contact($_,'Net::DRI::Data::Contact::AFNIC') } $rd->{contact}->get('tech');
  0            
126 0 0 0       Net::DRI::Exception::usererr_invalid_parameters('AFNIC needs one to three contacts of type tech') unless (@t >= 1 && @t <= 3);
127 0           return;
128             }
129              
130             sub build_contacts
131             {
132 0     0 0   my ($rd)=@_;
133 0           my $cs=$rd->{contact};
134 0           my @n;
135 0           push @n,['frnic:contact',{type => 'admin'},$cs->get('admin')->srid()]; ## only one admin allowed
136 0           push @n,map { ['frnic:contact',{type => 'tech'},$_->srid()] } $cs->get('tech'); ## 1 to 3 allowed
  0            
137 0           return @n;
138             }
139              
140             sub build_authinfo
141             {
142 0     0 0   my ($mes, $rd, $what)=@_;
143 0 0 0       Net::DRI::Exception::usererr_invalid_parameters('authInfo is mandatory for a "'.$what.'"') unless (Net::DRI::Util::has_auth($rd) && exists($rd->{auth}->{pw}) && $rd->{auth}->{pw});
      0        
144 0           return ['frnic:authInfo',['domain:pw',{'xmlns:domain'=>($mes->nsattrs('domain'))[0]},$rd->{auth}->{pw}]];
145             }
146              
147             sub create
148             {
149 0     0 0   my ($epp,$domain,$rd)=@_;
150 0           my $mes=$epp->message();
151              
152             ## We just make sure that we have all contact data
153 0           verify_contacts($rd);
154 0           build_registrant($rd);
155 0           return;
156             }
157              
158             sub update
159             {
160 0     0 0   my ($epp,$domain,$todo)=@_;
161 0           my $mes=$epp->message();
162              
163             ## We just verify that if we do a redemption, we only use op=request, because RFC3915 allows also op=report
164 0           my $rgp=$todo->set('rgp');
165 0 0 0       return unless (defined($rgp) && $rgp && (ref($rgp) eq 'HASH'));
      0        
166 0   0       my $op=$rgp->{op} || '';
167 0 0         Net::DRI::Exception::usererr_invalid_parameters('RGP op can only be request for AFNIC') unless ($op eq 'request');
168 0           return;
169             }
170              
171             sub add_keepds
172             {
173 0     0 0   my ($op,$rd)=@_;
174 0 0         Net::DRI::Exception::usererr_insufficient_parameters('Domain "'.$op.'" operation needs a keep_ds attribute') unless Net::DRI::Util::has_key($rd,'keep_ds');
175 0 0         Net::DRI::Exception::usererr_invalid_parameters('keep_ds attribute must be boolean, not '.$rd->{keep_ds}) unless Net::DRI::Util::xml_is_boolean($rd->{keep_ds});
176              
177 0           return { 'keepDS' => $rd->{keep_ds} };
178             }
179              
180             sub transfer_request
181             {
182 0     0 0   my ($epp,$domain,$rd)=@_;
183 0           my $mes=$epp->message();
184              
185 0           verify_contacts($rd);
186 0           my $eid=build_command_extension($mes,$epp,'frnic:ext');
187 0           $mes->command_extension($eid,['frnic:transfer',['frnic:domain',add_keepds('transfer',$rd),build_contacts($rd)]]);
188 0           return;
189             }
190              
191             sub parse_trade_recover
192             {
193 0     0 0   my ($po,$otype,$oaction,$oname,$rinfo,$s)=@_;
194 0           my $mes=$po->message();
195              
196 0           my $infdata=$mes->get_extension('frnic','ext');
197 0 0         return unless defined $infdata;
198              
199 0           my $ns=$mes->ns('frnic');
200 0           $infdata=Net::DRI::Util::xml_traverse($infdata,$ns,'resData',$s,'domain');
201 0 0         return unless defined $infdata;
202              
203 0           foreach my $el (Net::DRI::Util::xml_list_children($infdata))
204             {
205 0           my ($name,$c)=@$el;
206 0 0         if ($name eq 'name')
    0          
    0          
    0          
207             {
208 0           $oname=lc($c->textContent());
209 0           $rinfo->{domain}->{$oname}->{action}=$oaction;
210 0           $rinfo->{domain}->{$oname}->{exist}=1;
211             } elsif ($name eq 'trStatus')
212             {
213 0           $rinfo->{domain}->{$oname}->{$name}=$c->textContent();
214             } elsif ($name=~m/^(reID|reHldID|acID|acHldID)$/)
215             {
216 0           $rinfo->{domain}->{$oname}->{$name}=$c->textContent();
217             } elsif ($name=~m/^(reDate|rhDate|ahDate)$/)
218             {
219 0           $rinfo->{domain}->{$oname}->{$name}=$po->parse_iso8601($c->textContent());
220             }
221             }
222 0           return;
223             }
224              
225             sub trade_request
226             {
227 0     0 0   my ($epp,$domain,$rd)=@_;
228 0           my $mes=$epp->message();
229              
230 0           my $eid=build_command_extension($mes,$epp,'frnic:ext');
231 0           my @n=build_domain($domain);
232              
233 0           push @n,build_registrant($rd);
234 0           push @n,build_authinfo($mes, $rd, 'trade request');
235 0           $mes->command_extension($eid,['frnic:command',['frnic:trade',{op=>'request'},['frnic:domain',@n]],build_cltrid($mes)]);
236 0           return;
237             }
238              
239             sub trade_query
240             {
241 0     0 0   my ($epp,$domain,$rd)=@_;
242 0           my $mes=$epp->message();
243              
244 0           my $eid=build_command_extension($mes,$epp,'frnic:ext');
245 0           my @n=build_domain($domain);
246 0           push @n,build_authinfo($mes, $rd, 'trade query');
247 0           $mes->command_extension($eid,['frnic:command',['frnic:trade',{op=>'query'},['frnic:domain',@n]],build_cltrid($mes)]);
248 0           return;
249             }
250              
251             sub trade_cancel
252             {
253 0     0 0   my ($epp,$domain,$rd)=@_;
254 0           my $mes=$epp->message();
255              
256 0           my $eid=build_command_extension($mes,$epp,'frnic:ext');
257 0           my @n=build_domain($domain);
258 0           push @n,build_authinfo($mes, $rd, 'trade cancel');
259 0           $mes->command_extension($eid,['frnic:command',['frnic:trade',{op=>'cancel'},['frnic:domain',@n]],build_cltrid($mes)]);
260 0           return;
261             }
262              
263             sub trade_parse
264             {
265 0     0 0   my ($po,$otype,$oaction,$oname,$rinfo)=@_;
266 0           my $mes=$po->message();
267 0 0         return unless $mes->is_success();
268              
269 0           parse_trade_recover($po,$otype,'trade',$oname,$rinfo,'trdData');
270 0           return;
271             }
272              
273             sub recover_request
274             {
275 0     0 0   my ($epp,$domain,$rd)=@_;
276 0           my $mes=$epp->message();
277              
278 0           my $eid=build_command_extension($mes,$epp,'frnic:ext');
279 0           my @n=build_domain($domain);
280 0           push @n,build_authinfo($mes, $rd, 'recover request');
281 0           push @n,build_registrant($rd);
282 0           push @n,build_contacts($rd);
283 0           $mes->command_extension($eid,['frnic:command',['frnic:recover',{op=>'request'},['frnic:domain',add_keepds('recover',$rd),@n]],build_cltrid($mes)]);
284 0           return;
285             }
286              
287             sub recover_parse
288             {
289 0     0 0   my ($po,$otype,$oaction,$oname,$rinfo)=@_;
290 0           my $mes=$po->message();
291 0 0         return unless $mes->is_success();
292              
293 0           parse_trade_recover($po,$otype,'recover',$oname,$rinfo,'recData');
294 0           return;
295             }
296              
297             sub check_parse
298             {
299 0     0 0   my ($po,$otype,$oaction,$oname,$rinfo)=@_;
300 0           my $mes=$po->message();
301 0 0         return unless $mes->is_success();
302              
303 0           my $chkdata=$mes->get_extension('frnic','ext');
304 0 0         return unless defined $chkdata;
305              
306 0           my $ns=$mes->ns('frnic');
307 0           $chkdata=Net::DRI::Util::xml_traverse($chkdata,$ns,'resData','chkData','domain');
308 0 0         return unless defined $chkdata;
309              
310 0           foreach my $cd ($chkdata->getChildrenByTagNameNS($ns,'cd'))
311             {
312 0           my (@r,@f,$domain);
313 0           foreach my $el (Net::DRI::Util::xml_list_children($cd))
314             {
315 0           my ($n,$c)=@$el;
316 0 0         if ($n eq 'name')
    0          
    0          
317             {
318 0           $domain=lc($c->textContent());
319 0           $rinfo->{domain}->{$domain}->{action}='check';
320 0           $rinfo->{domain}->{$domain}->{reserved}=Net::DRI::Util::xml_parse_boolean($c->getAttribute('reserved'));
321 0           $rinfo->{domain}->{$domain}->{forbidden}=Net::DRI::Util::xml_parse_boolean($c->getAttribute('forbidden'));
322             } elsif ($n eq 'rsvReason')
323             {
324 0           push @r,$c->textContent();
325             } elsif ($n eq 'fbdReason')
326             {
327 0           push @f,$c->textContent();
328             }
329             }
330              
331             ## There may be multiple of them !
332 0 0         $rinfo->{domain}->{$domain}->{reserved_reason}=join("\n",@r) if @r;
333 0 0         $rinfo->{domain}->{$domain}->{forbidden_reason}=join("\n",@f) if @f;
334             }
335 0           return;
336             }
337              
338             sub info_parse
339             {
340 0     0 0   my ($po,$otype,$oaction,$oname,$rinfo)=@_;
341 0           my $mes=$po->message();
342 0 0         return unless $mes->is_success();
343              
344 0           my $infdata=$mes->get_extension('frnic','ext');
345 0 0         return unless defined $infdata;
346              
347 0           my $ns=$mes->ns('frnic');
348 0           $infdata=Net::DRI::Util::xml_traverse($infdata,$ns,'resData','infData','domain');
349 0 0         return unless defined $infdata;
350              
351 0           my $cs=$rinfo->{domain}->{$oname}->{status}; ## a Net::DRI::Protocol::EPP::Extensions::AFNIC::Status object
352 0           foreach my $el ($infdata->getChildrenByTagNameNS($ns,'status'))
353             {
354 0           $cs->rem('ok');
355 0           $cs->add($el->getAttribute('s'));
356             }
357 0           return;
358             }
359              
360             ####################################################################################################
361             1;