File Coverage

blib/lib/Data/FormValidator/Results.pm
Criterion Covered Total %
statement 440 484 90.9
branch 191 248 77.0
condition 79 109 72.4
subroutine 43 45 95.5
pod 0 20 0.0
total 753 906 83.1


line stmt bran cond sub pod time code
1             #
2             # Results.pm - Object which contains validation result.
3             #
4             # This file is part of FormValidator.
5             #
6             # Author: Francis J. Lacoste
7             # Maintainer: Mark Stosberg
8             #
9             # Copyright (C) 2000 iNsu Innovations Inc.
10             #
11             # This program is free software; you can redistribute it and/or modify
12             # it under the terms same terms as perl itself.
13             #
14 64     64   237 use strict;
  64         76  
  64         2014  
15              
16             package Data::FormValidator::Results;
17 63     63   210 use Carp;
  63         68  
  63         3757  
18 63     63   24571 use Symbol;
  63         37734  
  63         3527  
19 63     63   20523 use Data::FormValidator::Filters ':filters';
  63         468  
  63         10662  
20 62     62   25052 use Data::FormValidator::Constraints qw(:validators :matchers);
  62         95  
  62         397  
21             use overload
22 62         441 'bool' => \&_bool_overload_based_on_success,
23 62     62   55046 fallback => 1;
  62         43866  
