File Coverage

blib/lib/Net/DRI/Protocol/EPP/Extensions/AFNIC/Domain.pm
Criterion Covered Total %
statement 12 161 7.4
branch 0 64 0.0
condition 0 26 0.0
subroutine 4 24 16.6
pod 0 20 0.0
total 16 295 5.4


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