line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Data::CGIForm; |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# $Id: CGIForm.pm 2 2010-06-25 14:41:40Z twilde $ |
4
|
|
|
|
|
|
|
# |
5
|
12
|
|
|
12
|
|
339660
|
use 5.006; |
|
12
|
|
|
|
|
47
|
|
|
12
|
|
|
|
|
494
|
|
6
|
12
|
|
|
12
|
|
62
|
use strict; |
|
12
|
|
|
|
|
28
|
|
|
12
|
|
|
|
|
434
|
|
7
|
12
|
|
|
12
|
|
61
|
use warnings; |
|
12
|
|
|
|
|
26
|
|
|
12
|
|
|
|
|
461
|
|
8
|
12
|
|
|
12
|
|
67
|
use Carp (); |
|
12
|
|
|
|
|
22
|
|
|
12
|
|
|
|
|
48371
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $VERSION = 0.5; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Data::CGIForm - Form Data Interface. |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 DESCRIPTION |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Data::CGIForm is yet another way to parse and handle CGI form data. |
19
|
|
|
|
|
|
|
The main motivation behind this module was a simple specification |
20
|
|
|
|
|
|
|
based validator that could handle multiple values. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
You probably don't want to use this module. L |
23
|
|
|
|
|
|
|
is a much more feature complete take on getting this sort of work done. |
24
|
|
|
|
|
|
|
You may then ask why this is on the CPAN, I ask that of myself from time to |
25
|
|
|
|
|
|
|
time.... |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 SYNOPSIS |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
my %spec = ( |
30
|
|
|
|
|
|
|
username => qr/^([a-z0-9]+)$/, |
31
|
|
|
|
|
|
|
password => { |
32
|
|
|
|
|
|
|
regexp => qr/^([a-z0-9+])$/, |
33
|
|
|
|
|
|
|
filter => [qw(strip_leading_ws, strip_trailing_ws)], |
34
|
|
|
|
|
|
|
}, |
35
|
|
|
|
|
|
|
email => { |
36
|
|
|
|
|
|
|
regexp => qr/^([a-z0-9@.]+)$/, |
37
|
|
|
|
|
|
|
filter => \&qualify_domain, |
38
|
|
|
|
|
|
|
optional => 1, |
39
|
|
|
|
|
|
|
errors => { |
40
|
|
|
|
|
|
|
empty => 'You didn\'t enter an email address.', |
41
|
|
|
|
|
|
|
invalid => 'Bad [% key %]: "[% value %]"', |
42
|
|
|
|
|
|
|
}, |
43
|
|
|
|
|
|
|
extra_test => \&check_email_addr, |
44
|
|
|
|
|
|
|
}, |
45
|
|
|
|
|
|
|
email2 => { |
46
|
|
|
|
|
|
|
equal_to => email, |
47
|
|
|
|
|
|
|
errors => { |
48
|
|
|
|
|
|
|
unequal => 'Both email addresses must be the same.', |
49
|
|
|
|
|
|
|
}, |
50
|
|
|
|
|
|
|
}, |
51
|
|
|
|
|
|
|
); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
my $r = $ENV{'MOD_PERL'} ? Apache::Request->instance : CGI->new; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my $form = Data::CGIForm->new(datasource => $r, spec => \%spec); |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
my @params = $form->params; |
59
|
|
|
|
|
|
|
foreach $param (@params) { |
60
|
|
|
|
|
|
|
next unless my $error_string = $form->error($param); |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
print STDERR $error_string; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
if ($form->error('username')) { |
66
|
|
|
|
|
|
|
handle_error($form->username, $form->error('username')); |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
my $email = $form->param('email'); |
70
|
|
|
|
|
|
|
my $password = $form->password; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 Building the Spec |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
The spec is a hashref describing the format of the data expected, and the |
75
|
|
|
|
|
|
|
rules that that data must match. The keys for this hash are the parameters |
76
|
|
|
|
|
|
|
that you are expecting. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
In the most simple use, the value for a key can simply be a regular expression |
79
|
|
|
|
|
|
|
object. For example: |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
%spec = ( |
82
|
|
|
|
|
|
|
key => qr/.../, |
83
|
|
|
|
|
|
|
); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
For the more complex options, a key should point to a hashref containing the |
86
|
|
|
|
|
|
|
options for that key. The following keys are supported in the hashref: |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=over 4 |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=item equal_to |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
This is simply a bit of syntaxtic sugar. It makes this: |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
email2 => { |
95
|
|
|
|
|
|
|
equal_to => email, |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
The same as: |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
email2 => { |
101
|
|
|
|
|
|
|
regexp => qr/^(.*)$/, |
102
|
|
|
|
|
|
|
extra_test => sub { |
103
|
|
|
|
|
|
|
my ($textref, $form) = @_; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
return unless my $value = $form->param('email'); |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
if ($$textref eq $value) { |
108
|
|
|
|
|
|
|
return 1; |
109
|
|
|
|
|
|
|
} else { |
110
|
|
|
|
|
|
|
$form->param( email => ''); |
111
|
|
|
|
|
|
|
$form->param( email2 => ''); |
112
|
|
|
|
|
|
|
$self->errorf(email2 => unequal => $$textref); |
113
|
|
|
|
|
|
|
$self->error( email => $self->error('email2')); |
114
|
|
|
|
|
|
|
return 0; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
}, |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
C does not work properly with multiple values. This is a feature. |
120
|
|
|
|
|
|
|
Also, do not use C with a key more than once. The dragons may |
121
|
|
|
|
|
|
|
come looking for you if you do, and you taste good with ketchup. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=item regexp |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
The regular expression that the data must match. |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=item length |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
The I length that the input must be. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
B Length is tested after filtering, but before any extra_test is run. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item min_length |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
The minimum length that the input may be. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item max_length |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
The maximum length that the input may be. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item filter |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
The filter (or filters; to have more than one use an array ref) that the data |
144
|
|
|
|
|
|
|
must be passed though before it is validated. See the 'Filters' section |
145
|
|
|
|
|
|
|
below. |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=item optional |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
boolean. If true then the parameter is optioinal. Note that if the parameter |
150
|
|
|
|
|
|
|
is given, then it is still validated. It can still be marked as an error if |
151
|
|
|
|
|
|
|
parameter is given. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=item errors |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
A hashref to the error strings for this parameter. See the Error Strings |
156
|
|
|
|
|
|
|
section below. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item extra_test |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
A codefef (or arrayref of coderefs) of boolean functions that will be used |
161
|
|
|
|
|
|
|
in the validation process. See the Extra Test section below. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=back |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=head2 Filters |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
These functions are used to filter the data before that data is validated. In |
168
|
|
|
|
|
|
|
the spec they can be listed as a single filter, or an arrayref of many filters. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
There filters are built in, and can be specified by name: |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=over 4 |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=item strip_leading_ws |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
Removes any leading white space from the data. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=item strip_trailing_ws |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
Removes any trailing white space from the data. |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item strip_ws |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Removes any white space from the data. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=item lc |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Converts the data to lowercase. |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=item uc |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Converts the data to uppercase. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=back |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
If you with you use your own filter, then list it as a coderef in the spec. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Filters are passed 1 parameter. $_[0] is a scalar ref to the current data |
199
|
|
|
|
|
|
|
being filtered. For example: |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub fix_newlines { |
202
|
|
|
|
|
|
|
my $textref = shift; |
203
|
|
|
|
|
|
|
$$textref =~ s/[\n\r]*/\n/sg; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=cut |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
our %Filters = ( |
209
|
|
|
|
|
|
|
strip_leading_ws => sub { ${$_[0]} =~ s/^\s*// }, |
210
|
|
|
|
|
|
|
strip_trailing_ws => sub { ${$_[0]} =~ s/\s*$// }, |
211
|
|
|
|
|
|
|
strip_ws => sub { ${$_[0]} =~ s/\s*//g }, |
212
|
|
|
|
|
|
|
lc => sub { ${$_[0]} = lc ${$_[0]} }, |
213
|
|
|
|
|
|
|
uc => sub { ${$_[0]} = uc ${$_[0]} }, |
214
|
|
|
|
|
|
|
); |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=head2 Error Strings |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
For each key in the spec, you can specify different error messagses for |
219
|
|
|
|
|
|
|
different situations. For example: |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
%spec = ( |
222
|
|
|
|
|
|
|
field => { |
223
|
|
|
|
|
|
|
errors => { |
224
|
|
|
|
|
|
|
empty => "You didn't fill this out!" |
225
|
|
|
|
|
|
|
invalid => "That doesn't look right!" |
226
|
|
|
|
|
|
|
}, |
227
|
|
|
|
|
|
|
... |
228
|
|
|
|
|
|
|
}, |
229
|
|
|
|
|
|
|
); |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Currently, there are four error types. C is used when |
232
|
|
|
|
|
|
|
the data does not match the validation specification, while |
233
|
|
|
|
|
|
|
C is used when no data was given and the field is not optional. |
234
|
|
|
|
|
|
|
C is used when an equal_to pair does not match. C is used |
235
|
|
|
|
|
|
|
when a length, min_length, or max_length parameter is violated. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Two tags are filled in when the error messages are set: |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
[% key %] == Becomes ==> The current keyname. |
240
|
|
|
|
|
|
|
[% value %] == Becomes ==> The value for the current key. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
For example |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
errors => { |
245
|
|
|
|
|
|
|
invalid => "[% value %] doesn't look like a [% key %]", |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
If a type isn't given, then a default message is used. |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=cut |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
our %DefaultErrors = ( |
253
|
|
|
|
|
|
|
invalid => 'The input for [% key %] ("[% value %]") is invalid.', |
254
|
|
|
|
|
|
|
empty => '"[% key %]" not given.', |
255
|
|
|
|
|
|
|
unequal => 'The two fields must match.', |
256
|
|
|
|
|
|
|
length => 'The input for [% key %} ("[% value %]") does not meet length constraints.', |
257
|
|
|
|
|
|
|
); |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
our @ValidErrorFields = qw(invalid empty unequal length); |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head2 Extra Test |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
Extra tests give the programmer a hook into the validation process. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
Extra tests are declared in a similar fasion in the spec to filters, |
266
|
|
|
|
|
|
|
with the exception that everything is a coderef. There are no built |
267
|
|
|
|
|
|
|
in extra tests. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Extra tests functions are passed 3 paramters: |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
$_[0] is a scalar refernce to the data being tested: |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub is_right_size { |
274
|
|
|
|
|
|
|
return (${$_[0]} > 100 and ${$_[0]} < 1250); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
$_[1] is the current Data::CGIForm object. $_[2] is the key name for the |
278
|
|
|
|
|
|
|
data being filtered. For example: |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub check_email { |
281
|
|
|
|
|
|
|
my ($textref, $form, $key) = @_; |
282
|
|
|
|
|
|
|
unless (Email::Valid->address($$textref)) { |
283
|
|
|
|
|
|
|
$form->error( |
284
|
|
|
|
|
|
|
$key => "address failed $Email::Valid::Details check." |
285
|
|
|
|
|
|
|
); |
286
|
|
|
|
|
|
|
return; |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
return 1; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
Note that just setting the error string does not clear the parameter. You |
292
|
|
|
|
|
|
|
may want to do this yourself to keep with the built in behavior: |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub check_email { |
295
|
|
|
|
|
|
|
my ($textref, $form, $key) = @_; |
296
|
|
|
|
|
|
|
unless (Email::Valid->address($$textref)) { |
297
|
|
|
|
|
|
|
$form->param($key => ''); |
298
|
|
|
|
|
|
|
$form->error( |
299
|
|
|
|
|
|
|
$key => "address failed $Email::Valid::Details check." |
300
|
|
|
|
|
|
|
); |
301
|
|
|
|
|
|
|
return; |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
return 1; |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head1 METHODS |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head2 Data::CGIForm->new() |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Creates the Data::CGIForm object. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
This should be called in the following matter: |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
Data::CGIForm->new(datasource => $r, spec => \%spec, %options) |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
C should be something that has a C method, like a L |
317
|
|
|
|
|
|
|
object, or a L object. C<%spec> is explained in the specification |
318
|
|
|
|
|
|
|
docs above. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
The following options are supported: |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=over 4 |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=item start_param |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
Specifies that a given parameter acts as a switch for validation. If the value from |
327
|
|
|
|
|
|
|
the datasource for this parameter is true, then validation will be skipped and an empty |
328
|
|
|
|
|
|
|
string set as the value for each parameter in the spec. |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=back |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=cut |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub new { |
335
|
23
|
|
|
23
|
1
|
6176
|
my $class = shift; |
336
|
|
|
|
|
|
|
|
337
|
23
|
50
|
|
|
|
108
|
Carp::croak("${class}->new(): Odd number of parameters given.") unless @_ % 2 == 0; |
338
|
|
|
|
|
|
|
|
339
|
23
|
|
|
|
|
110
|
my %params = @_; |
340
|
|
|
|
|
|
|
|
341
|
23
|
|
|
|
|
72
|
for (qw(datasource spec)) { |
342
|
46
|
50
|
|
|
|
227
|
Carp::croak("${class}->new(): $_ not given.") unless $params{$_}; |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
23
|
50
|
33
|
|
|
388
|
unless (ref $params{'datasource'} and $params{'datasource'}->can('param')) { |
346
|
0
|
|
|
|
|
0
|
Carp::croak("${class}->new(): 'datasource' must be an object with a param() method."); |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
23
|
50
|
33
|
|
|
195
|
unless (ref $params{'spec'} and ref $params{'spec'} eq 'HASH') { |
350
|
0
|
|
|
|
|
0
|
Carp::croak("${class}->new(): 'spec' must be a hashref."); |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
|
353
|
23
|
|
|
|
|
104
|
my $self = { |
354
|
|
|
|
|
|
|
spec => {}, |
355
|
|
|
|
|
|
|
data => {}, |
356
|
|
|
|
|
|
|
errors => {}, |
357
|
|
|
|
|
|
|
}; |
358
|
|
|
|
|
|
|
|
359
|
23
|
100
|
|
|
|
77
|
if ($params{'start_param'}) { |
360
|
3
|
100
|
|
|
|
12
|
unless ($params{'spec'}->{$params{'start_param'}}) { |
361
|
1
|
|
|
|
|
215
|
Carp::croak(qq(${class}->new(): 'start_param' ("$params{'start_param'}") not listed in the spec.)); |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
2
|
|
|
|
|
5
|
$self->{'start_param'} = $params{'start_param'}; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
|
368
|
22
|
|
|
|
|
65
|
bless($self, $class); |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# Scan the user spec, and normalize it |
371
|
22
|
|
|
|
|
93
|
$self->_scan_spec($params{'spec'}); |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# pull the data from the datasource |
374
|
22
|
|
|
|
|
691
|
$self->_populate_vars($params{'datasource'}); |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# run the validation spec |
377
|
22
|
100
|
|
|
|
109
|
$self->_validate_params unless $self->{'in_unstarted_mode'}; |
378
|
|
|
|
|
|
|
|
379
|
22
|
|
|
|
|
192
|
return $self; |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# |
383
|
|
|
|
|
|
|
# $form->_scan_spec($spec) |
384
|
|
|
|
|
|
|
# |
385
|
|
|
|
|
|
|
# Runs though the given spec, and normalizes it. |
386
|
|
|
|
|
|
|
# |
387
|
|
|
|
|
|
|
sub _scan_spec { |
388
|
22
|
|
|
22
|
|
51
|
my ($self, $s) = @_; |
389
|
|
|
|
|
|
|
|
390
|
22
|
|
|
|
|
74
|
foreach my $param (keys %$s) { |
391
|
70
|
|
|
|
|
128
|
my $value = $s->{$param}; |
392
|
|
|
|
|
|
|
|
393
|
70
|
50
|
|
|
|
169
|
Carp::croak("new(): spec error: $param is not a ref") unless ref $value; |
394
|
|
|
|
|
|
|
|
395
|
70
|
100
|
|
|
|
188
|
if (ref $value eq 'HASH') { |
|
|
50
|
|
|
|
|
|
396
|
42
|
|
|
|
|
105
|
$self->_insert_spec($param => $value); |
397
|
|
|
|
|
|
|
} elsif (ref $value eq 'Regexp') { |
398
|
28
|
|
|
|
|
105
|
$self->_insert_spec($param => { regexp => $value}); |
399
|
|
|
|
|
|
|
} else { |
400
|
0
|
|
|
|
|
0
|
Carp::croak("new(): spec error: $param is not a hashref or regexp"); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
|
404
|
22
|
100
|
|
|
|
1476
|
$self->_insert_delayed_specs if $self->{'delayed_specs'}; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
# |
408
|
|
|
|
|
|
|
# $form->_insert_spec($key => $spec) |
409
|
|
|
|
|
|
|
# |
410
|
|
|
|
|
|
|
# Does most of the heavy lifting for _scan_spec |
411
|
|
|
|
|
|
|
# |
412
|
|
|
|
|
|
|
sub _insert_spec { |
413
|
72
|
|
|
72
|
|
123
|
my ($self, $key, $old_spec) = @_; |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# |
416
|
|
|
|
|
|
|
# Make a copy just to be safe. |
417
|
|
|
|
|
|
|
# |
418
|
72
|
|
|
|
|
240
|
my $s = { %$old_spec }; |
419
|
|
|
|
|
|
|
|
420
|
72
|
100
|
|
|
|
204
|
if ($s->{'equal_to'}) { |
421
|
|
|
|
|
|
|
# equal_to rules must be inserted last, so |
422
|
|
|
|
|
|
|
# they can see all the other data that has been inserted. |
423
|
2
|
|
|
|
|
30
|
$self->{'delayed_specs'}->{$key} = $s; |
424
|
2
|
|
|
|
|
8
|
return; |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
|
429
|
70
|
|
|
|
|
401
|
my $regexp = delete $s->{'regexp'}; |
430
|
|
|
|
|
|
|
|
431
|
70
|
50
|
|
|
|
168
|
Carp::croak("new(): spec error: no regexp given for '$key'.") |
432
|
|
|
|
|
|
|
unless $regexp; |
433
|
|
|
|
|
|
|
|
434
|
70
|
50
|
33
|
|
|
346
|
Carp::croak("new(): spec error: regexp for '$key' not a regexp.") |
435
|
|
|
|
|
|
|
unless ref $regexp and ref $regexp eq 'Regexp'; |
436
|
|
|
|
|
|
|
|
437
|
70
|
100
|
|
|
|
181
|
my $optional = delete $s->{'optional'} ? 1 : 0; |
438
|
70
|
|
|
|
|
100
|
my $errors = delete $s->{'errors'}; |
439
|
|
|
|
|
|
|
|
440
|
70
|
|
|
|
|
108
|
my $filter = delete $s->{'filter'}; |
441
|
70
|
|
|
|
|
99
|
my $extra_test = delete $s->{'extra_test'}; |
442
|
|
|
|
|
|
|
|
443
|
70
|
|
|
|
|
99
|
my $length = delete $s->{'length'}; |
444
|
70
|
|
|
|
|
88
|
my $min_length = delete $s->{'min_length'}; |
445
|
70
|
|
|
|
|
103
|
my $max_length = delete $s->{'max_length'}; |
446
|
|
|
|
|
|
|
|
447
|
70
|
50
|
|
|
|
81
|
if (%{$s}) { |
|
70
|
|
|
|
|
170
|
|
448
|
0
|
|
|
|
|
0
|
Carp::croak("new(): spec error: invalid options for $key: @{[ keys %{$s} ]}"); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
70
|
|
|
|
|
213
|
my %spec = ( |
452
|
|
|
|
|
|
|
optional => $optional, |
453
|
|
|
|
|
|
|
regexp => $regexp, |
454
|
|
|
|
|
|
|
); |
455
|
|
|
|
|
|
|
|
456
|
70
|
100
|
|
|
|
139
|
$spec{'length'} = $length if $length; |
457
|
70
|
100
|
|
|
|
150
|
$spec{'min_length'} = $min_length if $min_length; |
458
|
70
|
100
|
|
|
|
137
|
$spec{'max_length'} = $max_length if $max_length; |
459
|
|
|
|
|
|
|
|
460
|
70
|
100
|
|
|
|
311
|
if ($filter) { |
461
|
14
|
100
|
100
|
|
|
83
|
my @filters = (ref $filter and ref $filter eq 'ARRAY') ? @{$filter} : ($filter); |
|
4
|
|
|
|
|
612
|
|
462
|
|
|
|
|
|
|
|
463
|
14
|
|
|
|
|
576
|
foreach my $f (@filters) { |
464
|
17
|
100
|
33
|
|
|
74
|
if ($Filters{$f}) { |
|
|
50
|
|
|
|
|
|
465
|
11
|
|
|
|
|
12
|
push(@{$spec{'filter'}}, $Filters{$f}); |
|
11
|
|
|
|
|
54
|
|
466
|
|
|
|
|
|
|
} elsif (ref $f and ref $f eq 'CODE') { |
467
|
6
|
|
|
|
|
9
|
push(@{$spec{'filter'}}, $f); |
|
6
|
|
|
|
|
23
|
|
468
|
|
|
|
|
|
|
} else { |
469
|
0
|
|
|
|
|
0
|
Carp::croak("new(): spec error: No such built in filter: $f"); |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
70
|
100
|
|
|
|
224
|
if ($extra_test) { |
475
|
7
|
100
|
66
|
|
|
44
|
my @tests = (ref $extra_test and ref $extra_test eq 'ARRAY') ? @{$extra_test} : ($extra_test); |
|
1
|
|
|
|
|
3
|
|
476
|
|
|
|
|
|
|
|
477
|
7
|
|
|
|
|
580
|
foreach my $t (@tests) { |
478
|
8
|
50
|
33
|
|
|
43
|
if (ref $t and ref $t eq 'CODE') { |
479
|
8
|
|
|
|
|
24
|
push(@{$spec{'extra_test'}}, $t); |
|
8
|
|
|
|
|
41
|
|
480
|
|
|
|
|
|
|
} else { |
481
|
0
|
|
|
|
|
0
|
Carp::croak('new(): spec error: extra tests must be a code reference.'); |
482
|
|
|
|
|
|
|
} |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
70
|
100
|
|
|
|
755
|
if ($errors) { |
487
|
|
|
|
|
|
|
# |
488
|
|
|
|
|
|
|
# Make a copy just to be safe. (we use delete here too) |
489
|
|
|
|
|
|
|
# |
490
|
14
|
|
|
|
|
48
|
$errors = { %$errors }; |
491
|
|
|
|
|
|
|
|
492
|
14
|
50
|
33
|
|
|
78
|
unless (ref $errors and ref $errors eq 'HASH') { |
493
|
0
|
|
|
|
|
0
|
Carp::croak('new(): spec error: errors not a hashref'); |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
14
|
|
|
|
|
94
|
my %errors = (); |
497
|
|
|
|
|
|
|
|
498
|
14
|
|
|
|
|
34
|
foreach my $type (@ValidErrorFields) { |
499
|
56
|
|
100
|
|
|
1312
|
my $msg = delete $errors->{$type} || next; |
500
|
25
|
|
|
|
|
50
|
$errors{$type} = $msg; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
14
|
50
|
|
|
|
16
|
if (%{$errors}) { |
|
14
|
|
|
|
|
46
|
|
504
|
0
|
|
|
|
|
0
|
Carp::croak("new(): spec error: invalid error message types: @{[ keys %{$errors} ]}"); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
14
|
|
|
|
|
35
|
$spec{'errors'} = \%errors; |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
70
|
|
|
|
|
1015
|
$self->{'spec'}->{$key} = \%spec; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
sub _insert_delayed_specs { |
515
|
2
|
|
|
2
|
|
5
|
my ($self) = @_; |
516
|
|
|
|
|
|
|
|
517
|
2
|
|
|
|
|
3
|
while (my ($key, $s) = each %{$self->{'delayed_specs'}}) { |
|
4
|
|
|
|
|
19
|
|
518
|
2
|
|
33
|
|
|
9
|
my $equal_to = delete $s->{'equal_to'} || Carp::confess("How did we get a delayed spec with no equal_to?!"); |
519
|
|
|
|
|
|
|
|
520
|
2
|
50
|
|
|
|
8
|
unless ($self->{'spec'}->{$equal_to}) { |
521
|
0
|
|
|
|
|
0
|
Carp::croak("new(): spec error: equal_to set to unknown parameter: $equal_to."); |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
2
|
|
|
|
|
10
|
$s->{'regexp'} = qr/^(.*)$/; |
525
|
|
|
|
|
|
|
$s->{'extra_test'} = sub { |
526
|
2
|
|
|
2
|
|
4
|
my ($textref, $form) = @_; |
527
|
|
|
|
|
|
|
|
528
|
2
|
50
|
|
|
|
6
|
return unless my $value = $form->param($equal_to); |
529
|
|
|
|
|
|
|
|
530
|
2
|
100
|
|
|
|
7
|
if ($$textref eq $value) { |
531
|
1
|
|
|
|
|
4
|
return 1; |
532
|
|
|
|
|
|
|
} else { |
533
|
1
|
|
|
|
|
3
|
$form->param( $equal_to => ''); |
534
|
1
|
|
|
|
|
2
|
$form->param( $key => ''); |
535
|
|
|
|
|
|
|
|
536
|
1
|
|
|
|
|
4
|
$self->errorf($key => unequal => $$textref); |
537
|
1
|
|
|
|
|
3
|
$self->error( $equal_to => $self->error($key)); |
538
|
|
|
|
|
|
|
|
539
|
1
|
|
|
|
|
3
|
return 0; |
540
|
|
|
|
|
|
|
} |
541
|
2
|
|
|
|
|
27
|
}; |
542
|
|
|
|
|
|
|
|
543
|
2
|
|
|
|
|
5
|
$self->_insert_spec($key, $s); |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
# |
548
|
|
|
|
|
|
|
# $form->_populate_vars($datasource) |
549
|
|
|
|
|
|
|
# |
550
|
|
|
|
|
|
|
# Goes though the spec, grabbing data from the datasource for each var. |
551
|
|
|
|
|
|
|
# |
552
|
|
|
|
|
|
|
sub _populate_vars { |
553
|
22
|
|
|
22
|
|
41
|
my ($self, $data) = @_; |
554
|
|
|
|
|
|
|
|
555
|
22
|
100
|
100
|
|
|
85
|
$self->{'in_unstarted_mode'} = 1 if $self->{'start_param'} |
556
|
|
|
|
|
|
|
and !$data->param($self->{'start_param'}); |
557
|
|
|
|
|
|
|
|
558
|
22
|
100
|
|
|
|
78
|
if ($self->{'in_unstarted_mode'}) { |
559
|
1
|
|
|
|
|
2
|
foreach my $key (keys %{$self->{'spec'}}) { |
|
1
|
|
|
|
|
4
|
|
560
|
4
|
|
|
|
|
12
|
$self->{'data'}->{$key} = ['']; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
} else { |
563
|
21
|
|
|
|
|
39
|
foreach my $key (keys %{$self->{'spec'}}) { |
|
21
|
|
|
|
|
78
|
|
564
|
66
|
|
|
|
|
193
|
@{$self->{'data'}->{$key}} = $data->param($key); |
|
66
|
|
|
|
|
586
|
|
565
|
|
|
|
|
|
|
} |
566
|
|
|
|
|
|
|
} |
567
|
|
|
|
|
|
|
} |
568
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
# |
571
|
|
|
|
|
|
|
# $form->_validate_params |
572
|
|
|
|
|
|
|
# |
573
|
|
|
|
|
|
|
# Runs though the spec, validating the data we got from the datastore. |
574
|
|
|
|
|
|
|
# If the data is bad, we drop it to the floor, and set an error message. |
575
|
|
|
|
|
|
|
# |
576
|
|
|
|
|
|
|
sub _validate_params { |
577
|
21
|
|
|
21
|
|
37
|
my ($self) = @_; |
578
|
|
|
|
|
|
|
|
579
|
21
|
|
|
|
|
37
|
KEY: while (my ($key, $spec) = each %{$self->{'spec'}}) { |
|
87
|
|
|
|
|
310
|
|
580
|
|
|
|
|
|
|
|
581
|
66
|
|
|
|
|
73
|
my @new_data; |
582
|
|
|
|
|
|
|
|
583
|
66
|
100
|
|
|
|
69
|
unless (@{$self->{'data'}->{$key}}) { |
|
66
|
|
|
|
|
176
|
|
584
|
16
|
100
|
66
|
|
|
46
|
$self->errorf($key => 'empty', $_) unless $self->error($key) || $spec->{'optional'}; |
585
|
16
|
|
|
|
|
37
|
next KEY; |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
|
589
|
50
|
|
|
|
|
68
|
MEMBER: for (@{$self->{'data'}->{$key}}) { |
|
50
|
|
|
|
|
112
|
|
590
|
76
|
100
|
66
|
|
|
423
|
next MEMBER if defined $_ and length $_; |
591
|
|
|
|
|
|
|
|
592
|
1
|
50
|
33
|
|
|
4
|
$self->errorf($key => 'empty', $_) unless $self->error($key) || $spec->{'optional'}; |
593
|
1
|
|
|
|
|
2
|
next KEY; |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
49
|
|
|
|
|
72
|
DATA: foreach my $data (@{$self->{'data'}->{$key}}) { |
|
49
|
|
|
|
|
110
|
|
597
|
|
|
|
|
|
|
|
598
|
75
|
50
|
|
|
|
134
|
next DATA unless defined $data; |
599
|
|
|
|
|
|
|
|
600
|
75
|
100
|
|
|
|
155
|
if ($spec->{'filter'}) { |
601
|
19
|
|
|
|
|
16
|
$_->(\$data) for @{$spec->{'filter'}}; |
|
19
|
|
|
|
|
51
|
|
602
|
|
|
|
|
|
|
} |
603
|
|
|
|
|
|
|
|
604
|
75
|
100
|
|
|
|
463
|
unless ($data =~ $spec->{'regexp'}) { |
605
|
10
|
|
|
|
|
26
|
$self->errorf($key => 'invalid' => $data); |
606
|
|
|
|
|
|
|
} else { |
607
|
65
|
|
|
|
|
147
|
$data = $1; |
608
|
|
|
|
|
|
|
|
609
|
65
|
100
|
|
|
|
145
|
if (exists $spec->{'length'}) { |
610
|
3
|
50
|
|
|
|
8
|
$self->errorf($key => 'length', $data), next DATA |
611
|
|
|
|
|
|
|
unless length($data) == $spec->{'length'}; |
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
65
|
100
|
|
|
|
165
|
if (exists $spec->{'max_length'}) { |
615
|
3
|
100
|
|
|
|
15
|
$self->errorf($key => 'length', $data), next DATA |
616
|
|
|
|
|
|
|
unless length($data) <= $spec->{'max_length'}; |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
|
619
|
63
|
100
|
|
|
|
122
|
if (exists $spec->{'min_length'}) { |
620
|
3
|
100
|
|
|
|
11
|
$self->errorf($key => 'length', $data), next DATA |
621
|
|
|
|
|
|
|
unless length($data) >= $spec->{'min_length'}; |
622
|
|
|
|
|
|
|
} |
623
|
|
|
|
|
|
|
|
624
|
61
|
100
|
|
|
|
122
|
if ($spec->{'extra_test'}) { |
625
|
7
|
|
|
|
|
9
|
foreach my $t (@{$spec->{'extra_test'}}) { |
|
7
|
|
|
|
|
14
|
|
626
|
8
|
100
|
|
|
|
33
|
unless ($t->(\$data, $self, $key)) { |
627
|
|
|
|
|
|
|
# Don't overide any error message that the test |
628
|
|
|
|
|
|
|
# function set. |
629
|
2
|
100
|
|
|
|
34
|
$self->errorf($key => 'invalid', $data) |
630
|
|
|
|
|
|
|
unless $self->{'errors'}->{$key}; |
631
|
2
|
|
|
|
|
8
|
next DATA; |
632
|
|
|
|
|
|
|
} |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
59
|
|
|
|
|
173
|
push(@new_data, $data); |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
} |
639
|
|
|
|
|
|
|
|
640
|
49
|
100
|
|
|
|
109
|
if (@new_data) { |
641
|
38
|
|
|
|
|
180
|
$self->{'data'}->{$key} = [ @new_data ]; |
642
|
|
|
|
|
|
|
} else { |
643
|
11
|
|
|
|
|
38
|
delete $self->{'data'}->{$key}; |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
} |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
# |
651
|
|
|
|
|
|
|
# clear out the spec of the cruft we don't need anymore... |
652
|
|
|
|
|
|
|
# |
653
|
|
|
|
|
|
|
# XXX -- this is temp to make things work with storable. |
654
|
|
|
|
|
|
|
# |
655
|
21
|
|
|
|
|
35
|
foreach my $param (keys %{$self->{'spec'}}) { |
|
21
|
|
|
|
|
63
|
|
656
|
66
|
|
|
|
|
104
|
delete $self->{'spec'}->{$param}->{'extra_test'}; |
657
|
66
|
|
|
|
|
131
|
delete $self->{'spec'}->{$param}->{'filter'}; |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
=head2 $form->params |
665
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
Returns a list of all the parameters that were in the datasource that |
667
|
|
|
|
|
|
|
are called for in the spec. |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=cut |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
sub params { |
672
|
3
|
|
|
3
|
1
|
717
|
my ($self) = @_; |
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
# Store it in an tmp array to force this into list context. |
675
|
|
|
|
|
|
|
# (sort returns undef in non-list context.) |
676
|
3
|
|
|
|
|
6
|
my @params = sort keys %{$self->{'data'}}; |
|
3
|
|
|
|
|
28
|
|
677
|
|
|
|
|
|
|
|
678
|
3
|
|
|
|
|
17
|
return @params; |
679
|
|
|
|
|
|
|
} |
680
|
|
|
|
|
|
|
|
681
|
|
|
|
|
|
|
=head2 $form->param($name => $new_value) |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
Returns the parameter for a given var. If called in scalar context it returns |
684
|
|
|
|
|
|
|
the first value fetched from the datasource, regardless of the number of values. |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
C<$new_value> should be a scalar or an array ref. |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
If C<$name> is not given then this method returns C<$form-Eparams>, just like |
689
|
|
|
|
|
|
|
CGI or Apache::Request. |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
=cut |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
sub param { |
694
|
71
|
|
|
71
|
1
|
8473
|
my ($self, $name, $new_value) = @_; |
695
|
|
|
|
|
|
|
|
696
|
71
|
100
|
|
|
|
172
|
return $self->params unless $name; |
697
|
|
|
|
|
|
|
|
698
|
69
|
100
|
|
|
|
176
|
if (defined $new_value) { |
699
|
8
|
100
|
|
|
|
16
|
if (ref $new_value) { |
700
|
3
|
100
|
|
|
|
9
|
if (ref $new_value eq 'ARRAY') { |
701
|
2
|
|
|
|
|
7
|
$self->{'data'}->{$name} = $new_value; |
702
|
|
|
|
|
|
|
} else { |
703
|
1
|
|
|
|
|
180
|
Carp::croak("param(): new value is not data or an array reference."); |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
} else { |
706
|
5
|
|
|
|
|
14
|
$self->{'data'}->{$name} = [ $new_value ]; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
|
710
|
68
|
100
|
|
|
|
209
|
return unless my $data = $self->{'data'}->{$name}; |
711
|
|
|
|
|
|
|
|
712
|
61
|
100
|
|
|
|
281
|
return wantarray ? @{$data} : $data->[0]; |
|
18
|
|
|
|
|
143
|
|
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
=head2 $form->error($param_name => $new_error) |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
Returns the error string (if an error occcured) for the a given parameter. |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
If two arguments are passed, this can be used to set the error string. |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
If no parameter is passed, than it returns boolean. True if an error occured |
723
|
|
|
|
|
|
|
in validating the data, false if no error occured. |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
=cut |
726
|
|
|
|
|
|
|
|
727
|
|
|
|
|
|
|
sub error { |
728
|
96
|
|
|
96
|
1
|
11174
|
my ($self, $name, $new_error) = @_; |
729
|
|
|
|
|
|
|
|
730
|
96
|
100
|
|
|
|
188
|
if ($name) { |
731
|
82
|
100
|
|
|
|
195
|
$self->{'errors'}->{$name} = $new_error if $new_error; |
732
|
|
|
|
|
|
|
|
733
|
82
|
|
|
|
|
436
|
return $self->{'errors'}->{$name}; |
734
|
|
|
|
|
|
|
} else { |
735
|
14
|
100
|
|
|
|
19
|
return %{$self->{'errors'}} ? 1 : 0; |
|
14
|
|
|
|
|
92
|
|
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
=head2 $form->errors |
740
|
|
|
|
|
|
|
|
741
|
|
|
|
|
|
|
Returns a hash of all the errors in C error_message> pairs. |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
=cut |
744
|
|
|
|
|
|
|
|
745
|
0
|
|
|
0
|
1
|
0
|
sub errors { return %{$_[0]->{'errors'}}; } |
|
0
|
|
|
|
|
0
|
|
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
=head2 $form->errorf($key, $type, $data) |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
Sets the error for C<$key> to the format type C<$type>, using C<$data> |
752
|
|
|
|
|
|
|
for the C<[% value %]> tag. |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
=cut |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
sub errorf { |
757
|
25
|
|
|
25
|
1
|
50
|
my ($self, $key, $type, $data) = @_; |
758
|
|
|
|
|
|
|
|
759
|
25
|
|
|
|
|
28
|
my $format; |
760
|
|
|
|
|
|
|
|
761
|
25
|
50
|
|
|
|
74
|
unless ($self->{'spec'}->{$key}) { |
762
|
0
|
|
|
|
|
0
|
Carp::croak("errorf(): Invalid key: $key"); |
763
|
|
|
|
|
|
|
} |
764
|
|
|
|
|
|
|
|
765
|
25
|
100
|
|
|
|
61
|
if ($self->{'spec'}->{$key}->{'errors'}) { |
766
|
7
|
|
33
|
|
|
25
|
$format = $self->{'spec'}->{$key}->{'errors'}->{$type} || $DefaultErrors{$type}; |
767
|
|
|
|
|
|
|
} else { |
768
|
18
|
|
|
|
|
40
|
$format = $DefaultErrors{$type}; |
769
|
|
|
|
|
|
|
} |
770
|
|
|
|
|
|
|
|
771
|
25
|
50
|
|
|
|
53
|
Carp::croak("errorf(): Invalid error type: $type") unless $format; |
772
|
|
|
|
|
|
|
|
773
|
25
|
|
|
|
|
89
|
my %map = ( |
774
|
|
|
|
|
|
|
key => $key, |
775
|
|
|
|
|
|
|
value => $data, |
776
|
|
|
|
|
|
|
); |
777
|
|
|
|
|
|
|
|
778
|
25
|
50
|
|
|
|
157
|
$format =~ s{\[%\s*(\w+)\s*%\]}{ $map{$1} || '' }egs; |
|
29
|
|
|
|
|
144
|
|
779
|
|
|
|
|
|
|
|
780
|
25
|
|
|
|
|
68
|
return $self->error($key => $format); |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
=head2 $form->started |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
Returns boolean based on if the start_param was set. True if the form was started, |
786
|
|
|
|
|
|
|
false otherwise. |
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
=cut |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
sub started { |
791
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
792
|
|
|
|
|
|
|
|
793
|
0
|
0
|
|
|
|
0
|
return $self->{'in_unstarted_mode'} ? 0 : 1; |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
|
796
|
|
|
|
|
|
|
=head2 $form->ready |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
Returns boolean; true if the form is started and there are no errors, false |
799
|
|
|
|
|
|
|
other wise. |
800
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
=cut |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
sub ready { |
804
|
0
|
|
0
|
0
|
1
|
0
|
return ($_[0]->started and not $_[0]->error); |
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=head1 AUTOLOAD |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
Data::CGIForm creates uses AUTOLOAD to create methods for the parameters |
811
|
|
|
|
|
|
|
in the spec. These methods just call C<$form-Eparam($name)>, but it might prove |
812
|
|
|
|
|
|
|
helpful/elegent. |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=cut |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
sub AUTOLOAD { |
817
|
28
|
|
|
28
|
|
1132
|
my $self = shift; |
818
|
|
|
|
|
|
|
|
819
|
28
|
|
|
|
|
45
|
our $AUTOLOAD; |
820
|
|
|
|
|
|
|
|
821
|
28
|
50
|
|
|
|
93
|
return if $AUTOLOAD =~ m/DESTROY/; |
822
|
28
|
|
|
|
|
116
|
$AUTOLOAD =~ m/^.*:(.*)$/; |
823
|
|
|
|
|
|
|
|
824
|
28
|
|
50
|
|
|
104
|
my $name = $1 || return; |
825
|
|
|
|
|
|
|
|
826
|
28
|
100
|
|
|
|
120
|
if ($self->{'spec'}->{$name}) { |
827
|
27
|
|
|
|
|
79
|
return $self->param($name, @_); |
828
|
|
|
|
|
|
|
} else { |
829
|
1
|
|
|
|
|
209
|
Carp::croak("Unknown method: $name"); |
830
|
|
|
|
|
|
|
} |
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
=head1 TODO |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
Do we want to test new values given to param() against the spec? |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
Make sure the user hasn't given dangerous equal_to pairs. |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
=head1 AUTHOR |
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
Maintained by: Tim Wilde Etwilde@cymru.comE |
842
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
Originally by: Chris Reinhardt Ecpan@triv.orgE |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
=head1 COPYRIGHT |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
Portions Copyright (c) 2007 Tim Wilde. All rights reserved. |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
Portions Copyright (c) 2006 Dynamic Network Services, Inc. All rights |
850
|
|
|
|
|
|
|
reserved. |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
Portions Copyright (c) 2002 Chris Reinhardt. All rights reserved. This |
853
|
|
|
|
|
|
|
program is free software; you can redistribute it and/or modify it under the |
854
|
|
|
|
|
|
|
same terms as Perl itself. |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
=head1 SEE ALSO |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
L, L. |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
=cut |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
1; |
864
|
|
|
|
|
|
|
__END__ |