24              
25             our $VERSION = 4.85;
26              
27             =pod
28              
29             =head1 NAME
30              
31             Data::FormValidator::Results - results of form input validation.
32              
33             =head1 SYNOPSIS
34              
35             my $results = Data::FormValidator->check(\%input_hash, \%dfv_profile);
36              
37             # Print the name of missing fields
38             if ( $results->has_missing ) {
39             for my $f ( $results->missing ) {
40             print $f, " is missing\n";
41             }
42             }
43              
44             # Print the name of invalid fields
45             if ( $results->has_invalid ) {
46             for my $f ( $results->invalid ) {
47             print $f, " is invalid: ", $results->invalid( $f ), "\n";
48             }
49             }
50              
51             # Print unknown fields
52             if ( $results->has_unknown ) {
53             for my $f ( $results->unknown ) {
54             print $f, " is unknown\n";
55             }
56             }
57              
58             # Print valid fields
59             for my $f ( $results->valid() ) {
60             print $f, " = ", $results->valid( $f ), "\n";
61             }
62              
63             =head1 DESCRIPTION
64              
65             This object is returned by the L C method.
66             It can be queried for information about the validation results.
67              
68             =cut
69              
70             sub new {
71 127     127 0 148 my $proto = shift;
72 127   33     515 my $class = ref $proto || $proto;
73 127         166 my ($profile, $data) = @_;
74              
75 127         209 my $self = bless {}, $class;
76              
77 127         285 $self->_process( $profile, $data );
78              
79 122         338 $self;
80             }
81              
82             sub _process {
83 127     127   161 my ($self, $profile, $data) = @_;
84              
85             # Copy data and assumes that all is valid to start with
86              
87 127         306 my %data = $self->_get_input_as_hash($data);
88 127         281 my %valid = %data;
89 127         187 my @missings = ();
90 127         138 my @unknown = ();
91              
92             # msgs() method will need access to the profile
93 127         165 $self->{profile} = $profile;
94              
95 127         123 my %imported_validators;
96              
97             # import valid_* subs from requested packages
98 127         407 for my $package (_arrayify($profile->{validator_packages})) {
99 6 50       13 if ( !exists $imported_validators{$package} ) {
100 6         22 local $SIG{__DIE__} = \&confess;
101 6         295 eval "require $package";
102 6 50       37 if ($@) {
103 0         0 die "Couldn't load validator package '$package': $@";
104             }
105              
106             # Perl will die with a nice error message if the package can't be found
107             # No need to go through extra effort here. -mls :)
108 6         23 my $package_ref = qualify_to_ref("${package}::");
109             my @subs = grep(/^(valid_|match_|filter_)/,
110 6         64 keys(%{*{$package_ref}}));
  6         6  
  6         77  
111 6         14 for my $sub (@subs) {
112             # is it a sub? (i.e. make sure it's not a scalar, hash, etc.)
113 53         423 my $subref = *{qualify_to_ref("${package}::$sub")}{CODE};
  53         84  
114 53 50       306 if (defined $subref) {
115 53         36 *{qualify_to_ref($sub)} = $subref;
  53         60  
116             }
117             }
118 6         92 $imported_validators{$package} = 1;
119             }
120             }
121              
122             # Apply unconditional filters
123 127         365 for my $filter (_arrayify($profile->{filters})) {
124 7 50       18 if (defined $filter) {
125             # Qualify symbolic references
126 7   100     17 $filter = (ref $filter eq 'CODE' ? $filter : *{qualify_to_ref("filter_$filter")}{CODE}) ||
127             die "No filter found named: '$filter'";
128 6         151 for my $field ( keys %valid ) {
129             # apply filter, modifying %valid by reference, skipping undefined values
130 13         30 _filter_apply(\%valid,$field,$filter);
131             }
132             }
133             }
134              
135             # Apply specific filters
136 126         184 while ( my ($field,$filters) = each %{$profile->{field_filters} }) {
  132         548  
137 7         16 for my $filter ( _arrayify($filters)) {
138 7 50       16 if (defined $filter) {
139             # Qualify symbolic references
140 7   100     20 $filter = (ref $filter eq 'CODE' ? $filter : *{qualify_to_ref("filter_$filter")}{CODE}) ||
141             die "No filter found named '$filter'";
142              
143             # apply filter, modifying %valid by reference
144 6         72 _filter_apply(\%valid,$field,$filter);
145             }
146             }
147             }
148              
149             # add in specific filters from the regexp map
150 125         154 while ( my ($re,$filters) = each %{$profile->{field_filter_regexp_map} }) {
  130         421  
151 6         15 my $sub = _create_sub_from_RE($re);
152              
153 6         11 for my $filter ( _arrayify($filters)) {
154 6 50       17 if (defined $filter) {
155             # Qualify symbolic references
156 6   100     16 $filter = (ref $filter eq 'CODE' ? $filter : *{qualify_to_ref("filter_$filter")}{CODE}) ||
157             die "No filter found named '$filter'";
158              
159 59     59   27520 no strict 'refs';
  59         70  
  59         185088  
160              
161             # find all the keys that match this RE and apply filters to them
162 5         111 for my $field (grep { $sub->($_) } (keys %valid)) {
  18         166  
163             # apply filter, modifying %valid by reference
164 7         19 _filter_apply(\%valid,$field,$filter);
165             }
166             }
167             }
168             }
169              
170             # store the filtered data away for later use
171 124         314 $self->{__FILTERED_DATA} = \%valid;
172              
173 124         236 my %required = map { $_ => 1 } _arrayify($profile->{required});
  196         362  
174 124         309 my %optional = map { $_ => 1 } _arrayify($profile->{optional});
  23         41  
175              
176             # loop through and add fields to %required and %optional based on regular expressions
177 124         429 my $required_re = _create_sub_from_RE($profile->{required_regexp});
178 124         309 my $optional_re = _create_sub_from_RE($profile->{optional_regexp});
179              
180 124         328 for my $k (keys %valid) {
181 256 100 100     494 if ($required_re && $required_re->($k)) {
182 1         2 $required{$k} = 1;
183             }
184              
185 256 100 100     669 if ($optional_re && $optional_re->($k)) {
186 6         9 $optional{$k} = 1;
187             }
188             }
189              
190             # handle "require_some"
191 124         178 my %require_some;
192 124         146 while ( my ( $field, $deps) = each %{$profile->{require_some}} ) {
  127         450  
193 3         3 for my $dep (_arrayify($deps)){
194 11         13 $require_some{$dep} = 1;
195             }
196             }
197              
198              
199             # Remove all empty fields
200 124         225 for my $field (keys %valid) {
201 256 100       404 if (ref $valid{$field}) {
202 20 100       55 if ( ref $valid{$field} eq 'ARRAY' ) {
203 18         25 for (my $i = 0; $i < scalar @{ $valid{$field} }; $i++) {
  56         116  
204 38 100 100     243 $valid{$field}->[$i] = undef unless (defined $valid{$field}->[$i] and length $valid{$field}->[$i] and $valid{$field}->[$i] !~ /^\x00$/);
      66        
205             }
206             # If all fields are empty, we delete it.
207 18 100       20 delete $valid{$field} unless grep { defined $_ } @{$valid{$field}};
  38         78  
  18         30  
208              
209             }
210             }
211             else {
212 236 100 100     3893 delete $valid{$field} unless (defined $valid{$field} and length $valid{$field} and $valid{$field} !~ /^\x00$/);
      66        
213             }
214             }
215              
216             # Check if the presence of some fields makes other optional fields required.
217 124         169 while ( my ( $field, $deps) = each %{$profile->{dependencies}} ) {
  139         470  
218 15 100       28 if (defined $valid{$field}) {
219 11 100       26 if (ref($deps) eq 'HASH') {
    100          
220 6         16 for my $key (keys %$deps) {
221             # Handle case of a key with a single value given as an arrayref
222             # There is probably a better, more general solution to this problem.
223 12         10 my $val_to_compare;
224 12 100 66     29 if ((ref $valid{$field} eq 'ARRAY') and (scalar @{ $valid{$field} } == 1)) {
  2         6  
225 2         3 $val_to_compare = $valid{$field}->[0];
226             }
227             else {
228 10         7 $val_to_compare = $valid{$field}
229             }
230              
231 12 100       23 if($val_to_compare eq $key){
232 6         11 for my $dep (_arrayify($deps->{$key})){
233 11         23 $required{$dep} = 1;
234             }
235             }
236             }
237             }
238             elsif (ref $deps eq "CODE") {
239 4         6 for my $val (_arrayify($valid{$field})) {
240 5         10 my $returned_deps = $deps->($self, $val);
241              
242 5         27 for my $dep (_arrayify($returned_deps)) {
243 2         5 $required{$dep} = 1;
244             }
245             }
246             }
247             else {
248 1         2 for my $dep (_arrayify($deps)){
249 2         3 $required{$dep} = 1;
250             }
251             }
252             }
253             }
254              
255             # check dependency groups
256             # the presence of any member makes them all required
257 124         137 for my $group (values %{ $profile->{dependency_groups} }) {
  124         321  
258 0         0 my $require_all = 0;
259 0         0 for my $field (_arrayify($group)) {
260 0 0       0 $require_all = 1 if $valid{$field};
261             }
262 0 0       0 if ($require_all) {
263 0         0 map { $required{$_} = 1 } _arrayify($group);
  0         0  
264             }
265             }
266              
267             # Find unknown
268             @unknown =
269 124   66     210 grep { not (exists $optional{$_} or exists $required{$_} or exists $require_some{$_} ) } keys %valid;
  251         906  
270             # and remove them from the list
271 124         194 for my $field ( @unknown ) {
272 46         64 delete $valid{$field};
273             }
274              
275             # Add defaults from defaults_regexp_map
276 124         129 my %private_defaults;
277 124         224 my @all_possible = keys %optional, keys %required, keys %require_some;
278 124         134 while ( my ($re,$value) = each %{$profile->{defaults_regexp_map}} ) {
  125         398  
279             # We only add defaults for known fields.
280 1         3 for (@all_possible) {
281 3 100       29 $private_defaults{$_} = $value if m/$re/;
282             }
283             }
284              
285             # Fill defaults
286             my %combined_defaults = (
287             %private_defaults,
288 124 100       174 %{ $profile->{defaults} || {} }
  124         568  
289             );
290 124         373 while ( my ($field,$value) = each %combined_defaults ) {
291 3 50       9 unless(exists $valid{$field}) {
292 3 100 66     8 if (ref($value) && ref($value) eq "CODE") {
293 1         3 $valid{$field} = $value->($self);
294             } else {
295 2         6 $valid{$field} = $value;
296             }
297             }
298             }
299              
300             # Check for required fields
301 124         212 for my $field ( keys %required ) {
302 212 100       400 push @missings, $field unless exists $valid{$field};
303             }
304              
305             # Check for the absence of require_some fields
306 124         138 while ( my ( $field, $deps) = each %{$profile->{require_some}} ) {
  127         339  
307 3         2 my $enough_required_fields = 0;
308 3         3 my @deps = _arrayify($deps);
309             # num fields to require is first element in array if looks like a digit, 1 otherwise.
310 3 100       11 my $num_fields_to_require = ($deps[0] =~ m/^\d+$/) ? $deps[0] : 1;
311 3         3 for my $dep (@deps){
312 11 100       16 $enough_required_fields++ if exists $valid{$dep};
313             }
314 3 100       9 push @missings, $field unless ($enough_required_fields >= $num_fields_to_require);
315             }
316              
317             # add in the constraints from the regexp maps
318             # We don't want to modify the profile, so we use a new variable.
319 124   100     390 $profile->{constraints} ||= {};
320             my $private_constraints = {
321 124         110 %{ $profile->{constraints} },
  124         400  
322             _add_constraints_from_map($profile,'constraint',\%valid),
323             };
324 124   100     447 $profile->{constraint_methods} ||= {};
325             my $private_constraint_methods = {
326 124         117 %{ $profile->{constraint_methods} },
  124         305  
327             _add_constraints_from_map($profile,'constraint_method',\%valid),
328             };
329              
330             #Decide which fields to untaint
331 124         146 my ($untaint_all, %untaint_hash);
332 124 100 66     950 if (defined $profile->{untaint_regexp_map} or defined $profile->{untaint_constraint_fields} ) {
    100 66        
333             # first deal with untaint_constraint_fields
334 3 50       9 if (defined($profile->{untaint_constraint_fields})) {
335 3 50       12 if (ref $profile->{untaint_constraint_fields} eq "ARRAY") {
    0          
336 3         2 for my $field (@{$profile->{untaint_constraint_fields}}) {
  3         8  
337 3         9 $untaint_hash{$field} = 1;
338             }
339             }
340             elsif ($valid{$profile->{untaint_constraint_fields}}) {
341 0         0 $untaint_hash{$profile->{untaint_constraint_fields}} = 1;
342             }
343             }
344              
345             # now look at untaint_regexp_map
346 3 50       10 if(defined($profile->{untaint_regexp_map})) {
347 0         0 my @untaint_regexes;
348 0 0       0 if(ref $profile->{untaint_regexp_map} eq "ARRAY") {
349 0         0 @untaint_regexes = @{$profile->{untaint_regexp_map}};
  0         0  
350             }
351             else {
352 0         0 push(@untaint_regexes, $profile->{untaint_regexp_map});
353             }
354              
355 0         0 for my $regex (@untaint_regexes) {
356             # look at both constraints and constraint_methods
357 0         0 for my $field (keys %$private_constraints, keys %$private_constraint_methods) {
358 0 0       0 next if($untaint_hash{$field});
359 0 0       0 $untaint_hash{$field} = 1 if( $field =~ $regex );
360             }
361             }
362             }
363             }
364             elsif ((defined($profile->{untaint_all_constraints}))
365             && ($profile->{untaint_all_constraints} == 1)) {
366 10         13 $untaint_all = 1;
367             }
368              
369 124         383 $self->_check_constraints($private_constraints,\%valid,$untaint_all,\%untaint_hash);
370              
371 122         141 my $force_method_p = 1;
372 122         297 $self->_check_constraints($private_constraint_methods,\%valid,$untaint_all,\%untaint_hash, $force_method_p);
373              
374             # add back in missing optional fields from the data hash if we need to
375 122         296 for my $field ( keys %data ) {
376 250 100 66     527 if ($profile->{missing_optional_valid} and $optional{$field} and (not exists $valid{$field})) {
      100        
377 2         4 $valid{$field} = undef;
378             }
379             }
380              
381             # all invalid fields are removed from valid hash
382 122         153 for my $field (keys %{ $self->{invalid} }) {
  122         327  
383 71         123 delete $valid{$field};
384             }
385              
386 122         258 my ($missing,$invalid);
387              
388 122   50     520 $self->{valid} ||= {};
389 122         163 $self->{valid} = { %valid , %{$self->{valid}} };
  122         279  
390 122         273 $self->{missing} = { map { $_ => 1 } @missings };
  30         73  
391 122         512 $self->{unknown} = { map { $_ => $data{$_} } @unknown };
  42         222  
392              
393             }
394              
395             =pod
396              
397             =head1 success();
398              
399             This method returns true if there were no invalid or missing fields,
400             else it returns false.
401              
402             As a shorthand, When the $results object is used in boolean context, it is overloaded
403             to use the value of success() instead. That allows creation of a syntax like this one used
404             in C:
405              
406             my $results = $self->check_rm('form_display','_form_profile') || return $self->dfv_error_page;
407              
408             =cut
409              
410             sub success {
411 27     27 0 38 my $self = shift;
412 27   100     40 return !($self->has_invalid || $self->has_missing);
413             }
414              
415             =head1 valid( [[field] [, value]] );
416              
417             In list context with no arguments, it returns the list of fields which
418             contain valid values:
419              
420             @all_valid_field_names = $r->valid;
421              
422             In a scalar context with no arguments, it returns an hash reference which
423             contains the valid fields as keys and their input as values:
424              
425             $all_valid_href = $r->valid;
426              
427             If called with one argument in scalar context, it returns the value of that
428             C if it contains valid data, C otherwise. The value will be an
429             array ref if the field had multiple values:
430              
431             $value = $r->valid('field');
432              
433             If called with one argument in list context, it returns the values of C
434             as an array:
435              
436             @values = $r->valid('field');
437              
438             If called with two arguments, it sets C to C and returns C.
439             This form is useful to alter the results from within some constraints.
440             See the L documentation.
441              
442             $new_value = $r->valid('field',$new_value);
443              
444             =cut
445              
446             sub valid {
447 81     81 0 7823 my $self = shift;
448 81         85 my $key = shift;
449 81         140 my $val = shift;
450 81 50       164 $self->{valid}{$key} = $val if defined $val;
451              
452 81 100       168 if (defined $key) {
453 42 100       200 return wantarray ? _arrayify($self->{valid}{$key}) : $self->{valid}{$key};
454             }
455              
456             # If we got this far, there were no arguments passed.
457 39 100       165 return wantarray ? keys %{ $self->{valid} } : $self->{valid};
  1         9  
458             }
459              
460              
461             =pod
462              
463             =head1 has_missing()
464              
465             This method returns true if the results contain missing fields.
466              
467             =cut
468              
469             sub has_missing {
470 52     52 0 2471 return scalar keys %{$_[0]{missing}};
  52         160  
471             }
472              
473             =pod
474              
475             =head1 missing( [field] )
476              
477             In list context it returns the list of fields which are missing.
478             In a scalar context, it returns an array reference to the list of missing fields.
479              
480             If called with an argument, it returns true if that C is missing,
481             undef otherwise.
482              
483             =cut
484              
485             sub missing {
486 44 100   44 0 26403 return $_[0]{missing}{$_[1]} if (defined $_[1]);
487              
488 33 100       70 wantarray ? keys %{$_[0]{missing}} : [ keys %{$_[0]{missing}} ];
  1         6  
  32         104  
489             }
490              
491              
492             =pod
493              
494             =head1 has_invalid()
495              
496             This method returns true if the results contain fields with invalid
497             data.
498              
499             =cut
500              
501             sub has_invalid {
502 67     67 0 125 return scalar keys %{$_[0]{invalid}};
  67         184  
503             }
504              
505             =pod
506              
507             =head1 invalid( [field] )
508              
509             In list context, it returns the list of fields which contains invalid value.
510              
511             In a scalar context, it returns an hash reference which contains the invalid
512             fields as keys, and references to arrays of failed constraints as values.
513              
514             If called with an argument, it returns the reference to an array of failed
515             constraints for C.
516              
517             =cut
518              
519             sub invalid {
520 34     34 0 3375 my $self = shift;
521 34         42 my $field = shift;
522 34 100       112 return $self->{invalid}{$field} if defined $field;
523              
524 21 100       79 wantarray ? keys %{$self->{invalid}} : $self->{invalid};
  2         13  
525             }
526              
527             =pod
528              
529             =head1 has_unknown()
530              
531             This method returns true if the results contain unknown fields.
532              
533             =cut
534              
535             sub has_unknown {
536 0     0 0 0 return scalar keys %{$_[0]{unknown}};
  0         0  
537              
538             }
539              
540             =pod
541              
542             =head1 unknown( [field] )
543              
544             In list context, it returns the list of fields which are unknown.
545             In a scalar context, it returns an hash reference which contains the unknown
546             fields and their values.
547              
548             If called with an argument, it returns the value of that C if it
549             is unknown, undef otherwise.
550              
551             =cut
552              
553             sub unknown {
554 29 100   29 0 632 return (wantarray ? _arrayify($_[0]{unknown}{$_[1]}) : $_[0]{unknown}{$_[1]})
    100          
555             if (defined $_[1]);
556              
557 25 50       110 wantarray ? keys %{$_[0]{unknown}} : $_[0]{unknown};
  25         83  
558             }
559              
560              
561             =pod
562              
563             =head1 msgs([config parameters])
564              
565             This method returns a hash reference to error messages. The exact format
566             is determined by parameters in the C area of the validation profile,
567             described in the L documentation.
568              
569             B the C parameter in the profile can take a code reference as a
570             value, allowing complete control of how messages are generated. If such a code
571             reference was provided there, it will be called here instead of the usual
572             processing, described below. It will receive as arguments the L
573             object and a hash reference of control parameters.
574              
575             The hashref passed in should contain the same options that you can define in
576             the validation profile. This allows you to separate the controls for message
577             display from the rest of the profile. While validation profiles may be
578             different for every form, you may wish to format messages the same way across
579             many projects.
580              
581             Controls passed into the method will be applied first, followed by ones
582             applied in the profile. This allows you to keep the controls you pass to
583             C as "global" and override them in a specific profile if needed.
584              
585             =cut
586              
587             sub msgs {
588 17     17 0 1472 my $self = shift;
589 17   100     53 my $msgs = $self->{profile}{msgs} || {};
590 17 100       44 if ((ref $msgs eq 'CODE')) {
591 1         2 return $msgs->($self,@_);
592             } else {
593 16         37 return $self->_generate_msgs(@_);
594             }
595             }
596              
597              
598             sub _generate_msgs {
599 16     16   16 my $self = shift;
600 16   100     56 my $controls = shift || {};
601 16 50 33     79 if (defined $controls and ref $controls ne 'HASH') {
602 0         0 die "$0: parameter passed to msgs must be a hash ref";
603             }
604              
605              
606             # Allow msgs to be called more than one to accumulate error messages
607 16   100     67 $self->{msgs} ||= {};
608 16   100     36 $self->{profile}{msgs} ||= {};
609 16         20 $self->{msgs} = { %{ $self->{msgs} }, %$controls };
  16         45  
610              
611             # Legacy typo support.
612 16         35 for my $href ($self->{msgs}, $self->{profile}{msgs}) {
613 32 100 100     127 if (
614             (not defined $href->{invalid_separator})
615             && (defined $href->{invalid_seperator})
616             ) {
617 1         3 $href->{invalid_separator} = $href->{invalid_seperator};
618             }
619             }
620              
621             my %profile = (
622             prefix => '',
623             missing => 'Missing',
624             invalid => 'Invalid',
625             invalid_separator => ' ',
626              
627             format => '* %s',
628 16         24 %{ $self->{msgs} },
629 16         24 %{ $self->{profile}{msgs} },
  16         68  
630             );
631              
632              
633 16         21 my %msgs = ();
634              
635             # Add invalid messages to hash
636             # look at all the constraints, look up their messages (or provide a default)
637             # add field + formatted constraint message to hash
638 16 100       34 if ($self->has_invalid) {
639 9         19 my $invalid = $self->invalid;
640 9         17 for my $i ( keys %$invalid ) {
641             $msgs{$i} = join $profile{invalid_separator}, map {
642 18   66     56 _error_msg_fmt($profile{format},($profile{constraints}{$_} || $profile{invalid}))
643 14         16 } @{ $invalid->{$i} };
  14         20  
644             }
645             }
646              
647             # Add missing messages, if any
648 16 100       34 if ($self->has_missing) {
649 6         11 my $missing = $self->missing;
650 6         11 for my $m (@$missing) {
651 6         10 $msgs{$m} = _error_msg_fmt($profile{format},$profile{missing});
652             }
653             }
654              
655 16         37 my $msgs_ref = prefix_hash($profile{prefix},\%msgs);
656              
657 16 100       30 if (! $self->success) {
658 12 100       85 $msgs_ref->{ $profile{any_errors} } = 1 if defined $profile{any_errors};
659             }
660              
661 16         77 return $msgs_ref;
662              
663             }
664              
665             =pod
666              
667             =head1 meta()
668              
669             In a few cases, a constraint may discover meta data that is useful
670             to access later. For example, when using L, several bits of meta data are discovered about files in the process
671             of validating. These can include "bytes", "width", "height" and "extension".
672             The C function is used by constraint methods to set this data. It's
673             also used to access this data. Here are some examples.
674              
675             # return all field names that have meta data
676             my @fields = $results->meta();
677              
678             # To retrieve all meta data for a field:
679             $meta_href = $results->meta('img');
680              
681             # Access a particular piece:
682             $width = $results->meta('img')->{width};
683              
684             Here's how to set some meta data. This is useful to know if you are
685             writing your own complex constraint.
686              
687             $self->meta('img', {
688             width => '50',
689             height => '60',
690             });
691              
692             This function does not currently support multi-valued fields. If it
693             does in the future, the above syntax will still work.
694              
695             =cut
696              
697             sub meta {
698 0     0 0 0 my $self = shift;
699 0         0 my $field = shift;
700 0         0 my $data = shift;
701              
702             # initialize if it's the first call
703 0   0     0 $self->{__META} ||= {};
704              
705 0 0       0 if ($data) {
706 0 0       0 (ref $data eq 'HASH') or die 'meta: data passed not a hash ref';
707 0         0 $self->{__META}{$field} = $data;
708             }
709              
710              
711             # If we are passed a field, return data for that field
712 0 0       0 if ($field) {
713 0         0 return $self->{__META}{$field};
714             }
715             # Otherwise return a list of all fields that have meta data
716             else {
717 0         0 return keys %{ $self->{__META} };
  0         0  
718             }
719             }
720              
721             # These are documented in ::Constraints, in the section
722             # on writing your own routines. It was more intuitive
723             # for the user to look there.
724              
725             sub get_input_data {
726 157     157 0 157 my $self = shift;
727 157         197 my %p = @_;
728 157 50       349 if ($p{as_hashref}) {
729 0         0 my %hash = $self->_get_input_as_hash( $self->{__INPUT_DATA} );
730 0         0 return \%hash;
731             }
732             else {
733 157         373 return $self->{__INPUT_DATA};
734             }
735             }
736              
737             sub get_filtered_data {
738 21     21 0 24 my $self = shift;
739 21         31 return $self->{__FILTERED_DATA};
740             }
741              
742             sub get_current_constraint_field {
743 5     5 0 3 my $self = shift;
744 5         8 return $self->{__CURRENT_CONSTRAINT_FIELD};
745             }
746              
747             sub get_current_constraint_value {
748 36     36 0 36 my $self = shift;
749 36         637 return $self->{__CURRENT_CONSTRAINT_VALUE};
750             }
751              
752             sub get_current_constraint_name {
753 38     38 0 38 my $self = shift;
754 38         150 return $self->{__CURRENT_CONSTRAINT_NAME};
755             }
756              
757             sub untainted_constraint_value {
758 16     16 0 18 my $self = shift;
759 16         158 my $match = shift;
760              
761 16 100       44 return undef unless defined $match;
762 12 100       1077 return $self->{__UNTAINT_THIS} ? $match : length $match;
763             }
764              
765             sub set_current_constraint_name {
766 4     4 0 4 my $self = shift;
767 4         3 my $value = shift;
768 4         6 $self->{__CURRENT_CONSTRAINT_NAME} = $value;
769             }
770             # same as above
771             sub name_this {
772 35     35 0 37 my $self = shift;
773 35         37 my $value = shift;
774 35         72 $self->{__CURRENT_CONSTRAINT_NAME} = $value;
775             }
776              
777             # INPUT: prefix_string, hash reference
778             # Copies the hash and prefixes all keys with prefix_string
779             # OUTPUT: hash reference
780             sub prefix_hash {
781 16     16 0 22 my ($pre,$href) = @_;
782 16 50       35 die "prefix_hash: need two arguments" unless (scalar @_ == 2);
783 16 50       40 die "prefix_hash: second argument must be a hash ref" unless (ref $href eq 'HASH');
784 16         79 my %out;
785 16         30 for (keys %$href) {
786 20         43 $out{$pre.$_} = $href->{$_};
787             }
788 16         25 return \%out;
789             }
790              
791              
792             # We tolerate two kinds of regular expression formats
793             # First, the preferred format made with "qr", matched using a leading paren
794             # Also, we accept the deprecated format given as strings: 'm/old/'
795             # (which must start with a slash or "m", not a paren)
796             sub _create_sub_from_RE {
797 293   100 293   713 my $re = shift || return undef;
798 48         47 my $untaint_this = shift;
799 48         44 my $force_method_p = shift;
800              
801 48         40 my $sub;
802             # If it's "qr" style
803 48 100       123 if (substr($re,0,1) eq '(') {
804             $sub = sub {
805             # With methods, the value is the second argument
806 75 100   75   120 my $val = $force_method_p ? $_[1] : $_[0];
807 75         318 my ($match) = scalar ($val =~ $re);
808 75 100 66     168 if ($untaint_this && defined $match) {
809             # pass the value through a RE that matches anything to untaint it.
810 5         19 my ($untainted) = ($& =~ m/(.*)/s);
811 5         7 return $untainted;
812             }
813             else {
814 70         211 return $match;
815             }
816 41         166 };
817              
818             }
819             else {
820 7         27 local $SIG{__DIE__} = \&confess;
821 7 50       18 my $return_code = ($untaint_this) ? '; return ($& =~ m/(.*)/s)[0] if defined($`);' : '';
822             # With methods, the value is the second argument
823 7 50       20 if ($force_method_p) {
824 0         0 $sub = eval 'sub { $_[1] =~ '.$re.$return_code. '}';
825             }
826             else {
827 7         581 $sub = eval 'sub { $_[0] =~ '.$re.$return_code. '}';
828             }
829 7 50       30 die "Error compiling regular expression $re: $@" if $@;
830             }
831 48         87 return $sub;
832             }
833              
834              
835             sub _error_msg_fmt {
836 24     24   22 my ($fmt,$msg) = @_;
837 24   50     35 $fmt ||=
838             '* %s';
839 24 50       62 ($fmt =~ m/%s/) || die 'format must contain %s';
840 24         106 return sprintf $fmt, $msg;
841             }
842              
843              
844              
845             # takes string or array ref as input
846             # returns array
847             sub _arrayify {
848             # if the input is undefined, return an empty list
849 780     780   2075 my $val = shift;
850 780 100       1421 defined $val or return ();
851              
852             # if it's a reference, return an array unless it points to an empty array. -mls
853 409 100       658 if ( ref $val eq 'ARRAY' ) {
854 175         464 local $^W = 0; # turn off warnings about undef
855 175 100       682 return grep(defined, @$val) ? @$val : ();
856             }
857             # if it's a string, return an array unless the string is missing or empty. -mls
858             else {
859 234 50       661 return (length $val) ? ($val) : ();
860             }
861             }
862              
863             # apply filter, modifying %valid by reference
864             # We don't bother trying to filter undefined fields.
865             # This prevents warnings from Perl.
866             sub _filter_apply {
867 26     26   34 my ($valid,$field,$filter) = @_;
868 26 50       59 die 'wrong number of arguments passed to _filter_apply' unless (scalar @_ == 3);
869 26 100       54 if (ref $valid->{$field} eq 'ARRAY') {
870 7         8 for (my $i = 0; $i < @{ $valid->{$field} }; $i++) {
  29         56  
871 22 50       54 $valid->{$field}->[$i] = $filter->( $valid->{$field}->[$i] ) if defined $valid->{$field}->[$i];
872             }
873             }
874             else {
875 19 50       74 $valid->{$field} = $filter->( $valid->{$field} ) if defined $valid->{$field};
876             }
877             }
878              
879             # =head2 _constraint_hash_build()
880             #
881             # $constraint_href = $self->_constraint_hash_build($spec,$untaint_p)
882             #
883             # Input:
884             # - $spec # Any constraint valid in the profile
885             # - $untaint # bool for whether we could try to untaint the field.
886             # - $force_method_p # bool for if it's a method ?
887             #
888             # Output:
889             # - $constraint_hashref
890             # Keys are as follows:
891             # constraint - the constraint as coderef
892             # name - the constraint name, if we know it.
893             # params - 'params', as given in the hashref style of specifying a constraint
894             # is_method - bool for whether this was a 'constraint' or 'constraint_method'
895              
896             sub _constraint_hash_build {
897 159     159   196 my ($self,$constraint_spec,$untaint_this,$force_method_p) = @_;
898 159 50       330 die "_constraint_hash_build received wrong number of arguments" unless (scalar @_ == 4);
899              
900 159         315 my $c = {
901             name => undef,
902             constraint => $constraint_spec,
903             };
904 159 100       334 $c->{name} = $constraint_spec if not ref $constraint_spec;
905              
906             # constraints can be passed in directly via hash
907 159 100       340 if (ref $c->{constraint} eq 'HASH') {
908 38   66     156 $c->{constraint} = ($constraint_spec->{constraint_method} || $constraint_spec->{constraint});
909 38         54 $c->{name} = $constraint_spec->{name};
910 38         58 $c->{params} = $constraint_spec->{params};
911 38 100       103 $c->{is_method} = 1 if $constraint_spec->{constraint_method};
912             }
913              
914             # Check for regexp constraint
915 159 100 100     1145 if ((ref $c->{constraint} eq 'Regexp')
    100          
916             or ( $c->{constraint} =~ m@^\s*(/.+/|m(.).+\2)[cgimosx]*\s*$@ )) {
917 22         44 $c->{constraint} = _create_sub_from_RE($c->{constraint},$untaint_this,$force_method_p);
918             }
919             # check for code ref
920             elsif (ref $c->{constraint} eq 'CODE') {
921             # do nothing, it's already a code ref
922             }
923             else {
924             # provide a default name for the constraint if we don't have one already
925 61 50 66     143 if (not $c->{name} and not ref $c->{constraint}) {
926 16   33     44 $c->{name} ||= $c->{constraint};
927             }
928              
929             #If untaint is turned on call match_* sub directly.
930 61 100       100 if ($untaint_this) {
931 3         7 my $routine = 'match_'.$c->{constraint};
932 3         3 my $match_sub = *{qualify_to_ref($routine)}{CODE};
  3         9  
933 3 50       54 if ($match_sub) {
    100          
934 0         0 $c->{constraint} = $match_sub;
935             }
936             # If the constraint name starts with RE_, try looking for it in the Regexp::Common package
937             elsif ($c->{constraint} =~ m/^RE_/) {
938 2         7 local $SIG{__DIE__} = \&confess;
939 2         4 $c->{is_method} = 1;
940 2   50     122 $c->{constraint} = eval 'sub { &_create_regexp_common_constraint(@_)}'
941             || die "could not create Regexp::Common constraint: $@";
942             } else {
943 1         13 die "No untainting constraint found named $c->{constraint}";
944             }
945             }
946             else {
947             # try to use match_* first
948 58         102 my $routine = 'match_'.$c->{constraint};
949 58 100       46 if (defined *{qualify_to_ref($routine)}{CODE}) {
  58 100       178  
    100          
950 51         1149 local $SIG{__DIE__} = \&confess;
951 51     16   3157 $c->{constraint} = eval 'sub { no strict qw/refs/; return defined &{"match_'.$c->{constraint}.'"}(@_)}';
  16     12   62  
  16         15  
  16         699  
  12         66  
  12         16  
  12         468  
952             }
953             # match_* doesn't exist; if it is supposed to be from the
954             # validator_package(s) there may be only valid_* defined
955 7         161 elsif (my $valid_sub = *{qualify_to_ref('valid_'.$c->{constraint})}{CODE}) {
956 1         14 $c->{constraint} = $valid_sub;
957             }
958             # Load it from Regexp::Common
959             elsif ($c->{constraint} =~ m/^RE_/) {
960 5         96 local $SIG{__DIE__} = \&confess;
961 5         10 $c->{is_method} = 1;
962 5   50     339 $c->{constraint} = eval 'sub { return defined &_create_regexp_common_constraint(@_)}' ||
963             die "could not create Regexp::Common constraint: $@";
964             }
965             else {
966 1         31 die "No constraint found named '$c->{name}'";
967             }
968             }
969             }
970              
971             # Save the current constraint name for later
972 157         1245 $self->{__CURRENT_CONSTRAINT_NAME} = $c->{name};
973              
974 157         256 return $c;
975              
976             }
977              
978             # =head2 _constraint_input_build()
979             #
980             # @params = $self->constraint_input_build($c,$value,$data);
981             #
982             # Build in the input that passed into the constraint.
983             #
984             # =cut
985              
986             sub _constraint_input_build {
987 161     161   200 my ($self,$c,$value,$data) = @_;
988 161 50       300 die "_constraint_input_build received wrong number of arguments" unless (scalar @_ == 4);
989              
990 161         135 my @params;
991 161 100       260 if (defined $c->{params}) {
992 24         47 for my $fname (_arrayify($c->{params})) {
993             # If the value is passed by reference, we treat it literally
994 44 100       89 push @params, (ref $fname) ? $fname : $data->{$fname}
995             }
996             }
997             else {
998 137         180 push @params, $value;
999             }
1000              
1001 161 100       306 unshift @params, $self if $c->{is_method};
1002 161         349 return @params;
1003             }
1004              
1005             # =head2 _constraint_check_match()
1006             #
1007             # ($value,$failed_href) = $self->_constraint_check_match($c,\@params,$untaint_this);
1008             #
1009             # This is the routine that actually, finally, checks if a constraint passes or fails.
1010             #
1011             # Input:
1012             # - $c, a constraint hash, as returned by C<_constraint_hash_build()>.
1013             # - \@params, params to pass to the constraint, as prepared by C<_constraint_input_build()>.
1014             # - $untaint_this bool if we untaint successful constraints.
1015             #
1016             # Output:
1017             # - $value the value if successful
1018             # - $failed_href a hashref with the following keys:
1019             # - failed bool for failure or not
1020             # - name name of the failed constraint, if known.
1021              
1022             sub _constraint_check_match {
1023 161     161   172 my ($self,$c,$params,$untaint_this) = @_;
1024 161 50       299 die "_constraint_check_match received wrong number of arguments" unless (scalar @_ == 4);
1025              
1026             # Store whether or not we want untainting in the object so that constraints
1027             # can do the right thing conditionally.
1028 161         193 $self->{__UNTAINT_THIS} = $untaint_this;
1029              
1030 161         1654 my $match = $c->{constraint}->( @$params );
1031              
1032             # We need to make this distinction when untainting,
1033             # to allow untainting values that are defined but not true,
1034             # such as zero.
1035 161         2827 my $success;
1036 161 100       345 if (defined $match) {
1037 137 100       238 $success = ($untaint_this) ? length $match : $match;
1038             }
1039              
1040 161 100       300 my $failed = 1 unless $success;
1041             return (
1042             $match,
1043             {
1044             failed => $failed,
1045             name => $self->{__CURRENT_CONSTRAINT_NAME},
1046             },
1047 161         609 );
1048             }
1049              
1050             # Figure out whether the data is a hash reference of a param-capable object and return it has a hash
1051             sub _get_input_as_hash {
1052 285     285   294 my ($self,$data) = @_;
1053 285         1611 $self->{__INPUT_DATA} = $data;
1054              
1055 285         1256 require Scalar::Util;
1056              
1057             # This checks whether we have an object that supports param
1058 285 50 33     1434 if ( Scalar::Util::blessed($data) && $data->can('param') ) {
    50          
1059 0         0 my %return;
1060 0         0 for my $k ($data->param()){
1061             # we expect param to return an array if there are multiple values
1062 0         0 my @v;
1063              
1064             # CGI::Simple requires us to call 'upload()' to get upload data,
1065             # while CGI/Apache::Request return it on calling 'param()'.
1066             #
1067             # This seems quirky, but there isn't a way for us to easily check if
1068             # "this field contains a file upload" or not.
1069 0 0       0 if ($data->isa('CGI::Simple')) {
1070 0   0     0 @v = $data->upload($k) || $data->param($k);
1071             }
1072             else {
1073             # insecure
1074 0         0 @v = $data->multi_param($k);
1075             }
1076              
1077             # we expect param to return an array if there are multiple values
1078 0 0       0 $return{$k} = scalar(@v)>1 ? \@v : $v[0];
1079             }
1080 0         0 return %return;
1081             }
1082             # otherwise, it's already a hash reference
1083             elsif (ref $data eq 'HASH') {
1084             # be careful to actually copy array references
1085 285         787 my %copy = %$data;
1086 285         492 for (grep { ref $data->{$_} eq 'ARRAY' } keys %$data) {
  753         1226  
1087 44         36 my @array_copy = @{ $data->{$_} };
  44         85  
1088 44         68 $copy{$_} = \@array_copy;
1089             }
1090              
1091 285         1063 return %copy;
1092             }
1093             else {
1094 0         0 die "Data::FormValidator->validate() or check() called with invalid input data structure.";
1095             }
1096             }
1097              
1098             # A newer version of this logic now exists in Constraints.pm in the AUTOLOADing section
1099             # This is is used to support the older param passing style. Eg:
1100             #
1101             # {
1102             # constraint => 'RE_foo_bar',
1103             # params => [ \'zoo' ]
1104             # }
1105             #
1106             # Still, it's possible, the two bits of logic could be refactored into one location if you cared
1107             # to do that.
1108              
1109             sub _create_regexp_common_constraint {
1110             # this should work most of the time and is useful for preventing warnings
1111              
1112             # prevent name space clashes
1113             package Data::FormValidator::Constraints::RegexpCommon;
1114              
1115 7     7   550 require Regexp::Common;
1116 7         1805 import Regexp::Common 'RE_ALL';
1117              
1118 7         118484 my $self = shift;
1119 7         18 my $re_name = $self->get_current_constraint_name;
1120             # deference all input
1121 7 100       34 my @params = map {$_ = $$_ if ref $_ } @_;
  9         40  
1122              
1123 59     59   313 no strict "refs";
  59         69  
  59         31955  
1124 7   50     25 my $re = &$re_name(-keep=>1,@params) || die 'no matching Regexp::Common routine found';
1125 7 100       305 return ($self->get_current_constraint_value =~ qr/^$re$/) ? $1 : undef;
1126             }
1127              
1128             # _add_constraints_from_map($profile,'constraint',\%valid);
1129             # Returns:
1130             # - a hash to add to either 'constraints' or 'constraint_methods'
1131              
1132             sub _add_constraints_from_map {
1133 248 50   248   456 die "_add_constraints_from_map: need 3 arguments" unless (scalar @_ == 3);
1134 248         287 my ($profile, $name, $valid) = @_;
1135 248 50       849 ($name =~ m/^constraint(_method)?$/) || die "unexpected input.";
1136              
1137 248         367 my $key_name = $name.'s';
1138 248         291 my $map_name = $name.'_regexp_map';
1139              
1140 248         299 my %result = ();
1141 248         225 for my $re (keys %{ $profile->{$map_name} }) {
  248         549  
1142 17         33 my $sub = _create_sub_from_RE($re);
1143              
1144             # find all the keys that match this RE and add a constraint for them
1145 17         40 for my $key (keys %$valid) {
1146 45 100       279 if ($sub->($key)) {
1147 28         45 my $cur = $profile->{$key_name}{$key};
1148 28         40 my $new = $profile->{$map_name}{$re};
1149             # If they already have an arrayref of constraints, add to the list
1150 28 100       73 if (ref $cur eq 'ARRAY') {
    100          
1151 2         3 push @{ $result{$key} }, @$cur, $new;
  2         6  
1152             }
1153             # If they have a single constraint defined, create an array ref with with this plus the new one
1154             elsif ($cur) {
1155 1         2 $result{$key} = [$cur,$new];
1156             }
1157             # otherwise, a new constraint is created with this as the single constraint
1158             else {
1159 25         37 $result{$key} = $new;
1160             }
1161 28 50       133 warn "$map_name: $key matches\n" if $profile->{debug};
1162             }
1163             }
1164             }
1165 248         540 return %result;
1166             }
1167              
1168             sub _bool_overload_based_on_success {
1169 9     9   1679 my $results = shift;
1170 9         14 return $results->success()
1171             }
1172              
1173             # =head2 _check_constraints()
1174             #
1175             # $self->_check_constraints(
1176             # $profile->{constraint_methods},
1177             # \%valid,
1178             # $untaint_all
1179             # \%untaint_hash
1180             # $force_method_p
1181             #);
1182             #
1183             # Input:
1184             # - 'constraints' or 'constraint_methods' hashref
1185             # - hashref of valid data
1186             # - bool to try to untaint everything
1187             # - hashref of things to untaint
1188             # - bool if all constraints should be treated as methods.
1189              
1190             sub _check_constraints {
1191 246     246   306 my ($self,
1192             $constraint_href,
1193             $valid,
1194             $untaint_all,
1195             $untaint_href,
1196             $force_method_p) = @_;
1197              
1198 246         669 while ( my ($field,$constraint_list) = each %$constraint_href ) {
1199 149 100       284 next unless exists $valid->{$field};
1200              
1201 145 100       329 my $is_constraint_list = 1 if (ref $constraint_list eq 'ARRAY');
1202 145   100     628 my $untaint_this = ($untaint_all || $untaint_href->{$field} || 0);
1203              
1204 145         116 my @invalid_list;
1205             # used to insure we only bother recording each failed constraint once
1206             my %constraints_seen;
1207 145         236 for my $constraint_spec (_arrayify($constraint_list)) {
1208              
1209             # set current constraint field for use by get_current_constraint_field
1210 159         243 $self->{__CURRENT_CONSTRAINT_FIELD} = $field;
1211              
1212             # Initialize the current constraint name to undef, to prevent it
1213             # from being accidently shared
1214 159         193 $self->{__CURRENT_CONSTRAINT_NAME} = undef;
1215              
1216 159         338 my $c = $self->_constraint_hash_build($constraint_spec,$untaint_this, $force_method_p);
1217 157 100       331 $c->{is_method} = 1 if $force_method_p;
1218              
1219 157 100       313 my $is_value_list = 1 if (ref $valid->{$field} eq 'ARRAY');
1220 157         416 my %param_data = ( $self->_get_input_as_hash($self->get_input_data) , %$valid );
1221 157 100       292 if ($is_value_list) {
1222 7         10 for (my $i = 0; $i < scalar @{ $valid->{$field}} ; $i++) {
  21         46  
1223 14 100       33 if( !exists $constraints_seen{\$c} ) {
1224              
1225 11         19 my @params = $self->_constraint_input_build($c,$valid->{$field}->[$i],\%param_data);
1226              
1227             # set current constraint field for use by get_current_constraint_value
1228 11         16 $self->{__CURRENT_CONSTRAINT_VALUE} = $valid->{$field}->[$i];
1229              
1230 11         22 my ($match,$failed) = $self->_constraint_check_match($c,\@params,$untaint_this);
1231 11 100       20 if ($failed->{failed}) {
1232 4         4 push @invalid_list, $failed;
1233 4         10 $constraints_seen{\$c} = 1;
1234             }
1235             else {
1236 7 50       20 $valid->{$field}->[$i] = $match if $untaint_this;
1237             }
1238             }
1239             }
1240             }
1241             else {
1242 150         345 my @params = $self->_constraint_input_build($c,$valid->{$field},\%param_data);
1243              
1244             # set current constraint field for use by get_current_constraint_value
1245 150         207 $self->{__CURRENT_CONSTRAINT_VALUE} = $valid->{$field};
1246              
1247 150         285 my ($match,$failed) = $self->_constraint_check_match($c,\@params,$untaint_this);
1248 150 100       274 if ($failed->{failed}) {
1249 75         476 push @invalid_list, $failed
1250             }
1251             else {
1252 75 100       438 $valid->{$field} = $match if $untaint_this;
1253             }
1254             }
1255             }
1256              
1257 143 100       547 if (@invalid_list) {
1258 71         92 my @failed = map { $_->{name} } @invalid_list;
  79         222  
1259 71         78 push @{ $self->{invalid}{$field} }, @failed;
  71         265  
1260             # the older interface to validate returned things differently
1261 71 100       75 push @{ $self->{validate_invalid} }, $is_constraint_list ? [$field, @failed] : $field;
  71         446  
1262             }
1263             }
1264             }
1265              
1266             1;
1267              
1268             __END__