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
|
|
825
|
use utf8; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
7
|
|
18
|
1
|
|
|
1
|
|
26
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
31
|
|
19
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
20
|
|
|
|
|
|
|
|
21
|
1
|
|
|
1
|
|
3
|
use base qw/Net::DRI::Data::Contact/; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
64
|
|
22
|
|
|
|
|
|
|
|
23
|
1
|
|
|
1
|
|
6
|
use Email::Valid; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
17
|
|
24
|
|
|
|
|
|
|
|
25
|
1
|
|
|
1
|
|
4
|
use Net::DRI::Exception; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
19
|
|
26
|
1
|
|
|
1
|
|
3
|
use Net::DRI::Util; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1613
|
|
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; |