line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
## Domain Registry Interface, Misc. useful functions |
2
|
|
|
|
|
|
|
## |
3
|
|
|
|
|
|
|
## Copyright (c) 2005-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::Util; |
16
|
|
|
|
|
|
|
|
17
|
88
|
|
|
88
|
|
47794
|
use utf8; |
|
88
|
|
|
|
|
593
|
|
|
88
|
|
|
|
|
322
|
|
18
|
88
|
|
|
88
|
|
1964
|
use strict; |
|
88
|
|
|
|
|
92
|
|
|
88
|
|
|
|
|
1216
|
|
19
|
88
|
|
|
88
|
|
235
|
use warnings; |
|
88
|
|
|
|
|
84
|
|
|
88
|
|
|
|
|
1618
|
|
20
|
|
|
|
|
|
|
|
21
|
88
|
|
|
88
|
|
37445
|
use Time::HiRes (); |
|
88
|
|
|
|
|
81942
|
|
|
88
|
|
|
|
|
1754
|
|
22
|
88
|
|
|
88
|
|
41197
|
use Encode (); |
|
88
|
|
|
|
|
628239
|
|
|
88
|
|
|
|
|
1703
|
|
23
|
88
|
|
|
88
|
|
35817
|
use Module::Load; |
|
88
|
|
|
|
|
66655
|
|
|
88
|
|
|
|
|
441
|
|
24
|
88
|
|
|
88
|
|
3153
|
use Scalar::Util (); |
|
88
|
|
|
|
|
95
|
|
|
88
|
|
|
|
|
1133
|
|
25
|
88
|
|
|
88
|
|
26118
|
use Net::DRI::Exception; |
|
88
|
|
|
|
|
119
|
|
|
88
|
|
|
|
|
198017
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=pod |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=head1 NAME |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Net::DRI::Util - Various useful functions for Net::DRI operations |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=head1 DESCRIPTION |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
Please see the README file for details. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 SUPPORT |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
For now, support questions should be sent to: |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Enetdri@dotandco.comE |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
Please also see the SUPPORT file in the distribution. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=head1 SEE ALSO |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
Ehttp://www.dotandco.com/services/software/Net-DRI/E |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head1 AUTHOR |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Patrick Mevzek, Enetdri@dotandco.comE |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head1 COPYRIGHT |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Copyright (c) 2005-2016 Patrick Mevzek . |
56
|
|
|
|
|
|
|
All rights reserved. |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
59
|
|
|
|
|
|
|
it under the terms of the GNU General Public License as published by |
60
|
|
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or |
61
|
|
|
|
|
|
|
(at your option) any later version. |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
See the LICENSE file that comes with this distribution for more details. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
#################################################################################################### |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
## See https://www.iso.org/obp/ui/#search , select 'Country codes', then 'Officially assigned', order by Alpha-2 code (last checked on 2015-05-24) |
71
|
|
|
|
|
|
|
## qw/.A .B .C .D .E .F .G .H .I .J .K .L .M .N .O .P .Q .R .S .T .U .V .W .X .Y .Z |
72
|
|
|
|
|
|
|
our %CCA2=map { $_ => 1 } qw/ AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ/, |
73
|
|
|
|
|
|
|
qw/BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BV BW BY BZ/, |
74
|
|
|
|
|
|
|
qw/CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ/, |
75
|
|
|
|
|
|
|
qw/ DE DJ DK DM DO DZ/, |
76
|
|
|
|
|
|
|
qw/ EC EE EG EH ER ES ET /, |
77
|
|
|
|
|
|
|
qw/ FI FJ FK FM FO FR /, |
78
|
|
|
|
|
|
|
qw/GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW GY /, |
79
|
|
|
|
|
|
|
qw/ HK HM HN HR HT HU /, |
80
|
|
|
|
|
|
|
qw/ ID IE IL IM IN IO IQ IR IS IT /, |
81
|
|
|
|
|
|
|
qw/ JE JM JO JP /, |
82
|
|
|
|
|
|
|
qw/ KE KG KH KI KM KN KP KR KW KY KZ/, |
83
|
|
|
|
|
|
|
qw/LA LB LC LI LK LR LS LT LU LV LY /, |
84
|
|
|
|
|
|
|
qw/MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ/, |
85
|
|
|
|
|
|
|
qw/NA NC NE NF NG NI NL NO NP NR NU NZ/, |
86
|
|
|
|
|
|
|
qw/ OM /, |
87
|
|
|
|
|
|
|
qw/PA PE PF PG PH PK PL PM PN PR PS PT PW PY /, |
88
|
|
|
|
|
|
|
qw/QA /, |
89
|
|
|
|
|
|
|
qw/ RE RO RS RU RW /, |
90
|
|
|
|
|
|
|
qw/SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ/, |
91
|
|
|
|
|
|
|
qw/ TC TD TF TG TH TJ TK TL TM TN TO TR TT TV TW TZ/, |
92
|
|
|
|
|
|
|
qw/UA UG UM US UY UZ/, |
93
|
|
|
|
|
|
|
qw/VA VC VE VG VI VN VU /, |
94
|
|
|
|
|
|
|
qw/ WF WS /, |
95
|
|
|
|
|
|
|
qw/ YE YT /, |
96
|
|
|
|
|
|
|
qw/ZA ZM ZW /; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub all_valid |
99
|
|
|
|
|
|
|
{ |
100
|
267
|
|
|
267
|
0
|
3064
|
my (@args)=@_; |
101
|
267
|
|
|
|
|
449
|
foreach (@args) |
102
|
|
|
|
|
|
|
{ |
103
|
602
|
100
|
66
|
|
|
2499
|
return 0 unless (defined($_) && (ref($_) || length($_))); |
|
|
|
66
|
|
|
|
|
104
|
|
|
|
|
|
|
} |
105
|
242
|
|
|
|
|
1181
|
return 1; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub hash_merge |
109
|
|
|
|
|
|
|
{ |
110
|
3
|
|
|
3
|
0
|
3
|
my ($rmaster,$rtoadd)=@_; |
111
|
3
|
|
|
|
|
12
|
while(my ($k,$v)=each(%$rtoadd)) |
112
|
|
|
|
|
|
|
{ |
113
|
3
|
50
|
|
|
|
9
|
$rmaster->{$k}={} unless exists($rmaster->{$k}); |
114
|
3
|
|
|
|
|
8
|
while(my ($kk,$vv)=each(%$v)) |
115
|
|
|
|
|
|
|
{ |
116
|
18
|
50
|
|
|
|
27
|
$rmaster->{$k}->{$kk}=[] unless exists($rmaster->{$k}->{$kk}); |
117
|
18
|
|
|
|
|
20
|
my @t=@$vv; |
118
|
18
|
|
|
|
|
12
|
push @{$rmaster->{$k}->{$kk}},\@t; |
|
18
|
|
|
|
|
69
|
|
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
} |
121
|
3
|
|
|
|
|
6
|
return; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub deepcopy ## no critic (Subroutines::RequireFinalReturn) |
125
|
|
|
|
|
|
|
{ |
126
|
0
|
|
|
0
|
0
|
0
|
my $in=shift; |
127
|
0
|
0
|
|
|
|
0
|
return $in unless defined $in; |
128
|
0
|
|
|
|
|
0
|
my $ref=ref $in; |
129
|
0
|
0
|
|
|
|
0
|
return $in unless $ref; |
130
|
0
|
|
|
|
|
0
|
my $cname; |
131
|
0
|
0
|
|
|
|
0
|
($cname,$ref)=($1,$2) if ("$in"=~m/^(\S+)=([A-Z]+)\(0x/); |
132
|
|
|
|
|
|
|
|
133
|
0
|
0
|
|
|
|
0
|
if ($ref eq 'SCALAR') |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
134
|
|
|
|
|
|
|
{ |
135
|
0
|
|
|
|
|
0
|
my $tmp=$$in; |
136
|
0
|
|
|
|
|
0
|
return \$tmp; |
137
|
|
|
|
|
|
|
} elsif ($ref eq 'HASH') |
138
|
|
|
|
|
|
|
{ |
139
|
0
|
0
|
0
|
|
|
0
|
my $r={ map { $_ => (defined $in->{$_} && ref $in->{$_}) ? deepcopy($in->{$_}) : $in->{$_} } keys(%$in) }; |
|
0
|
|
|
|
|
0
|
|
140
|
0
|
0
|
|
|
|
0
|
bless($r,$cname) if defined $cname; |
141
|
0
|
|
|
|
|
0
|
return $r; |
142
|
|
|
|
|
|
|
} elsif ($ref eq 'ARRAY') |
143
|
|
|
|
|
|
|
{ |
144
|
0
|
0
|
0
|
|
|
0
|
return [ map { (defined $_ && ref $_)? deepcopy($_) : $_ } @$in ]; |
|
0
|
|
|
|
|
0
|
|
145
|
|
|
|
|
|
|
} else |
146
|
|
|
|
|
|
|
{ |
147
|
0
|
|
|
|
|
0
|
Net::DRI::Exception::usererr_invalid_parameters('Do not know how to deepcopy '.$in); |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub link_rs |
152
|
|
|
|
|
|
|
{ |
153
|
4
|
|
|
4
|
0
|
4
|
my (@rs)=@_; |
154
|
4
|
|
|
|
|
3
|
my %seen; |
155
|
4
|
|
|
|
|
10
|
foreach my $i (1..$#rs) |
156
|
|
|
|
|
|
|
{ |
157
|
0
|
0
|
|
|
|
0
|
$rs[$i-1]->_set_last($rs[$i]) unless exists $seen{$rs[$i]}; |
158
|
0
|
|
|
|
|
0
|
$seen{$rs[$i]}=1; |
159
|
|
|
|
|
|
|
} |
160
|
4
|
|
|
|
|
17
|
return $rs[0]; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
#################################################################################################### |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub isint |
166
|
|
|
|
|
|
|
{ |
167
|
5
|
|
|
5
|
0
|
7
|
my $in=shift; |
168
|
5
|
100
|
|
|
|
32
|
return ($in=~m/^\d+$/)? 1 : 0; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
## eppcom:roidType |
172
|
|
|
|
|
|
|
sub is_roid |
173
|
|
|
|
|
|
|
{ |
174
|
0
|
|
|
0
|
0
|
0
|
my $in=shift; |
175
|
0
|
|
0
|
|
|
0
|
return xml_is_token($in,3,89) && $in=~m/^\w{1,80}-[0-9A-Za-z]{1,8}$/; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub check_equal |
179
|
|
|
|
|
|
|
{ |
180
|
7
|
|
|
7
|
0
|
13
|
my ($input,$ra,$default)=@_; |
181
|
7
|
100
|
|
|
|
19
|
return $default unless defined($input); |
182
|
5
|
100
|
|
|
|
14
|
foreach my $a (ref($ra)? @$ra : ($ra)) |
183
|
|
|
|
|
|
|
{ |
184
|
6
|
100
|
|
|
|
63
|
return $a if ($a=~m/^${input}$/); |
185
|
|
|
|
|
|
|
} |
186
|
2
|
100
|
|
|
|
6
|
return $default if $default; |
187
|
1
|
|
|
|
|
3
|
return; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub check_isa |
191
|
|
|
|
|
|
|
{ |
192
|
17
|
|
|
17
|
0
|
325
|
my ($what,$isa)=@_; |
193
|
17
|
100
|
50
|
|
|
40
|
Net::DRI::Exception::usererr_invalid_parameters((${what} || 'parameter').' must be a '.$isa.' object') unless $what && is_class($what,$isa); |
|
|
|
66
|
|
|
|
|
194
|
16
|
|
|
|
|
28
|
return 1; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub is_class |
198
|
|
|
|
|
|
|
{ |
199
|
35
|
|
|
35
|
0
|
73
|
my ($obj,$class)=@_; |
200
|
35
|
100
|
|
|
|
30
|
return eval { $obj->isa($class); } ? 1 : 0; |
|
35
|
|
|
|
|
307
|
|
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub isa_contactset |
204
|
|
|
|
|
|
|
{ |
205
|
0
|
|
|
0
|
0
|
0
|
my $cs=shift; |
206
|
0
|
0
|
0
|
|
|
0
|
return (defined $cs && is_class($cs,'Net::DRI::Data::ContactSet') && !$cs->is_empty())? 1 : 0; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub isa_contact |
210
|
|
|
|
|
|
|
{ |
211
|
9
|
|
|
9
|
0
|
11
|
my ($c,$class)=@_; |
212
|
9
|
50
|
|
|
|
21
|
$class='Net::DRI::Data::Contact' unless defined $class; |
213
|
9
|
50
|
33
|
|
|
23
|
return (defined $c && is_class($c,$class))? 1 : 0; ## no way to check if it is empty or not ? Contact->validate() is too strong as it may die, Contact->roid() maybe not ok always |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub isa_hosts |
217
|
|
|
|
|
|
|
{ |
218
|
3
|
|
|
3
|
0
|
3
|
my ($h,$emptyok)=@_; |
219
|
3
|
100
|
|
|
|
6
|
$emptyok=0 unless defined $emptyok; |
220
|
3
|
50
|
33
|
|
|
9
|
return (defined $h && is_class($h,'Net::DRI::Data::Hosts') && ($emptyok || !$h->is_empty()) )? 1 : 0; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub isa_nsgroup |
224
|
|
|
|
|
|
|
{ |
225
|
0
|
|
|
0
|
0
|
0
|
my $h=shift; |
226
|
0
|
0
|
0
|
|
|
0
|
return (defined $h && is_class($h,'Net::DRI::Data::Hosts'))? 1 : 0; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub isa_changes |
230
|
|
|
|
|
|
|
{ |
231
|
3
|
|
|
3
|
0
|
2
|
my $c=shift; |
232
|
3
|
50
|
33
|
|
|
9
|
return (defined $c && is_class($c,'Net::DRI::Data::Changes') && !$c->is_empty())? 1 : 0; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub isa_statuslist |
236
|
|
|
|
|
|
|
{ |
237
|
0
|
|
|
0
|
0
|
0
|
my $s=shift; |
238
|
0
|
0
|
0
|
|
|
0
|
return (defined $s && is_class($s,'Net::DRI::Data::StatusList') && !$s->is_empty())? 1 : 0; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub has_key |
242
|
|
|
|
|
|
|
{ |
243
|
211
|
|
|
211
|
0
|
288
|
my ($rh,$key)=@_; |
244
|
211
|
50
|
33
|
|
|
880
|
return 0 unless (defined $key && $key); |
245
|
211
|
100
|
33
|
|
|
2055
|
return 0 unless (defined $rh && (ref $rh eq 'HASH') && exists $rh->{$key} && defined $rh->{$key}); |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
246
|
88
|
|
|
|
|
753
|
return 1; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
sub has_contact |
250
|
|
|
|
|
|
|
{ |
251
|
0
|
|
|
0
|
0
|
0
|
my $rh=shift; |
252
|
0
|
|
0
|
|
|
0
|
return has_key($rh,'contact') && isa_contactset($rh->{contact}); |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub has_ns |
256
|
|
|
|
|
|
|
{ |
257
|
1
|
|
|
1
|
0
|
5
|
my $rh=shift; |
258
|
1
|
|
33
|
|
|
1
|
return has_key($rh,'ns') && isa_hosts($rh->{ns}); |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub has_duration |
262
|
|
|
|
|
|
|
{ |
263
|
1
|
|
|
1
|
0
|
2
|
my $rh=shift; |
264
|
1
|
|
33
|
|
|
2
|
return has_key($rh,'duration') && check_isa($rh->{'duration'},'DateTime::Duration'); ## check_isa throws an Exception if not |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub has_auth |
268
|
|
|
|
|
|
|
{ |
269
|
0
|
|
|
0
|
0
|
0
|
my $rh=shift; |
270
|
0
|
0
|
0
|
|
|
0
|
return (has_key($rh,'auth') && ref $rh->{'auth'} eq 'HASH')? 1 : 0; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub has_status |
274
|
|
|
|
|
|
|
{ |
275
|
0
|
|
|
0
|
0
|
0
|
my $rh=shift; |
276
|
0
|
0
|
0
|
|
|
0
|
return (has_key($rh,'status') && isa_statuslist($rh->{status}))? 1 : 0; |
277
|
|
|
|
|
|
|
} |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
#################################################################################################### |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub microtime |
282
|
|
|
|
|
|
|
{ |
283
|
43
|
|
|
43
|
0
|
102
|
my ($t,$v)=Time::HiRes::gettimeofday(); |
284
|
43
|
|
|
|
|
177
|
return $t.sprintf('%06d',$v); |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub fulltime |
288
|
|
|
|
|
|
|
{ |
289
|
0
|
|
|
0
|
0
|
0
|
my ($t,$v)=Time::HiRes::gettimeofday(); |
290
|
0
|
|
|
|
|
0
|
my @t=localtime($t); |
291
|
0
|
|
|
|
|
0
|
return sprintf('%d-%02d-%02d %02d:%02d:%02d.%06d',1900+$t[5],1+$t[4],$t[3],$t[2],$t[1],$t[0],$v); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
## From EPP, trID=token from 3 to 64 characters |
295
|
|
|
|
|
|
|
sub create_trid_1 |
296
|
|
|
|
|
|
|
{ |
297
|
11
|
|
|
11
|
0
|
26
|
my ($name)=@_; |
298
|
11
|
|
|
|
|
18
|
my $mt=microtime(); ## length=16 |
299
|
11
|
|
|
|
|
49
|
return uc($name).'-'.$$.'-'.$mt; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub create_params |
303
|
|
|
|
|
|
|
{ |
304
|
7
|
|
|
7
|
0
|
8
|
my ($op,$rd)=@_; |
305
|
7
|
100
|
|
|
|
18
|
return {} unless defined $rd; |
306
|
2
|
50
|
|
|
|
9
|
Net::DRI::Exception::usererr_invalid_parameters('last parameter of '.$op.', if defined, must be a ref hash holding extra parameters as needed') unless ref $rd eq 'HASH'; |
307
|
2
|
|
|
|
|
7
|
return { %$rd }; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
#################################################################################################### |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub is_hostname ## RFC952/1123 |
313
|
|
|
|
|
|
|
{ |
314
|
235
|
|
|
235
|
0
|
66019
|
my ($name,$unicode)=@_; |
315
|
235
|
100
|
|
|
|
413
|
return 0 unless defined $name; |
316
|
234
|
100
|
|
|
|
364
|
$unicode=0 unless defined $unicode; |
317
|
|
|
|
|
|
|
|
318
|
234
|
|
|
|
|
529
|
my @d=split(/\./,$name,-1); |
319
|
234
|
|
|
|
|
283
|
foreach my $d (@d) |
320
|
|
|
|
|
|
|
{ |
321
|
291
|
100
|
66
|
|
|
871
|
return 0 unless (defined $d && $d ne ''); |
322
|
287
|
100
|
|
|
|
375
|
return 0 unless (length $d <= 63); |
323
|
286
|
100
|
100
|
|
|
925
|
return 0 if (($d=~m/^-/) || ($d=~m/-$/)); |
324
|
284
|
100
|
66
|
|
|
1641
|
return 0 if (!$unicode && $d=~m/[^A-Za-z0-9\-]/); |
325
|
|
|
|
|
|
|
} |
326
|
33
|
|
|
|
|
97
|
return 1; |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub is_ipv4 |
330
|
|
|
|
|
|
|
{ |
331
|
39
|
|
|
39
|
0
|
381
|
my ($ip,$checkpublic)=@_; |
332
|
|
|
|
|
|
|
|
333
|
39
|
100
|
|
|
|
69
|
return 0 unless defined $ip; |
334
|
38
|
|
|
|
|
164
|
my (@ip)=($ip=~m/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/); |
335
|
38
|
100
|
|
|
|
75
|
return 0 unless (@ip==4); |
336
|
34
|
|
|
|
|
44
|
foreach my $s (@ip) |
337
|
|
|
|
|
|
|
{ |
338
|
133
|
100
|
66
|
|
|
384
|
return 0 unless (($s >= 0) && ($s <= 255)); |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
33
|
100
|
66
|
|
|
100
|
return 1 unless (defined $checkpublic && $checkpublic); |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
## Check if this IP is public (see RFC3330) |
344
|
32
|
100
|
|
|
|
53
|
return 0 if ($ip[0] == 0); ## 0.x.x.x [ RFC 1700 ] |
345
|
31
|
100
|
|
|
|
45
|
return 0 if ($ip[0] == 10); ## 10.x.x.x [ RFC 1918 ] |
346
|
30
|
100
|
|
|
|
45
|
return 0 if ($ip[0] == 127); ## 127.x.x.x [ RFC 1700 ] |
347
|
29
|
100
|
66
|
|
|
53
|
return 0 if (($ip[0] == 169) && ($ip[1]==254)); ## 169.254.0.0/16 link local |
348
|
28
|
100
|
66
|
|
|
58
|
return 0 if (($ip[0] == 172 ) && ($ip[1]>=16) && ($ip[1]<=31)); ## 172.16.x.x to 172.31.x.x [ RFC 1918 ] |
|
|
|
100
|
|
|
|
|
349
|
27
|
100
|
100
|
|
|
65
|
return 0 if (($ip[0] == 192 ) && ($ip[1]==0) && ($ip[2]==2)); ## 192.0.2.0/24 TEST-NET |
|
|
|
66
|
|
|
|
|
350
|
26
|
100
|
100
|
|
|
62
|
return 0 if (($ip[0] == 192 ) && ($ip[1]==168)); ## 192.168.x.x [ RFC 1918 ] |
351
|
25
|
100
|
66
|
|
|
44
|
return 0 if (($ip[0] >= 224) && ($ip[0] < 240 )); ## 224.0.0.0/4 Class D [ RFC 3171] |
352
|
24
|
50
|
|
|
|
31
|
return 0 if ($ip[0] >= 240); ## 240.0.0.0/4 Class E [ RFC 1700 ] |
353
|
24
|
|
|
|
|
73
|
return 1; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
## Inspired by Net::IP which unfortunately requires Perl 5.8 |
357
|
|
|
|
|
|
|
sub is_ipv6 |
358
|
|
|
|
|
|
|
{ |
359
|
12
|
|
|
12
|
0
|
12
|
my ($ip,$checkpublic)=@_; |
360
|
12
|
50
|
|
|
|
18
|
return 0 unless defined $ip; |
361
|
|
|
|
|
|
|
|
362
|
12
|
|
|
|
|
29
|
my (@ip)=split(/:/,$ip); |
363
|
12
|
50
|
33
|
|
|
37
|
return 0 unless ((@ip > 0) && (@ip <= 8)); |
364
|
12
|
50
|
33
|
|
|
47
|
return 0 if (($ip=~m/^:[^:]/) || ($ip=~m/[^:]:$/)); |
365
|
12
|
50
|
|
|
|
36
|
return 0 if ($ip =~ s/:(?=:)//g > 1); |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
## We do not allow IPv4 in IPv6 |
368
|
12
|
100
|
|
|
|
13
|
return 0 if grep { ! /^[a-f\d]{0,4}$/i } @ip; |
|
19
|
|
|
|
|
85
|
|
369
|
|
|
|
|
|
|
|
370
|
1
|
50
|
33
|
|
|
5
|
return 1 unless (defined($checkpublic) && $checkpublic); |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
## Check if this IP is public |
373
|
1
|
|
|
|
|
3
|
my ($ip1,$ip2)=split(/::/,$ip); |
374
|
1
|
|
50
|
|
|
12
|
$ip1=join('',map { sprintf('%04s',$_) } split(/:/,$ip1 || '')); |
|
8
|
|
|
|
|
12
|
|
375
|
1
|
|
50
|
|
|
6
|
$ip2=join('',map { sprintf('%04s',$_) } split(/:/,$ip2 || '')); |
|
0
|
|
|
|
|
0
|
|
376
|
1
|
|
|
|
|
3
|
my $wip=$ip1.('0' x (32-length($ip1)-length($ip2))).$ip2; ## 32 chars |
377
|
1
|
|
|
|
|
12
|
my $bip=unpack('B128',pack('H32',$wip)); ## 128-bit array |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
## RFC 3513 §2.4 |
380
|
1
|
50
|
|
|
|
3
|
return 0 if ($bip=~m/^0{127}/); ## unspecified + loopback |
381
|
1
|
50
|
|
|
|
3
|
return 0 if ($bip=~m/^1{7}/); ## multicast + link-local unicast + site-local unicast |
382
|
|
|
|
|
|
|
## everything else is global unicast, |
383
|
|
|
|
|
|
|
## but see §4 and http://www.iana.org/assignments/ipv6-address-space |
384
|
1
|
50
|
|
|
|
3
|
return 0 if ($bip=~m/^000/); ## unassigned + reserved (first 6 lines) |
385
|
1
|
50
|
|
|
|
7
|
return 1 if ($bip=~m/^001/); ## global unicast (2000::/3) |
386
|
0
|
|
|
|
|
0
|
return 0; ## everything else is unassigned |
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
#################################################################################################### |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
sub compare_durations |
392
|
|
|
|
|
|
|
{ |
393
|
10
|
|
|
10
|
0
|
7
|
my ($dtd1,$dtd2)=@_; |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
## from DateTime::Duration module, internally are stored: months, days, minutes, seconds and nanoseconds |
396
|
|
|
|
|
|
|
## those are the keys of the hash ref given by the deltas method |
397
|
10
|
|
|
|
|
16
|
my %d1=$dtd1->deltas(); |
398
|
10
|
|
|
|
|
57
|
my %d2=$dtd2->deltas(); |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
## Not perfect, but should be enough for us |
401
|
|
|
|
|
|
|
return (($d1{months} <=> $d2{months}) || |
402
|
|
|
|
|
|
|
($d1{days} <=> $d2{days}) || |
403
|
|
|
|
|
|
|
($d1{minutes} <=> $d2{minutes}) || |
404
|
|
|
|
|
|
|
($d1{seconds} <=> $d2{seconds}) |
405
|
10
|
|
33
|
|
|
98
|
); |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
#################################################################################################### |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
sub xml_is_normalizedstring |
411
|
|
|
|
|
|
|
{ |
412
|
10
|
|
|
10
|
0
|
518
|
my ($what,$min,$max)=@_; |
413
|
10
|
|
|
|
|
17
|
my $r=xml_is_string($what,$min,$max); |
414
|
10
|
100
|
|
|
|
22
|
return 0 if $r==0; |
415
|
6
|
100
|
|
|
|
13
|
return 0 if $what=~m/[\r\n\t]/; |
416
|
5
|
|
|
|
|
13
|
return 1; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
sub xml_is_string |
420
|
|
|
|
|
|
|
{ |
421
|
10
|
|
|
10
|
0
|
8
|
my ($what,$min,$max)=@_; |
422
|
10
|
100
|
|
|
|
18
|
return 0 unless defined $what; |
423
|
9
|
50
|
|
|
|
21
|
return 0 if defined Scalar::Util::reftype($what); |
424
|
9
|
50
|
|
|
|
32
|
return 0 unless $what=~m/^[\x{0009}\x{000A}\x{000D}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/; ## XML Char definition (all Unicode excluding the surrogate blocks, FFFE, and FFFF) |
425
|
9
|
|
|
|
|
9
|
my $l=length $what; |
426
|
9
|
100
|
100
|
|
|
26
|
return 0 if (defined $min && $l < $min); |
427
|
8
|
100
|
100
|
|
|
25
|
return 0 if (defined $max && $l > $max); |
428
|
6
|
|
|
|
|
7
|
return 1; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
sub xml_is_token |
432
|
|
|
|
|
|
|
{ |
433
|
13
|
|
|
13
|
0
|
20
|
my ($what,$min,$max)=@_; |
434
|
|
|
|
|
|
|
|
435
|
13
|
100
|
|
|
|
28
|
return 0 unless defined $what; |
436
|
12
|
50
|
|
|
|
28
|
return 0 if defined Scalar::Util::reftype($what); |
437
|
12
|
100
|
|
|
|
20
|
return 0 if $what=~m/[\r\n\t]/; |
438
|
11
|
100
|
|
|
|
27
|
return 0 if $what=~m/^\s/; |
439
|
10
|
100
|
|
|
|
23
|
return 0 if $what=~m/\s$/; |
440
|
9
|
100
|
|
|
|
17
|
return 0 if $what=~m/\s\s/; |
441
|
|
|
|
|
|
|
|
442
|
8
|
|
|
|
|
35
|
my $l=length $what; |
443
|
8
|
100
|
100
|
|
|
28
|
return 0 if (defined $min && $l < $min); |
444
|
7
|
100
|
100
|
|
|
30
|
return 0 if (defined $max && $l > $max); |
445
|
5
|
|
|
|
|
13
|
return 1; |
446
|
|
|
|
|
|
|
} |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub xml_is_ncname ## xml:id is of this type |
449
|
|
|
|
|
|
|
{ |
450
|
0
|
|
|
0
|
0
|
0
|
my ($what)=@_; |
451
|
0
|
0
|
0
|
|
|
0
|
return 0 unless defined($what) && $what; |
452
|
0
|
0
|
|
|
|
0
|
return 0 if defined Scalar::Util::reftype($what); |
453
|
88
|
|
|
88
|
|
456
|
return ($what=~m/^\p{ID_Start}\p{ID_Continue}*$/) |
|
88
|
|
|
|
|
106
|
|
|
88
|
|
|
|
|
963
|
|
|
0
|
|
|
|
|
0
|
|
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
5
|
100
|
100
|
5
|
0
|
10
|
sub verify_ushort { my $in=shift; return (defined($in) && ($in=~m/^\d+$/) && ($in < 65536))? 1 : 0; } |
|
5
|
|
|
|
|
48
|
|
457
|
5
|
100
|
100
|
5
|
0
|
7
|
sub verify_ubyte { my $in=shift; return (defined($in) && ($in=~m/^\d+$/) && ($in < 256))? 1 : 0; } |
|
5
|
|
|
|
|
50
|
|
458
|
4
|
100
|
100
|
4
|
0
|
6
|
sub verify_hex { my $in=shift; return (defined($in) && ($in=~m/^[0-9A-F]+$/i))? 1 : 0; } |
|
4
|
|
|
|
|
28
|
|
459
|
|
|
|
|
|
|
sub verify_int |
460
|
|
|
|
|
|
|
{ |
461
|
13
|
|
|
13
|
0
|
25
|
my ($in,$min,$max)=@_; |
462
|
13
|
100
|
100
|
|
|
88
|
return 0 unless defined($in) && ($in=~m/^-?\d+$/); |
463
|
11
|
100
|
|
|
|
39
|
return 0 if ($in < (defined $min ? $min : -2147483648)); |
|
|
100
|
|
|
|
|
|
464
|
8
|
100
|
|
|
|
25
|
return 0 if ($in > (defined $max ? $max : 2147483647)); |
|
|
100
|
|
|
|
|
|
465
|
5
|
|
|
|
|
13
|
return 1; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub verify_base64 |
469
|
|
|
|
|
|
|
{ |
470
|
31
|
|
|
31
|
0
|
47
|
my ($in,$min,$max)=@_; |
471
|
31
|
|
|
|
|
25
|
my $b04='[AQgw]'; |
472
|
31
|
|
|
|
|
25
|
my $b16='[AEIMQUYcgkosw048]'; |
473
|
31
|
|
|
|
|
18
|
my $b64='[A-Za-z0-9+/]'; |
474
|
31
|
100
|
|
|
|
394
|
return 0 unless ($in=~m/^(?:(?:$b64 ?$b64 ?$b64 ?$b64 ?)*(?:(?:$b64 ?$b64 ?$b64 ?$b64)|(?:$b64 ?$b64 ?$b16 ?=)|(?:$b64 ?$b04 ?= ?=)))?$/); |
475
|
27
|
100
|
100
|
|
|
67
|
return 0 if (defined $min && (length $in < $min)); |
476
|
24
|
100
|
100
|
|
|
45
|
return 0 if (defined $max && (length $in > $max)); |
477
|
23
|
|
|
|
|
75
|
return 1; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
## Same in XML and in RFC3066 |
481
|
|
|
|
|
|
|
sub xml_is_language |
482
|
|
|
|
|
|
|
{ |
483
|
3
|
|
|
3
|
0
|
4
|
my $in=shift; |
484
|
3
|
50
|
|
|
|
7
|
return 0 unless defined $in; |
485
|
3
|
100
|
|
|
|
26
|
return 1 if ($in=~m/^[a-zA-Z]{1,8}(?:-[a-zA-Z0-9]{1,8})*$/); |
486
|
1
|
|
|
|
|
3
|
return 0; |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
sub xml_is_boolean |
490
|
|
|
|
|
|
|
{ |
491
|
6
|
|
|
6
|
0
|
8
|
my $in=shift; |
492
|
6
|
50
|
|
|
|
14
|
return 0 unless defined $in; |
493
|
6
|
100
|
|
|
|
30
|
return 1 if ($in=~m/^(?:1|0|true|false)$/); |
494
|
2
|
|
|
|
|
5
|
return 0; |
495
|
|
|
|
|
|
|
} |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
sub xml_parse_boolean |
498
|
|
|
|
|
|
|
{ |
499
|
0
|
|
|
0
|
0
|
0
|
my $in=shift; |
500
|
0
|
|
|
|
|
0
|
return {'true'=>1,1=>1,0=>0,'false'=>0}->{$in}; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
sub xml_escape |
504
|
|
|
|
|
|
|
{ |
505
|
0
|
|
|
0
|
0
|
0
|
my ($in)=@_; |
506
|
0
|
|
|
|
|
0
|
$in=~s/&/&/g; |
507
|
0
|
|
|
|
|
0
|
$in=~s/</g; |
508
|
0
|
|
|
|
|
0
|
$in=~s/>/>/g; |
509
|
0
|
|
|
|
|
0
|
return $in; |
510
|
|
|
|
|
|
|
} |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
sub xml_write |
513
|
|
|
|
|
|
|
{ |
514
|
0
|
|
|
0
|
0
|
0
|
my $rd=shift; |
515
|
0
|
|
|
|
|
0
|
my @t; |
516
|
0
|
0
|
|
|
|
0
|
foreach my $d (ref $rd->[0] ? @$rd : ($rd)) ## $d is a node=ref array |
517
|
|
|
|
|
|
|
{ |
518
|
0
|
|
|
|
|
0
|
my @c; ## list of children nodes |
519
|
|
|
|
|
|
|
my %attr; |
520
|
0
|
|
|
|
|
0
|
foreach my $e (grep { defined } @$d) |
|
0
|
|
|
|
|
0
|
|
521
|
|
|
|
|
|
|
{ |
522
|
0
|
0
|
|
|
|
0
|
if (ref $e eq 'HASH') |
523
|
|
|
|
|
|
|
{ |
524
|
0
|
|
|
|
|
0
|
while(my ($k,$v)=each(%$e)) { $attr{$k}=$v; } |
|
0
|
|
|
|
|
0
|
|
525
|
|
|
|
|
|
|
} else |
526
|
|
|
|
|
|
|
{ |
527
|
0
|
|
|
|
|
0
|
push @c,$e; |
528
|
|
|
|
|
|
|
} |
529
|
|
|
|
|
|
|
} |
530
|
0
|
|
|
|
|
0
|
my $tag=shift(@c); |
531
|
0
|
0
|
|
|
|
0
|
my $attr=keys(%attr)? ' '.join(' ',map { $_.'="'.$attr{$_}.'"' } sort { $a cmp $b } keys %attr) : ''; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
532
|
0
|
0
|
0
|
|
|
0
|
if (!@c || (@c==1 && !ref($c[0]) && ($c[0] eq ''))) |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
533
|
|
|
|
|
|
|
{ |
534
|
0
|
|
|
|
|
0
|
push @t,'<'.$tag.$attr.'/>'; |
535
|
|
|
|
|
|
|
} else |
536
|
|
|
|
|
|
|
{ |
537
|
0
|
|
|
|
|
0
|
push @t,'<'.$tag.$attr.'>'; |
538
|
0
|
0
|
0
|
|
|
0
|
push @t,(@c==1 && !ref($c[0]))? xml_escape($c[0]) : xml_write(\@c); |
539
|
0
|
|
|
|
|
0
|
push @t,''.$tag.'>'; |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
} |
542
|
0
|
|
|
|
|
0
|
return @t; |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
sub xml_indent |
546
|
|
|
|
|
|
|
{ |
547
|
0
|
|
|
0
|
0
|
0
|
my $xml=shift; |
548
|
0
|
|
|
|
|
0
|
chomp $xml; |
549
|
0
|
|
|
|
|
0
|
my $r=''; |
550
|
|
|
|
|
|
|
|
551
|
0
|
|
|
|
|
0
|
$xml=~s!(<)!\n$1!g; |
552
|
0
|
|
|
|
|
0
|
$xml=~s!<(\S+)>(.+)\n\1>!<$1>$2$1>!g; |
553
|
0
|
|
|
|
|
0
|
$xml=~s!<(\S+)((?:\s+\S+=['"][^'"]+['"])+)>(.+)\n\1>!<$1$2>$3$1>!g; |
554
|
|
|
|
|
|
|
|
555
|
0
|
|
|
|
|
0
|
my $s=0; |
556
|
0
|
|
|
|
|
0
|
foreach my $m (split(/\n/,$xml)) |
557
|
|
|
|
|
|
|
{ |
558
|
0
|
0
|
|
|
|
0
|
next if $m=~m/^\s*$/; |
559
|
0
|
0
|
|
|
|
0
|
$s-- if ($m=~m!^\S+>$!); |
560
|
|
|
|
|
|
|
|
561
|
0
|
|
|
|
|
0
|
$r.=' ' x $s; |
562
|
0
|
|
|
|
|
0
|
$r.=$m."\n"; |
563
|
|
|
|
|
|
|
|
564
|
0
|
0
|
|
|
|
0
|
$s++ if ($m=~m!^<[^>?]+[^/](?:\s+\S+=['"][^'"]+['"])*>$!); |
565
|
0
|
0
|
|
|
|
0
|
$s-- if ($m=~m!^\S+>$!); |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
## As xml_indent is used during logging, we do a final quick check (spaces should not be relevant anyway) |
569
|
|
|
|
|
|
|
## This test should probably be dumped as some point in the future when we are confident enough. But we got hit in the past by some subtleties, so... |
570
|
0
|
|
|
|
|
0
|
my $in=$xml; |
571
|
0
|
|
|
|
|
0
|
$in=~s/\s+//g; |
572
|
0
|
|
|
|
|
0
|
my $out=$r; |
573
|
0
|
|
|
|
|
0
|
$out=~s/\s+//g; |
574
|
0
|
0
|
|
|
|
0
|
if ($in ne $out) { Net::DRI::Exception::err_assert('xml_indent failed to do its job, please report !'); } |
|
0
|
|
|
|
|
0
|
|
575
|
|
|
|
|
|
|
|
576
|
0
|
|
|
|
|
0
|
return $r; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub xml_list_children |
580
|
|
|
|
|
|
|
{ |
581
|
0
|
|
|
0
|
0
|
0
|
my ($node, $name_filter)=@_; |
582
|
|
|
|
|
|
|
## '*' catch all element nodes being direct children of given node |
583
|
0
|
|
0
|
|
|
0
|
my @r = map { [ $_->localname() || $_->nodeName(),$_ ] } grep { $_->nodeType() == 1 } $node->getChildrenByTagName('*'); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
584
|
0
|
0
|
|
|
|
0
|
return @r unless defined $name_filter; |
585
|
0
|
|
|
|
|
0
|
return map { $_->[1] } grep { $_->[0] eq $name_filter } @r; |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
sub xml_traverse |
589
|
|
|
|
|
|
|
{ |
590
|
0
|
|
|
0
|
0
|
0
|
my ($node,$ns,@nodes)=@_; |
591
|
0
|
|
|
|
|
0
|
my $p=sprintf('*[namespace-uri()="%s" and local-name()="%s"]',$ns,shift(@nodes)); |
592
|
0
|
0
|
|
|
|
0
|
$p.='/'.join('/',map { '*[local-name()="'.$_.'"]' } @nodes) if @nodes; |
|
0
|
|
|
|
|
0
|
|
593
|
0
|
|
|
|
|
0
|
my $r=$node->findnodes($p); |
594
|
0
|
0
|
|
|
|
0
|
return unless $r->size(); |
595
|
0
|
0
|
|
|
|
0
|
return ($r->size()==1)? $r->get_node(1) : $r->get_nodelist(); |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub xml_child_content |
599
|
|
|
|
|
|
|
{ |
600
|
0
|
|
|
0
|
0
|
0
|
my ($node,$ns,$what)=@_; |
601
|
0
|
|
|
|
|
0
|
my $list=$node->getChildrenByTagNameNS($ns,$what); |
602
|
0
|
0
|
|
|
|
0
|
return undef unless $list->size()==1; ## no critic (Subroutines::ProhibitExplicitReturnUndef) |
603
|
0
|
|
|
|
|
0
|
my $n=$list->get_node(1); |
604
|
0
|
0
|
|
|
|
0
|
return defined $n ? $n->textContent() : undef; |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
#################################################################################################### |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
sub remcam |
610
|
|
|
|
|
|
|
{ |
611
|
0
|
|
|
0
|
0
|
0
|
my $in=shift; |
612
|
0
|
|
|
|
|
0
|
$in=~s/ID/_id/g; |
613
|
0
|
|
|
|
|
0
|
$in=~s/([A-Z])/_$1/g; |
614
|
0
|
|
|
|
|
0
|
return lc($in); |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
|
617
|
0
|
0
|
|
0
|
0
|
0
|
sub encode { my ($cs,$data)=@_; return Encode::encode($cs,ref $data? $data->as_string() : $data,1); } ## Will croak on malformed data (a case that should not happen) |
|
0
|
|
|
|
|
0
|
|
618
|
0
|
|
|
0
|
0
|
0
|
sub encode_utf8 { return encode('UTF-8',$_[0]); } ## no critic (Subroutines::RequireArgUnpacking) |
619
|
0
|
|
|
0
|
0
|
0
|
sub encode_ascii { return encode('ascii',$_[0]); } ## no critic (Subroutines::RequireArgUnpacking) |
620
|
0
|
|
|
0
|
0
|
0
|
sub decode { my ($cs,$data)=@_; return Encode::decode($cs,$data,1); } ## Will croak on malformed data (a case that should not happen) |
|
0
|
|
|
|
|
0
|
|
621
|
0
|
|
|
0
|
0
|
0
|
sub decode_utf8 { return decode('UTF-8',$_[0]); } ## no critic (Subroutines::RequireArgUnpacking) |
622
|
0
|
|
|
0
|
0
|
0
|
sub decode_ascii { return decode('ascii',$_[0]); } ## no critic (Subroutines::RequireArgUnpacking) |
623
|
0
|
|
|
0
|
0
|
0
|
sub decode_latin1{ return decode('iso-8859-1',$_[0]); } ## no critic (Subroutines::RequireArgUnpacking) |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
sub normalize_name |
626
|
|
|
|
|
|
|
{ |
627
|
15
|
|
|
15
|
0
|
17
|
my ($type,$key)=@_; |
628
|
15
|
|
|
|
|
20
|
$type=lc($type); |
629
|
|
|
|
|
|
|
## contact IDs may be case sensitive... |
630
|
|
|
|
|
|
|
## Will need to be redone differently with IDNs |
631
|
15
|
100
|
66
|
|
|
44
|
$key=lc $key if ($type eq 'domain' || $type eq 'nsgroup'); |
632
|
15
|
100
|
66
|
|
|
37
|
$key=lc $key if ($type eq 'host' && $key=~m/\./); ## last test part is done only to handle the pure mess created by Nominet .UK "EPP" implementation... |
633
|
15
|
|
|
|
|
30
|
return ($type,$key); |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
## DateTime object to Zulu time stringified |
637
|
|
|
|
|
|
|
sub dto2zstring |
638
|
|
|
|
|
|
|
{ |
639
|
0
|
|
|
0
|
0
|
0
|
my ($dt)=@_; |
640
|
0
|
|
|
|
|
0
|
my $date=$dt->clone()->set_time_zone('UTC'); |
641
|
0
|
0
|
|
|
|
0
|
return $date->ymd('-').'T'.$date->hms(':').($date->microsecond() ? '.'.sprintf('%06s',$date->microsecond()) : '').'Z'; |
642
|
|
|
|
|
|
|
} |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
#################################################################################################### |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
## RFC2782 |
647
|
|
|
|
|
|
|
## (Net::DNS rrsort for SRV records does not seem to implement the same algorithm as the one specificied in the RFC, |
648
|
|
|
|
|
|
|
## as it just does a comparison on priority then weight) |
649
|
|
|
|
|
|
|
sub dns_srv_order |
650
|
|
|
|
|
|
|
{ |
651
|
0
|
|
|
0
|
0
|
0
|
my (@args)=@_; |
652
|
0
|
|
|
|
|
0
|
my (@r,%r); |
653
|
0
|
|
|
|
|
0
|
foreach my $ans (@args) |
654
|
|
|
|
|
|
|
{ |
655
|
0
|
|
|
|
|
0
|
push @{$r{$ans->priority()}},$ans; |
|
0
|
|
|
|
|
0
|
|
656
|
|
|
|
|
|
|
} |
657
|
0
|
|
|
|
|
0
|
foreach my $pri (sort { $a <=> $b } keys(%r)) |
|
0
|
|
|
|
|
0
|
|
658
|
|
|
|
|
|
|
{ |
659
|
0
|
|
|
|
|
0
|
my @o=@{$r{$pri}}; |
|
0
|
|
|
|
|
0
|
|
660
|
0
|
0
|
|
|
|
0
|
if (@o > 1) |
661
|
|
|
|
|
|
|
{ |
662
|
0
|
|
|
|
|
0
|
my $ts=0; |
663
|
0
|
|
|
|
|
0
|
foreach (@o) { $ts+=$_->weight(); } |
|
0
|
|
|
|
|
0
|
|
664
|
0
|
|
|
|
|
0
|
my $s=0; |
665
|
0
|
|
|
|
|
0
|
@o=map { $s+=$_->weight(); [ $s, $_ ] } (grep { $_->weight() == 0 } @o, grep { $_->weight() > 0 } @o); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
666
|
0
|
|
|
|
|
0
|
my $cs=0; |
667
|
0
|
|
|
|
|
0
|
while(@o > 1) |
668
|
|
|
|
|
|
|
{ |
669
|
0
|
|
|
|
|
0
|
my $r=int(rand($ts-$cs+1)); |
670
|
0
|
|
|
|
|
0
|
foreach my $i (0..$#o) |
671
|
|
|
|
|
|
|
{ |
672
|
0
|
0
|
|
|
|
0
|
next unless $o[$i]->[0] >= $r; |
673
|
0
|
|
|
|
|
0
|
$cs+=$o[$i]->[0]; |
674
|
0
|
|
|
|
|
0
|
foreach my $j (($i+1)..$#o) { $o[$j]->[0]-=$o[$i]->[0]; } |
|
0
|
|
|
|
|
0
|
|
675
|
0
|
|
|
|
|
0
|
push @r,$o[$i]->[1]; |
676
|
0
|
|
|
|
|
0
|
splice(@o,$i,1); |
677
|
0
|
|
|
|
|
0
|
last; |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
} |
681
|
0
|
|
|
|
|
0
|
push @r,$o[0]->[1]; |
682
|
|
|
|
|
|
|
} |
683
|
0
|
|
|
|
|
0
|
return map { [$_->target(),$_->port()] } @r; |
|
0
|
|
|
|
|
0
|
|
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
#################################################################################################### |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
sub load_module |
689
|
|
|
|
|
|
|
{ |
690
|
271
|
|
|
271
|
0
|
411
|
my ($class,$etype)=@_; |
691
|
271
|
|
|
|
|
294
|
my $ok = eval { Module::Load::load($class); 1; }; |
|
271
|
|
|
|
|
726
|
|
|
204
|
|
|
|
|
1985
|
|
692
|
271
|
100
|
50
|
|
|
12766
|
Net::DRI::Exception::err_failed_load_module($etype,$class,$@ // 'unknown error') if ! defined $ok || ! $ok || $@; |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
693
|
204
|
|
|
|
|
525
|
return; |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
#################################################################################################### |
697
|
|
|
|
|
|
|
1; |