line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# |
2
|
|
|
|
|
|
|
# Constraints.pm - Standard constraints for use in Data::FormValidator. |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# This file is part of Data::FormValidator. |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Author: Francis J. Lacoste |
7
|
|
|
|
|
|
|
# Maintainer: Mark Stosberg |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# Copyright (C) 1999,2000 iNsu Innovations Inc. |
10
|
|
|
|
|
|
|
# Copyright (C) 2001 Francis J. Lacoste |
11
|
|
|
|
|
|
|
# Parts Copyright 1996-1999 by Michael J. Heins |
12
|
|
|
|
|
|
|
# Parts Copyright 1996-1999 by Bruce Albrecht |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
# Parts of this module are based on work by |
15
|
|
|
|
|
|
|
# Bruce Albrecht, contributed to MiniVend. |
16
|
|
|
|
|
|
|
# |
17
|
|
|
|
|
|
|
# Parts also based on work by Michael J. Heins |
18
|
|
|
|
|
|
|
# |
19
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
20
|
|
|
|
|
|
|
# it under the terms same terms as perl itself. |
21
|
|
|
|
|
|
|
# |
22
|
|
|
|
|
|
|
package Data::FormValidator::Constraints; |
23
|
59
|
|
|
59
|
|
211
|
use base 'Exporter'; |
|
59
|
|
|
|
|
64
|
|
|
59
|
|
|
|
|
5091
|
|
24
|
59
|
|
|
59
|
|
209
|
use strict; |
|
59
|
|
|
|
|
65
|
|
|
59
|
|
|
|
|
2131
|
|
25
|
|
|
|
|
|
|
our $AUTOLOAD; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our $VERSION = 4.85; |
28
|
|
|
|
|
|
|
|
29
|
0
|
|
|
|
|
0
|
BEGIN { |
30
|
59
|
|
|
59
|
|
198
|
use Carp; |
|
59
|
|
|
|
|
77
|
|
|
59
|
|
|
|
|
17130
|
|
31
|
59
|
|
|
59
|
|
188
|
my @closures = (qw/ |
32
|
|
|
|
|
|
|
american_phone |
33
|
|
|
|
|
|
|
cc_exp |
34
|
|
|
|
|
|
|
cc_number |
35
|
|
|
|
|
|
|
cc_type |
36
|
|
|
|
|
|
|
email |
37
|
|
|
|
|
|
|
ip_address |
38
|
|
|
|
|
|
|
phone |
39
|
|
|
|
|
|
|
postcode |
40
|
|
|
|
|
|
|
province |
41
|
|
|
|
|
|
|
state |
42
|
|
|
|
|
|
|
state_or_province |
43
|
|
|
|
|
|
|
zip |
44
|
|
|
|
|
|
|
zip_or_postcode/); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# This be optimized with some of the voodoo that CGI.pm |
47
|
|
|
|
|
|
|
# uses to AUTOLOAD dynamic functions. |
48
|
59
|
|
|
|
|
125
|
for my $func (@closures) { |
49
|
|
|
|
|
|
|
# cc_number is defined statically |
50
|
767
|
100
|
|
|
|
1568
|
unless ($func eq 'cc_number') { |
51
|
|
|
|
|
|
|
# Notice we have to escape some characters |
52
|
|
|
|
|
|
|
# in the subroutine, which is really a string here. |
53
|
|
|
|
|
|
|
|
54
|
708
|
|
|
|
|
2121
|
local $SIG{__DIE__} = \&confess; |
55
|
708
|
|
|
|
|
1751
|
my $code = qq! |
56
|
|
|
|
|
|
|
sub $func { |
57
|
|
|
|
|
|
|
return sub { |
58
|
|
|
|
|
|
|
my \$dfv = shift; |
59
|
|
|
|
|
|
|
use Scalar::Util (); |
60
|
|
|
|
|
|
|
die "first arg to $func was not an object. Must be called as a constraint_method." |
61
|
|
|
|
|
|
|
unless ( Scalar::Util::blessed(\$dfv) && \$dfv->can('name_this') ); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
\$dfv->name_this('$func') unless \$dfv->get_current_constraint_name(); |
64
|
|
|
|
|
|
|
no strict 'refs'; |
65
|
|
|
|
|
|
|
return &{"match_$func"}(\@_); |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
!; |
69
|
|
|
|
|
|
|
|
70
|
708
|
0
|
0
|
59
|
1
|
43001
|
eval "package Data::FormValidator::Constraints; $code"; |
|
59
|
0
|
0
|
59
|
1
|
225
|
|
|
59
|
0
|
33
|
59
|
1
|
75
|
|
|
59
|
0
|
0
|
59
|
1
|
2617
|
|
|
59
|
50
|
0
|
59
|
1
|
235
|
|
|
59
|
50
|
0
|
59
|
1
|
72
|
|
|
59
|
0
|
0
|
59
|
1
|
2840
|
|
|
59
|
0
|
0
|
59
|
1
|
249
|
|
|
59
|
0
|
0
|
59
|
1
|
68
|
|
|
59
|
0
|
0
|
59
|
1
|
2629
|
|
|
59
|
0
|
0
|
59
|
1
|
198
|
|
|
59
|
0
|
0
|
59
|
1
|
75
|
|
|
59
|
0
|
|
59
|
|
2740
|
|
|
59
|
0
|
|
59
|
|
241
|
|
|
59
|
0
|
|
59
|
|
68
|
|
|
59
|
0
|
|
59
|
|
2445
|
|
|
59
|
0
|
|
59
|
|
183
|
|
|
59
|
0
|
|
59
|
|
60
|
|
|
59
|
0
|
|
59
|
|
2624
|
|
|
59
|
0
|
|
59
|
|
228
|
|
|
59
|
0
|
|
59
|
|
68
|
|
|
59
|
0
|
|
59
|
|
2421
|
|
|
59
|
0
|
|
59
|
|
180
|
|
|
59
|
0
|
|
59
|
|
61
|
|
|
59
|
|
|
0
|
|
2647
|
|
|
59
|
|
|
0
|
|
229
|
|
|
59
|
|
|
0
|
|
67
|
|
|
59
|
|
|
0
|
|
2311
|
|
|
59
|
|
|
1
|
|
178
|
|
|
59
|
|
|
0
|
|
62
|
|
|
59
|
|
|
0
|
|
3977
|
|
|
59
|
|
|
0
|
|
226
|
|
|
59
|
|
|
0
|
|
66
|
|
|
59
|
|
|
0
|
|
2321
|
|
|
59
|
|
|
0
|
|
179
|
|
|
59
|
|
|
0
|
|
68
|
|
|
59
|
|
|
0
|
|
2588
|
|
|
59
|
|
|
|
|
223
|
|
|
59
|
|
|
|
|
65
|
|
|
59
|
|
|
|
|
2431
|
|
|
59
|
|
|
|
|
809
|
|
|
59
|
|
|
|
|
79
|
|
|
59
|
|
|
|
|
5027
|
|
|
59
|
|
|
|
|
232
|
|
|
59
|
|
|
|
|
769
|
|
|
59
|
|
|
|
|
2421
|
|
|
59
|
|
|
|
|
192
|
|
|
59
|
|
|
|
|
61
|
|
|
59
|
|
|
|
|
2438
|
|
|
59
|
|
|
|
|
214
|
|
|
59
|
|
|
|
|
63
|
|
|
59
|
|
|
|
|
2345
|
|
|
59
|
|
|
|
|
194
|
|
|
59
|
|
|
|
|
76
|
|
|
59
|
|
|
|
|
2492
|
|
|
59
|
|
|
|
|
252
|
|
|
59
|
|
|
|
|
79
|
|
|
59
|
|
|
|
|
2320
|
|
|
59
|
|
|
|
|
183
|
|
|
59
|
|
|
|
|
81
|
|
|
59
|
|
|
|
|
2490
|
|
|
59
|
|
|
|
|
206
|
|
|
59
|
|
|
|
|
65
|
|
|
59
|
|
|
|
|
2305
|
|
|
59
|
|
|
|
|
178
|
|
|
59
|
|
|
|
|
64
|
|
|
59
|
|
|
|
|
2507
|
|
|
59
|
|
|
|
|
242
|
|
|
59
|
|
|
|
|
160
|
|
|
59
|
|
|
|
|
2266
|
|
|
59
|
|
|
|
|
175
|
|
|
59
|
|
|
|
|
1456
|
|
|
59
|
|
|
|
|
3108
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
13
|
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
5
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
40
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
71
|
708
|
50
|
|
|
|
2874
|
die "couldn't create $func: $@" if $@; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
59
|
|
|
|
|
2154
|
my @FVs = (qw/ |
76
|
|
|
|
|
|
|
FV_length_between |
77
|
|
|
|
|
|
|
FV_min_length |
78
|
|
|
|
|
|
|
FV_max_length |
79
|
|
|
|
|
|
|
FV_eq_with |
80
|
|
|
|
|
|
|
FV_num_values |
81
|
|
|
|
|
|
|
FV_num_values_between |
82
|
|
|
|
|
|
|
/); |
83
|
|
|
|
|
|
|
|
84
|
59
|
|
|
|
|
972
|
our @EXPORT_OK = ( |
85
|
|
|
|
|
|
|
@closures, |
86
|
|
|
|
|
|
|
@FVs, |
87
|
|
|
|
|
|
|
qw( |
88
|
|
|
|
|
|
|
valid_american_phone |
89
|
|
|
|
|
|
|
valid_cc_exp |
90
|
|
|
|
|
|
|
valid_cc_number |
91
|
|
|
|
|
|
|
valid_cc_type |
92
|
|
|
|
|
|
|
valid_email |
93
|
|
|
|
|
|
|
valid_ip_address |
94
|
|
|
|
|
|
|
valid_phone |
95
|
|
|
|
|
|
|
valid_postcode |
96
|
|
|
|
|
|
|
valid_province |
97
|
|
|
|
|
|
|
valid_state |
98
|
|
|
|
|
|
|
valid_state_or_province |
99
|
|
|
|
|
|
|
valid_zip |
100
|
|
|
|
|
|
|
valid_zip_or_postcode |
101
|
|
|
|
|
|
|
match_american_phone |
102
|
|
|
|
|
|
|
match_cc_exp |
103
|
|
|
|
|
|
|
match_cc_number |
104
|
|
|
|
|
|
|
match_cc_type |
105
|
|
|
|
|
|
|
match_email |
106
|
|
|
|
|
|
|
match_ip_address |
107
|
|
|
|
|
|
|
match_phone |
108
|
|
|
|
|
|
|
match_postcode |
109
|
|
|
|
|
|
|
match_province |
110
|
|
|
|
|
|
|
match_state |
111
|
|
|
|
|
|
|
match_state_or_province |
112
|
|
|
|
|
|
|
match_zip |
113
|
|
|
|
|
|
|
match_zip_or_postcode) |
114
|
|
|
|
|
|
|
); |
115
|
|
|
|
|
|
|
|
116
|
59
|
|
|
|
|
6177
|
our %EXPORT_TAGS = ( |
117
|
|
|
|
|
|
|
# regexp common is correctly empty here, because we handle the case on the fly with the import function below. |
118
|
|
|
|
|
|
|
regexp_common => [], |
119
|
|
|
|
|
|
|
closures => [ @closures, @FVs ], |
120
|
|
|
|
|
|
|
validators => [qw/ |
121
|
|
|
|
|
|
|
valid_american_phone |
122
|
|
|
|
|
|
|
valid_cc_exp |
123
|
|
|
|
|
|
|
valid_cc_number |
124
|
|
|
|
|
|
|
valid_cc_type |
125
|
|
|
|
|
|
|
valid_email |
126
|
|
|
|
|
|
|
valid_ip_address |
127
|
|
|
|
|
|
|
valid_phone |
128
|
|
|
|
|
|
|
valid_postcode |
129
|
|
|
|
|
|
|
valid_province |
130
|
|
|
|
|
|
|
valid_state |
131
|
|
|
|
|
|
|
valid_state_or_province |
132
|
|
|
|
|
|
|
valid_zip |
133
|
|
|
|
|
|
|
valid_zip_or_postcode |
134
|
|
|
|
|
|
|
/], |
135
|
|
|
|
|
|
|
matchers => [qw/ |
136
|
|
|
|
|
|
|
match_american_phone |
137
|
|
|
|
|
|
|
match_cc_exp |
138
|
|
|
|
|
|
|
match_cc_number |
139
|
|
|
|
|
|
|
match_cc_type |
140
|
|
|
|
|
|
|
match_email |
141
|
|
|
|
|
|
|
match_ip_address |
142
|
|
|
|
|
|
|
match_phone |
143
|
|
|
|
|
|
|
match_postcode |
144
|
|
|
|
|
|
|
match_province |
145
|
|
|
|
|
|
|
match_state |
146
|
|
|
|
|
|
|
match_state_or_province |
147
|
|
|
|
|
|
|
match_zip |
148
|
|
|
|
|
|
|
match_zip_or_postcode |
149
|
|
|
|
|
|
|
/], |
150
|
|
|
|
|
|
|
); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub import { |
153
|
|
|
|
|
|
|
# This is Regexp::Common support. |
154
|
|
|
|
|
|
|
# Here we are handling cases that look like this: |
155
|
|
|
|
|
|
|
# |
156
|
|
|
|
|
|
|
# my_field => FV_foo_bar(-zoo=>'queue'), |
157
|
126
|
100
|
|
126
|
|
1296
|
if (grep { m/^:regexp_common$/ } @_) { |
|
373
|
|
|
|
|
874
|
|
158
|
1
|
|
|
|
|
582
|
require Regexp::Common; |
159
|
1
|
|
|
|
|
2364
|
import Regexp::Common 'RE_ALL'; |
160
|
|
|
|
|
|
|
|
161
|
1
|
|
|
|
|
131615
|
for my $sub (grep { m/^RE_/} keys %Data::FormValidator::Constraints:: ) { |
|
236
|
|
|
|
|
207
|
|
162
|
59
|
|
|
59
|
|
247
|
no strict 'refs'; |
|
59
|
|
|
|
|
70
|
|
|
59
|
|
|
|
|
5339
|
|
163
|
173
|
|
|
|
|
112
|
my $new_name = $sub; |
164
|
173
|
|
|
|
|
274
|
$new_name =~ s/^RE_/FV_/; |
165
|
173
|
|
|
|
|
490
|
*{caller() . "::$new_name"} = sub { |
166
|
6
|
|
|
6
|
|
50
|
my @params = @_; |
167
|
|
|
|
|
|
|
return sub { |
168
|
9
|
|
|
9
|
|
13
|
my $dfv = shift; |
169
|
9
|
50
|
|
|
|
23
|
$dfv->name_this($new_name) unless $dfv->get_current_constraint_name(); |
170
|
|
|
|
|
|
|
|
171
|
59
|
|
|
59
|
|
221
|
no strict "refs"; |
|
59
|
|
|
|
|
67
|
|
|
59
|
|
|
|
|
6831
|
|
172
|
9
|
|
|
|
|
63
|
my $re = &$sub(-keep=>1,@params); |
173
|
9
|
|
|
|
|
767
|
my ($match) = ($dfv->get_current_constraint_value =~ qr/^($re)$/); |
174
|
9
|
|
|
|
|
51
|
return $dfv->untainted_constraint_value($match); |
175
|
|
|
|
|
|
|
} |
176
|
6
|
|
|
|
|
90
|
} |
177
|
173
|
|
|
|
|
316
|
} |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
126
|
|
|
|
|
41473
|
Data::FormValidator::Constraints->export_to_level(1,@_); |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# sub DESTROY {} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=pod |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 NAME |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Data::FormValidator::Constraints - Basic sets of constraints on input profile. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=head1 SYNOPSIS |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
use Data::FormValidator::Constraints qw(:closures); |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
In an Data::FormValidator profile: |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
constraint_methods => { |
201
|
|
|
|
|
|
|
email => email(), |
202
|
|
|
|
|
|
|
phone => american_phone(), |
203
|
|
|
|
|
|
|
first_names => { |
204
|
|
|
|
|
|
|
constraint_method => FV_max_length(3), |
205
|
|
|
|
|
|
|
name => 'my_custom_name', |
206
|
|
|
|
|
|
|
}, |
207
|
|
|
|
|
|
|
}, |
208
|
|
|
|
|
|
|
msgs => { |
209
|
|
|
|
|
|
|
constraints => { |
210
|
|
|
|
|
|
|
my_custom_name => 'My message', |
211
|
|
|
|
|
|
|
}, |
212
|
|
|
|
|
|
|
}, |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head1 DESCRIPTION |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
These are the builtin constraints that can be specified by name in the input |
219
|
|
|
|
|
|
|
profiles. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Be sure to check out the SEE ALSO section for even more pre-packaged |
222
|
|
|
|
|
|
|
constraints you can use. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub AUTOLOAD { |
227
|
34
|
|
|
34
|
|
6364
|
my $name = $AUTOLOAD; |
228
|
|
|
|
|
|
|
|
229
|
59
|
|
|
59
|
|
214
|
no strict qw/refs/; |
|
59
|
|
|
|
|
65
|
|
|
59
|
|
|
|
|
118390
|
|
230
|
|
|
|
|
|
|
|
231
|
34
|
|
|
|
|
111
|
$name =~ m/^(.*::)(valid_|RE_)(.*)/; |
232
|
|
|
|
|
|
|
|
233
|
34
|
|
|
|
|
72
|
my ($pkg,$prefix,$sub) = ($1,$2,$3); |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
#warn "hello! my ($pkg,$prefix,$sub) = ($1,$2,$3);"; |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# Since all the valid_* routines are essentially identical we're |
238
|
|
|
|
|
|
|
# going to generate them dynamically from match_ routines with the same names. |
239
|
34
|
50
|
33
|
|
|
167
|
if ((defined $prefix) and ($prefix eq 'valid_')) { |
240
|
34
|
|
|
|
|
33
|
return defined &{$pkg.'match_' . $sub}(@_); |
|
34
|
|
|
|
|
135
|
|
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=head2 FV_length_between(1,23) |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
=head2 FV_max_length(23) |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=head2 FV_min_length(1) |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
use Data::FormValidator::Constraints qw( |
251
|
|
|
|
|
|
|
FV_length_between |
252
|
|
|
|
|
|
|
FV_min_length |
253
|
|
|
|
|
|
|
FV_max_length |
254
|
|
|
|
|
|
|
); |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
constraint_methods => { |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
# specify a min and max, inclusive |
259
|
|
|
|
|
|
|
last_name => FV_length_between(1,23), |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
Specify a length constraint for a field. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
These constraints have a different naming convention because they are higher-order |
266
|
|
|
|
|
|
|
functions. They take input and return a code reference to a standard constraint |
267
|
|
|
|
|
|
|
method. A constraint name of C, C, or C will be set, |
268
|
|
|
|
|
|
|
corresponding to the function name you choose. |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
The checks are all inclusive, so a max length of '100' will allow the length 100. |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
Length is measured in perl characters as opposed to bytes or anything else. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
This constraint I untaint your data if you have untainting turned on. However, |
275
|
|
|
|
|
|
|
a length check alone may not be enough to insure the safety of the data you are receiving. |
276
|
|
|
|
|
|
|
Using additional constraints to check the data is encouraged. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=cut |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub FV_length_between { |
281
|
8
|
|
|
8
|
1
|
6
|
my ($min,$max) = @_; |
282
|
8
|
50
|
33
|
|
|
26
|
if (not (defined $min and defined $max)) { |
283
|
0
|
|
|
|
|
0
|
croak "min and max are required"; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
return sub { |
286
|
8
|
|
|
8
|
|
6
|
my ($dfv,$value) = @_; |
287
|
8
|
100
|
|
|
|
16
|
$dfv->name_this('length_between') unless $dfv->get_current_constraint_name(); |
288
|
8
|
100
|
100
|
|
|
1065
|
return undef if ( ( length($value) > $max ) || ( length($value) < $min) ); |
289
|
|
|
|
|
|
|
# Use a regexp to untaint |
290
|
3
|
|
|
|
|
346
|
$value=~/(.*)/s; |
291
|
3
|
|
|
|
|
8
|
return $dfv->untainted_constraint_value($1); |
292
|
|
|
|
|
|
|
} |
293
|
8
|
|
|
|
|
44
|
} |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub FV_max_length { |
296
|
6
|
|
|
6
|
1
|
999
|
my ($max) = @_; |
297
|
6
|
50
|
|
|
|
12
|
croak "max is required" unless defined $max; |
298
|
|
|
|
|
|
|
return sub { |
299
|
6
|
|
|
6
|
|
8
|
my ($dfv,$value) = @_; |
300
|
6
|
100
|
|
|
|
13
|
$dfv->name_this('max_length') unless $dfv->get_current_constraint_name(); |
301
|
6
|
100
|
|
|
|
698
|
return undef if ( length($value) > $max ); |
302
|
|
|
|
|
|
|
# Use a regexp to untaint |
303
|
2
|
|
|
|
|
346
|
$value=~/(.*)/s; |
304
|
2
|
|
|
|
|
7
|
return $dfv->untainted_constraint_value($1); |
305
|
|
|
|
|
|
|
} |
306
|
6
|
|
|
|
|
60
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub FV_min_length { |
309
|
5
|
|
|
5
|
1
|
5
|
my ($min) = @_; |
310
|
5
|
50
|
|
|
|
6
|
croak "min is required" unless defined $min; |
311
|
|
|
|
|
|
|
return sub { |
312
|
4
|
|
|
4
|
|
3
|
my ($dfv,$value) = @_; |
313
|
4
|
50
|
|
|
|
8
|
$dfv->name_this('min_length') unless $dfv->get_current_constraint_name(); |
314
|
4
|
100
|
|
|
|
724
|
return undef if ( length($value) < $min ); |
315
|
|
|
|
|
|
|
# Use a regexp to untaint |
316
|
2
|
|
|
|
|
343
|
$value=~/(.*)/s; |
317
|
2
|
|
|
|
|
5
|
return $dfv->untainted_constraint_value($1); |
318
|
|
|
|
|
|
|
} |
319
|
5
|
|
|
|
|
17
|
} |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=head2 FV_eq_with |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
use Data::FormValidator::Constraints qw( FV_eq_with ); |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
constraint_methods => { |
326
|
|
|
|
|
|
|
password => FV_eq_with('password_confirm'), |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Compares the current field to another field. |
330
|
|
|
|
|
|
|
A constraint name of C will be set. |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=cut |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub FV_eq_with { |
335
|
2
|
|
|
2
|
1
|
486
|
my ($other_field) = @_; |
336
|
|
|
|
|
|
|
return sub { |
337
|
2
|
|
|
2
|
|
5
|
my $dfv = shift; |
338
|
2
|
50
|
|
|
|
10
|
$dfv->name_this('eq_with') unless $dfv->get_current_constraint_name(); |
339
|
|
|
|
|
|
|
|
340
|
2
|
|
|
|
|
8
|
my $curr_val = $dfv->get_current_constraint_value; |
341
|
|
|
|
|
|
|
|
342
|
2
|
|
|
|
|
6
|
my $data = $dfv->get_filtered_data; |
343
|
|
|
|
|
|
|
# Sometimes the data comes through both ways... |
344
|
2
|
50
|
|
|
|
7
|
my $other_val = (ref $data->{$other_field}) ? $data->{$other_field}[0] : $data->{$other_field}; |
345
|
|
|
|
|
|
|
|
346
|
2
|
|
|
|
|
4
|
return ($curr_val eq $other_val); |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
2
|
|
|
|
|
24
|
} |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 FV_num_values |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
use Data::FormValidator::Constraints qw ( FV_num_values ); |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
constraint_methods => { |
356
|
|
|
|
|
|
|
attachments => FV_num_values(4), |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
Checks the number of values in the array named by this param. |
360
|
|
|
|
|
|
|
Note that this is useful for making sure that only one value was passed for a |
361
|
|
|
|
|
|
|
given param (by supplying a size argument of 1). |
362
|
|
|
|
|
|
|
A constraint name of C will be set. |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
=cut |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
sub FV_num_values { |
367
|
2
|
|
33
|
2
|
1
|
22
|
my $size = shift || croak 'size argument is required'; |
368
|
|
|
|
|
|
|
return sub { |
369
|
3
|
|
|
3
|
|
2
|
my $dfv = shift; |
370
|
3
|
|
|
|
|
8
|
$dfv->name_this('num_values'); |
371
|
3
|
|
|
|
|
5
|
my $param = $dfv->get_current_constraint_field(); |
372
|
3
|
|
|
|
|
7
|
my $value = $dfv->get_filtered_data()->{$param}; |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# If there's an arrayref of values provided, test the number of them found |
375
|
|
|
|
|
|
|
# against the number of them of required |
376
|
3
|
50
|
33
|
|
|
16
|
if (defined $value and ref $value eq 'ARRAY') { |
|
|
0
|
|
|
|
|
|
377
|
3
|
|
|
|
|
2
|
my $num_values_found = scalar @$value; |
378
|
3
|
|
|
|
|
6
|
return ($num_values_found == $size); |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
# If a size of 1 was requested, there was not an arrayref of values, |
381
|
|
|
|
|
|
|
# there must be exactly one value. |
382
|
|
|
|
|
|
|
elsif ($size == 1) { |
383
|
0
|
|
|
|
|
0
|
return 1; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
# Any other case is failure. |
386
|
|
|
|
|
|
|
else { |
387
|
0
|
|
|
|
|
0
|
return 0; |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
} |
390
|
2
|
|
|
|
|
13
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=head2 FV_num_values_between |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
use Data::FormValidator::Constraints qw ( FV_num_values_between ); |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
constraint_methods => { |
397
|
|
|
|
|
|
|
attachments => FV_num_values_between(1,4), |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
Checks that the number of values in the array named by this param is between |
401
|
|
|
|
|
|
|
the supplied bounds (inclusively). |
402
|
|
|
|
|
|
|
A constraint name of C will be set. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=cut |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub FV_num_values_between { |
407
|
2
|
|
|
2
|
1
|
3
|
my ($min, $max) = @_; |
408
|
2
|
50
|
33
|
|
|
9
|
croak 'min and max arguments are required' unless $min && $max; |
409
|
|
|
|
|
|
|
return sub { |
410
|
2
|
|
|
2
|
|
2
|
my $dfv = shift; |
411
|
2
|
|
|
|
|
5
|
$dfv->name_this('num_values_between'); |
412
|
2
|
|
|
|
|
4
|
my $param = $dfv->get_current_constraint_field(); |
413
|
2
|
|
|
|
|
4
|
my $value = $dfv->get_filtered_data()->{$param}; |
414
|
|
|
|
|
|
|
|
415
|
2
|
|
|
|
|
3
|
my $num_values = scalar @$value; |
416
|
|
|
|
|
|
|
|
417
|
2
|
50
|
66
|
|
|
11
|
return ($num_values >= $min) && ($num_values <= $max) if ref $value eq 'ARRAY'; |
418
|
0
|
0
|
0
|
|
|
0
|
return 1 if $min == 0 && $max >= 2; # scalar, size could be 1 |
419
|
0
|
|
|
|
|
0
|
return 0; # scalar, size can't be 1 |
420
|
|
|
|
|
|
|
} |
421
|
2
|
|
|
|
|
16
|
} |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=head2 email |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
Checks if the email LOOKS LIKE an email address. This should be sufficient |
426
|
|
|
|
|
|
|
99% of the time. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
Look elsewhere if you want something super fancy that matches every possible variation |
429
|
|
|
|
|
|
|
that is valid in the RFC, or runs out and checks some MX records. |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=cut |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
# Many of the following validators are taken from |
434
|
|
|
|
|
|
|
# MiniVend 3.14. (http://www.minivend.com) |
435
|
|
|
|
|
|
|
# Copyright 1996-1999 by Michael J. Heins |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
sub match_email { |
438
|
36
|
|
|
36
|
0
|
1007
|
my $in_email = shift; |
439
|
|
|
|
|
|
|
|
440
|
36
|
|
|
|
|
6586
|
require Email::Valid; |
441
|
36
|
|
|
|
|
1096362
|
my $valid_email; |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
# The extra check that the result matches the input prevents |
444
|
|
|
|
|
|
|
# an address like this from being considered valid: Joe Smith |
445
|
36
|
100
|
100
|
|
|
179
|
if ( ($valid_email = Email::Valid->address($in_email) ) |
446
|
|
|
|
|
|
|
and ($valid_email eq $in_email)) { |
447
|
10
|
|
|
|
|
7471
|
return $valid_email; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
else { |
450
|
26
|
|
|
|
|
11260
|
return undef; |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
my $state = <
|
455
|
|
|
|
|
|
|
AL AK AZ AR CA CO CT DE FL GA HI ID IL IN IA KS KY LA ME MD |
456
|
|
|
|
|
|
|
MA MI MN MS MO MT NE NV NH NJ NM NY NC ND OH OK OR PA PR RI |
457
|
|
|
|
|
|
|
SC SD TN TX UT VT VA WA WV WI WY DC AP FP FPO APO GU VI |
458
|
|
|
|
|
|
|
EOF |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
my $province = <
|
461
|
|
|
|
|
|
|
AB BC MB NB NF NL NS NT NU ON PE QC SK YT YK |
462
|
|
|
|
|
|
|
EOF |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=head2 state_or_province |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
This one checks if the input correspond to an american state or a canadian |
467
|
|
|
|
|
|
|
province. |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=cut |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
sub match_state_or_province { |
472
|
4
|
|
|
4
|
0
|
607
|
my $match; |
473
|
4
|
50
|
|
|
|
7
|
if ($match = match_state(@_)) { |
474
|
0
|
|
|
|
|
0
|
return $match; |
475
|
|
|
|
|
|
|
} |
476
|
|
|
|
|
|
|
else { |
477
|
4
|
|
|
|
|
7
|
return match_province(@_); |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=head2 state |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
This one checks if the input is a valid two letter abbreviation of an |
484
|
|
|
|
|
|
|
American state. |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
=cut |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
sub match_state { |
489
|
11
|
|
|
11
|
0
|
603
|
my $val = shift; |
490
|
11
|
100
|
|
|
|
180
|
if ($state =~ /\b($val)\b/i) { |
491
|
2
|
|
|
|
|
15
|
return $1; |
492
|
|
|
|
|
|
|
} |
493
|
9
|
|
|
|
|
34
|
else { return undef; } |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=head2 province |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
This checks if the input is a two letter Canadian province |
499
|
|
|
|
|
|
|
abbreviation. |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=cut |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
sub match_province { |
504
|
10
|
|
|
10
|
0
|
627
|
my $val = shift; |
505
|
10
|
100
|
|
|
|
105
|
if ($province =~ /\b($val)\b/i) { |
506
|
4
|
|
|
|
|
29
|
return $1; |
507
|
|
|
|
|
|
|
} |
508
|
6
|
|
|
|
|
33
|
else { return undef; } |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=head2 zip_or_postcode |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
This constraints checks if the input is an American zipcode or a |
514
|
|
|
|
|
|
|
Canadian postal code. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=cut |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
sub match_zip_or_postcode { |
519
|
4
|
|
|
4
|
0
|
630
|
my $match; |
520
|
4
|
100
|
|
|
|
11
|
if ($match = match_zip(@_)) { |
521
|
2
|
|
|
|
|
15
|
return $match; |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
else { |
524
|
2
|
|
|
|
|
9
|
return match_postcode(@_) |
525
|
|
|
|
|
|
|
}; |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
=pod |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=head2 postcode |
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
This constraints checks if the input is a valid Canadian postal code. |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=cut |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
sub match_postcode { |
536
|
6
|
|
|
6
|
0
|
685
|
my $val = shift; |
537
|
|
|
|
|
|
|
#$val =~ s/[_\W]+//g; |
538
|
6
|
100
|
|
|
|
48
|
if ($val =~ /^([ABCEGHJKLMNPRSTVXYabceghjklmnprstvxy][_\W]*\d[_\W]*[A-Za-z][_\W]*[- ]?[_\W]*\d[_\W]*[A-Za-z][_\W]*\d[_\W]*)$/) { |
539
|
2
|
|
|
|
|
14
|
return $1; |
540
|
|
|
|
|
|
|
} |
541
|
4
|
|
|
|
|
25
|
else { return undef; } |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
=head2 zip |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
This input validator checks if the input is a valid american zipcode : |
547
|
|
|
|
|
|
|
5 digits followed by an optional mailbox number. |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=cut |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub match_zip { |
552
|
12
|
|
|
12
|
0
|
610
|
my $val = shift; |
553
|
12
|
100
|
|
|
|
47
|
if ($val =~ /^(\s*\d{5}(?:[-]\d{4})?\s*)$/) { |
554
|
6
|
|
|
|
|
26
|
return $1; |
555
|
|
|
|
|
|
|
} |
556
|
6
|
|
|
|
|
24
|
else { return undef; } |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=head2 phone |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
This one checks if the input looks like a phone number, (if it |
562
|
|
|
|
|
|
|
contains at least 6 digits.) |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
=cut |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
sub match_phone { |
567
|
6
|
|
|
6
|
0
|
611
|
my $val = shift; |
568
|
|
|
|
|
|
|
|
569
|
6
|
100
|
|
|
|
43
|
if ($val =~ /^((?:\D*\d\D*){6,})$/) { |
570
|
4
|
|
|
|
|
22
|
return $1; |
571
|
|
|
|
|
|
|
} |
572
|
2
|
|
|
|
|
14
|
else { return undef; } |
573
|
|
|
|
|
|
|
} |
574
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
=head2 american_phone |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
This constraints checks if the number is a possible North American style |
578
|
|
|
|
|
|
|
of phone number : (XXX) XXX-XXXX. It has to contains 7 or more digits. |
579
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
=cut |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
sub match_american_phone { |
583
|
5
|
|
|
5
|
0
|
852
|
my $val = shift; |
584
|
|
|
|
|
|
|
|
585
|
5
|
100
|
|
|
|
30
|
if ($val =~ /^((?:\D*\d\D*){7,})$/) { |
586
|
2
|
|
|
|
|
14
|
return $1; |
587
|
|
|
|
|
|
|
} |
588
|
3
|
|
|
|
|
43
|
else { return undef; } |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=head2 cc_number |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
This constraint references the value of a credit card type field. |
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
constraint_methods => { |
597
|
|
|
|
|
|
|
cc_no => cc_number({fields => ['cc_type']}), |
598
|
|
|
|
|
|
|
} |
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
The number is checked only for plausibility, it checks if the number could |
602
|
|
|
|
|
|
|
be valid for a type of card by checking the checksum and looking at the number |
603
|
|
|
|
|
|
|
of digits and the number of digits of the number. |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
This functions is only good at catching typos. IT DOESN'T |
606
|
|
|
|
|
|
|
CHECK IF THERE IS AN ACCOUNT ASSOCIATED WITH THE NUMBER. |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=cut |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
# This one is taken from the contributed program to |
611
|
|
|
|
|
|
|
# MiniVend by Bruce Albrecht |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
# XXX raise exception on bad/missing params? |
614
|
|
|
|
|
|
|
sub cc_number { |
615
|
1
|
|
|
1
|
1
|
367
|
my $attrs = shift; |
616
|
|
|
|
|
|
|
return undef unless $attrs && ref($attrs) eq 'HASH' |
617
|
1
|
50
|
33
|
|
|
13
|
&& exists $attrs->{fields} && ref($attrs->{fields}) eq 'ARRAY'; |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
618
|
|
|
|
|
|
|
|
619
|
1
|
|
|
|
|
1
|
my ($cc_type_field) = @{ $attrs->{fields} }; |
|
1
|
|
|
|
|
2
|
|
620
|
1
|
50
|
|
|
|
3
|
return undef unless $cc_type_field; |
621
|
|
|
|
|
|
|
|
622
|
|
|
|
|
|
|
return sub { |
623
|
12
|
|
|
12
|
|
9
|
my $dfv = shift; |
624
|
12
|
|
|
|
|
23
|
my $data = $dfv->get_filtered_data; |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
return match_cc_number( |
627
|
|
|
|
|
|
|
$dfv->get_current_constraint_value, |
628
|
12
|
|
|
|
|
19
|
$data->{$cc_type_field} |
629
|
|
|
|
|
|
|
); |
630
|
1
|
|
|
|
|
7
|
}; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
sub match_cc_number { |
634
|
28
|
|
|
28
|
0
|
925
|
my ( $the_card, $card_type ) = @_; |
635
|
28
|
|
|
|
|
33
|
my $orig_card = $the_card; #used for return match at bottom |
636
|
28
|
|
|
|
|
18
|
my ($index, $digit, $product); |
637
|
28
|
|
|
|
|
20
|
my $multiplier = 2; # multiplier is either 1 or 2 |
638
|
28
|
|
|
|
|
28
|
my $the_sum = 0; |
639
|
|
|
|
|
|
|
|
640
|
28
|
50
|
|
|
|
43
|
return undef if length($the_card) == 0; |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
# check card type |
643
|
28
|
50
|
|
|
|
65
|
return undef unless $card_type =~ /^[admv]/i; |
644
|
|
|
|
|
|
|
|
645
|
28
|
100
|
66
|
|
|
314
|
return undef if ($card_type =~ /^v/i && substr($the_card, 0, 1) ne "4") || |
|
|
|
100
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
646
|
|
|
|
|
|
|
($card_type =~ /^m/i && substr($the_card, 0, 1) ne "5") || |
647
|
|
|
|
|
|
|
($card_type =~ /^d/i && substr($the_card, 0, 4) ne "6011") || |
648
|
|
|
|
|
|
|
($card_type =~ /^a/i && substr($the_card, 0, 2) ne "34" && |
649
|
|
|
|
|
|
|
substr($the_card, 0, 2) ne "37"); |
650
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
# check for valid number of digits. |
652
|
24
|
|
|
|
|
35
|
$the_card =~ s/\s//g; # strip out spaces |
653
|
24
|
50
|
|
|
|
65
|
return undef if $the_card !~ /^\d+$/; |
654
|
|
|
|
|
|
|
|
655
|
24
|
|
|
|
|
28
|
$digit = substr($the_card, 0, 1); |
656
|
24
|
|
|
|
|
24
|
$index = length($the_card)-1; |
657
|
24
|
50
|
66
|
|
|
218
|
return undef if ($digit == 3 && $index != 14) || |
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
658
|
|
|
|
|
|
|
($digit == 4 && $index != 12 && $index != 15) || |
659
|
|
|
|
|
|
|
($digit == 5 && $index != 15) || |
660
|
|
|
|
|
|
|
($digit == 6 && $index != 13 && $index != 15); |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
# calculate checksum. |
664
|
24
|
|
|
|
|
47
|
for ($index--; $index >= 0; $index --) |
665
|
|
|
|
|
|
|
{ |
666
|
354
|
|
|
|
|
245
|
$digit=substr($the_card, $index, 1); |
667
|
354
|
|
|
|
|
232
|
$product = $multiplier * $digit; |
668
|
354
|
100
|
|
|
|
309
|
$the_sum += $product > 9 ? $product - 9 : $product; |
669
|
354
|
|
|
|
|
424
|
$multiplier = 3 - $multiplier; |
670
|
|
|
|
|
|
|
} |
671
|
24
|
|
|
|
|
29
|
$the_sum %= 10; |
672
|
24
|
100
|
|
|
|
33
|
$the_sum = 10 - $the_sum if $the_sum; |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
# return whether checksum matched. |
675
|
24
|
100
|
|
|
|
37
|
if ($the_sum == substr($the_card, -1)) { |
676
|
18
|
50
|
|
|
|
49
|
if ($orig_card =~ /^([\d\s]*)$/) { return $1; } |
|
18
|
|
|
|
|
81
|
|
677
|
0
|
|
|
|
|
0
|
else { return undef; } |
678
|
|
|
|
|
|
|
} |
679
|
|
|
|
|
|
|
else { |
680
|
6
|
|
|
|
|
19
|
return undef; |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
} |
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
=head2 cc_exp |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
This one checks if the input is in the format MM/YY or MM/YYYY and if |
687
|
|
|
|
|
|
|
the MM part is a valid month (1-12) and if that date is not in the past. |
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
=cut |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
sub match_cc_exp { |
692
|
4
|
|
|
4
|
0
|
619
|
my $val = shift; |
693
|
4
|
|
|
|
|
5
|
my ($matched_month, $matched_year); |
694
|
|
|
|
|
|
|
|
695
|
4
|
|
|
|
|
11
|
my ($month, $year) = split('/', $val); |
696
|
4
|
100
|
|
|
|
30
|
return undef if $month !~ /^(\d+)$/; |
697
|
2
|
|
|
|
|
5
|
$matched_month = $1; |
698
|
|
|
|
|
|
|
|
699
|
2
|
50
|
|
|
|
9
|
return undef if $year !~ /^(\d+)$/; |
700
|
2
|
|
|
|
|
4
|
$matched_year = $1; |
701
|
|
|
|
|
|
|
|
702
|
2
|
50
|
33
|
|
|
16
|
return undef if $month <1 || $month > 12; |
703
|
2
|
50
|
|
|
|
9
|
$year += ($year < 70) ? 2000 : 1900 if $year < 1900; |
|
|
50
|
|
|
|
|
|
704
|
2
|
|
|
|
|
44
|
my @now=localtime(); |
705
|
2
|
|
|
|
|
5
|
$now[5] += 1900; |
706
|
2
|
50
|
33
|
|
|
14
|
return undef if ($year < $now[5]) || ($year == $now[5] && $month <= $now[4]); |
|
|
|
33
|
|
|
|
|
707
|
|
|
|
|
|
|
|
708
|
2
|
|
|
|
|
22
|
return "$matched_month/$matched_year"; |
709
|
|
|
|
|
|
|
} |
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
=head2 cc_type |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
This one checks if the input field starts by M(asterCard), V(isa), |
714
|
|
|
|
|
|
|
A(merican express) or D(iscovery). |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
=cut |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
sub match_cc_type { |
719
|
4
|
|
|
4
|
0
|
604
|
my $val = shift; |
720
|
4
|
100
|
|
|
|
17
|
if ($val =~ /^([MVAD].*)$/i) { return $1; } |
|
2
|
|
|
|
|
16
|
|
721
|
2
|
|
|
|
|
14
|
else { return undef; } |
722
|
|
|
|
|
|
|
} |
723
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
=head2 ip_address |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
This checks if the input is formatted like a dotted decimal IP address (v4). |
727
|
|
|
|
|
|
|
For other kinds of IP address method, See L which provides |
728
|
|
|
|
|
|
|
several more options. L explains how we easily integrate |
729
|
|
|
|
|
|
|
with Regexp::Common. |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
=cut |
732
|
|
|
|
|
|
|
|
733
|
|
|
|
|
|
|
# contributed by Juan Jose Natera Abreu |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
sub match_ip_address { |
736
|
6
|
|
|
6
|
0
|
617
|
my $val = shift; |
737
|
6
|
100
|
|
|
|
26
|
if ($val =~ m/^((\d+)\.(\d+)\.(\d+)\.(\d+))$/) { |
738
|
4
|
100
|
66
|
|
|
94
|
if |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
739
|
|
|
|
|
|
|
(($2 >= 0 && $2 <= 255) && ($3 >= 0 && $3 <= 255) && ($4 >= 0 && $4 <= 255) && ($5 >= 0 && $5 <= 255)) { |
740
|
3
|
|
|
|
|
23
|
return $1; |
741
|
|
|
|
|
|
|
} |
742
|
1
|
|
|
|
|
3
|
else { return undef; } |
743
|
|
|
|
|
|
|
} |
744
|
2
|
|
|
|
|
12
|
else { return undef; } |
745
|
|
|
|
|
|
|
} |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
1; |
749
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
__END__ |