File Coverage

blib/lib/Net/DRI/Data/Contact/AFNIC.pm
Criterion Covered Total %
statement 21 92 22.8
branch 0 88 0.0
condition 0 101 0.0
subroutine 7 15 46.6
pod 0 8 0.0
total 28 304 9.2


line stmt bran cond sub pod time code
1             ## Domain Registry Interface, Handling of contact data for AFNIC
2             ##
3             ## Copyright (c) 2006,2008-2010,2012-2014 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::Data::Contact::AFNIC;
16              
17 1     1   730 use utf8;
  1         2  
  1         5  
18 1     1   26 use strict;
  1         1  
  1         18  
19 1     1   3 use warnings;
  1         1  
  1         29  
20              
21 1     1   4 use base qw/Net::DRI::Data::Contact/;
  1         1  
  1         67  
22              
23 1     1   5 use Email::Valid;
  1         1  
  1         24  
24              
25 1     1   3 use Net::DRI::Exception;
  1         4  
  1         73  
26 1     1   4 use Net::DRI::Util;
  1         2  
  1         1806  
27              
28             __PACKAGE__->register_attributes(qw(firstname legal_form legal_form_other legal_id legal_id_type jo trademark birth vat qualification obsoleted));
29              
30             =pod
31              
32             =encoding utf8
33              
34             =head1 NAME
35              
36             Net::DRI::Data::Contact::AFNIC - Handle AFNIC contact data for Net::DRI
37              
38             =head1 DESCRIPTION
39              
40             This subclass of Net::DRI::Data::Contact adds accessors and validation for
41             AFNIC specific data.
42              
43             =head1 METHODS
44              
45             The following accessors/mutators can be called in chain, as they all return the object itself.
46              
47             =head2 firstname()
48              
49             Please note that for AFNIC data, the name() must be only the lastname, hence this extra firstname() method needed for contacts being individuals
50              
51             =head2 legal_form()
52              
53             for an organization, either 'A' or 'association' for non profit organization, 'S' or 'company' for company or 'other' for other types;
54             this must be set for contacts being moral entities
55              
56             =head2 legal_form_other()
57              
58             type of organization for other types
59              
60             =head2 legal_id()
61              
62             French SIREN/SIRET of organization
63              
64             =head2 jo()
65              
66             reference to an hash with 4 keys storing details about «Journal Officiel» :
67             date_declaration (Declaration date), date_publication (Publication date),
68             number (Announce number) and page (Announce page)
69              
70             a waldec key can also be present for the waldec id
71              
72             =head2 trademark()
73              
74             for trademarks, its number
75              
76             =head2 vat()
77              
78             vat number (not used by registry for now)
79              
80             =head2 birth()
81              
82             reference to an hash with 2 keys storing details about birth of contact :
83             date (Date of birth) and place (Place of birth)
84              
85             =head1 SUPPORT
86              
87             For now, support questions should be sent to:
88              
89             Enetdri@dotandco.comE
90              
91             Please also see the SUPPORT file in the distribution.
92              
93             =head1 SEE ALSO
94              
95             http://www.dotandco.com/services/software/Net-DRI/
96              
97             =head1 AUTHOR
98              
99             Patrick Mevzek, Enetdri@dotandco.comE
100              
101             =head1 COPYRIGHT
102              
103             Copyright (c) 2006,2008-2010,2012-2014 Patrick Mevzek .
104             All rights reserved.
105              
106             This program is free software; you can redistribute it and/or modify
107             it under the terms of the GNU General Public License as published by
108             the Free Software Foundation; either version 2 of the License, or
109             (at your option) any later version.
110              
111             See the LICENSE file that comes with this distribution for more details.
112              
113             =cut
114              
115             ####################################################################################################
116              
117             our $LETTRES=qr(A-Z\x{00C0}\x{00C2}\x{00C7}\x{00C8}\x{00C9}\x{00CA}\x{00CB}\x{00CE}\x{00CF}\x{00D4}\x{00D9}\x{00DB}\x{00DC}\x{0178}\x{00C6}\x{0152}a-z\x{00E0}\x{00E2}\x{00E7}\x{00E8}\x{00E9}\x{00EA}\x{00EB}\x{00EE}\x{00EF}\x{00F4}\x{00F9}\x{00FB}\x{00FC}\x{00FF}\x{00E6}\x{0153});
118             our $NOM_LIBRE_ITEM=qr{[${LETTRES}0-9\(\)\.\[\]\?\+\*#&/!\@',><":-]+};
119             our $NOM_PROPRE_ITEM=qr{[${LETTRES}]+(('?(?:[${LETTRES}]+(?:\-?[${LETTRES}]+)?)+)|(?:\.?))};
120             our $NOM_PROPRE=qr{${NOM_PROPRE_ITEM}( +${NOM_PROPRE_ITEM})*};
121             our $ADRESSE_ITEM=qr{[${LETTRES}0-9\(\)\./',"#-]+};
122             our $NOM_COMMUNE_ITEM=qr{[${LETTRES}]+(?:['-]?[${LETTRES}]+)*};
123              
124 0     0 0   sub is_nom_libre { return shift=~m/^(?:${NOM_LIBRE_ITEM} *)*[${LETTRES}0-9]+(?: *${NOM_LIBRE_ITEM}*)*$/; }
125 0     0 0   sub is_adresse { return shift=~m/^(?:${ADRESSE_ITEM} *)*[${LETTRES}]+(?: *${ADRESSE_ITEM})*$/; }
126 0     0 0   sub is_commune { return shift=~m/^${NOM_COMMUNE_ITEM}(?:(?:(?: *\/ *)|(?: +))${NOM_COMMUNE_ITEM})*(?: +(?:[cC][eE][dD][eE][xX]|[cC][dD][xX])(?: +[0-9]+)?)?$/; }
127 0     0 0   sub is_code_fr { return shift=~m/^(?:FR|RE|MQ|GP|GF|TF|NC|PF|WF|PM|YT)$/; }
128 0     0 0   sub is_dep_fr { return shift=~m/^(?:0[1-9])|(?:[1345678][0-9])|(?:2[1-9ABab])|(?:9[0-5])|(?:97[1-5])|(?:98[5-8])$/; }
129              
130             sub validate
131             {
132 0     0 0   my ($self,$change)=@_;
133 0   0       $change||=0;
134              
135 0           $self->SUPER::validate(1); ## will trigger an Exception if problem
136              
137 0           my @errs;
138 0 0 0       push @errs,'srid' if ($self->srid() && $self->srid()!~m/^[A-Z]+(?:[1-9][0-9]*)?(?:-FRNIC)?$/i);
139 0 0 0       push @errs,'name' if ($self->name() && ($self->name()!~m/^${NOM_PROPRE}$/ || ! is_nom_libre($self->name())));
      0        
140 0 0 0       push @errs,'firstname' if ($self->firstname() && $self->firstname()!~m/^${NOM_PROPRE}$/);
141 0 0 0       push @errs,'org' if ($self->org() && ! is_nom_libre($self->org()));
142              
143 0 0 0       push @errs,'legal_form' if ($self->legal_form() && $self->legal_form()!~m/^(?:company|association|other)$/);
144 0 0 0       push @errs,'legal_form_other' if ($self->legal_form_other() && ! is_nom_libre($self->legal_form_other()));
145 0 0         if ($self->legal_id_type())
146             {
147 0 0         push @errs,'legal_id_type' if $self->legal_id_type()!~m/^(?:siren|duns|local)$/;
148 0 0 0       push @errs,'legal_id' if ($self->legal_id() && $self->legal_id_type() eq 'sirent' && $self->legal_id()!~m/^[0-9]{9}(?:[0-9]{5})?$/);
      0        
149             }
150              
151 0           my $jo=$self->jo();
152 0 0         if ($jo)
153             {
154 0 0 0       if ((ref($jo) eq 'HASH') && exists($jo->{date_declaration}) && exists($jo->{date_publication}) && exists($jo->{number}) && exists ($jo->{page}))
      0        
      0        
      0        
155             {
156 0 0 0       push @errs,'jo' unless ($jo->{date_declaration}=~m!^[0-9]{2}/[0-9]{2}/[0-9]{4}$! || $jo->{date_declaration}=~m!^[0-9]{4}-[0-9]{2}-[0-9]{2}$!);
157 0 0 0       push @errs,'jo' unless ($jo->{date_publication}=~m!^[0-9]{2}/[0-9]{2}/[0-9]{4}$! || $jo->{date_publication}=~m!^[0-9]{4}-[0-9]{2}-[0-9]{2}$!);
158 0 0         push @errs,'jo' unless $jo->{number}=~m/^[1-9][0-9]*$/;
159 0 0         push @errs,'jo' unless $jo->{page}=~m/^[1-9][0-9]*$/;
160             } else
161             {
162 0           push @errs,'jo';
163             }
164             }
165              
166 0 0 0       push @errs,'vat' if ($self->vat() && !Net::DRI::Util::xml_is_token($self->vat()));
167 0 0 0       push @errs,'trademark' if ($self->trademark() && $self->trademark()!~m/^[0-9]*[A-Za-z]*[0-9]+$/);
168              
169 0           my $birth=$self->birth();
170 0 0         if ($birth)
171             {
172 0 0 0       if ((ref($birth) eq 'HASH') && exists($birth->{date}) && exists($birth->{place}))
      0        
173             {
174 0 0 0       push @errs,'birth' unless ((ref($birth->{date}) eq 'DateTime') || $birth->{date}=~m!^[0-9]{4}-[0-9]{2}-[0-9]{2}$! || $birth->{date}=~m!^[0-9]{2}/[0-9]{2}/[0-9]{4}$!);
      0        
175 0 0 0       push @errs,'birth' unless (($birth->{place}=~m/^[A-Za-z]{2}$/ && ! is_code_fr($birth->{place})) || ($birth->{place}=~m/^(?:[0-9]{5}|) *, *(.+)$/ && is_commune($1)));
      0        
      0        
176             } else
177             {
178 0           push @errs,'birth';
179             }
180             }
181              
182 0 0         my $isccfr=$self->cc()? is_code_fr(uc($self->cc())) : 0;
183              
184             ## Not same checks as AFNIC, but we will translate to their format when needed, better to standardize on EPP
185 0 0         if ($self->voice())
186             {
187 0 0         push @errs,'voice' if $self->voice()!~m/^\+[0-9]{1,3}\.[0-9]{1,14}(?:x\d+)?$/;
188 0 0 0       push @errs,'voice' if ($isccfr && $self->voice()!~m/^\+33\./);
189             }
190 0 0         if ($self->fax())
191             {
192 0 0         push @errs,'fax' if $self->fax()!~m/^\+[0-9]{1,3}\.[0-9]{1,14}(?:x\d+)?$/;
193 0 0 0       push @errs,'fax' if ($isccfr && $self->fax()!~m/^\+33\./);
194             }
195 0 0 0       push @errs,'email' if ($self->email() && !Email::Valid->rfc822($self->email()));
196              
197             ## Maintainer is not tied to contact
198              
199 0 0 0       push @errs,'disclose' if ($self->disclose() && $self->disclose()!~m/^[ONY]$/i);
200              
201 0           my $q=$self->qualification();
202 0 0         if (defined $q)
203             {
204 0 0 0       push @errs,'qualification' if ref $q ne 'HASH' || grep { ! /^(?:identification|reachable)$/ } keys %$q;
  0            
205             }
206              
207 0 0         Net::DRI::Exception::usererr_invalid_parameters('Invalid contact information: '.join('/',@errs)) if @errs;
208 0           return 1; ## everything ok.
209             }
210              
211             sub validate_registrant
212             {
213 0     0 0   my $self=shift;
214 0           my @errs;
215 0           my $rs=$self->street();
216 0 0 0       push @errs,'street' if ($rs && ((ref($rs) ne 'ARRAY') || (@$rs > 3) || (grep { ! is_adresse($_) } @$rs)));
      0        
217 0 0 0       push @errs,'city' if ($self->city() && ! is_commune($self->city()));
218              
219 0           my $cc=$self->cc();
220 0           my $isccfr=0;
221 0 0         if ($cc)
222             {
223 0 0         push @errs,'cc' if !exists($Net::DRI::Util::CCA2{uc($cc)});
224 0           $isccfr=is_code_fr(uc($cc));
225             }
226              
227 0           my $pc=$self->pc();
228 0 0         if ($pc)
229             {
230 0 0         if ($isccfr)
231             {
232 0 0         push @errs,'pc' unless $pc=~m/^[0-9]{5}$/;
233             } else
234             {
235 0 0         push @errs,'pc' unless $pc=~m/^[-0-9A-Za-z ]+$/;
236             }
237             }
238              
239 0 0         Net::DRI::Exception::usererr_invalid_parameters('Invalid contact information: '.join('/',@errs)) if @errs;
240 0           return 1; ## everything ok.
241             }
242              
243             sub init
244             {
245 0     0 0   my ($self,$what,$ndr)=@_;
246 0           my $pn=$ndr->protocol()->name();
247 0 0 0       if ($what eq 'create' && $pn eq 'EPP')
248             {
249 0 0         $self->srid('AUTO') unless defined($self->srid()); ## we can not choose the ID
250             }
251 0           return;
252             }
253              
254             ####################################################################################################
255             1;