File Coverage

lib/CGI/Application/Plugin/ValidateQuery.pm
Criterion Covered Total %
statement 67 71 94.3
branch 22 26 84.6
condition 8 12 66.6
subroutine 12 12 100.0
pod 2 4 50.0
total 111 125 88.8


line stmt bran cond sub pod time code
1             package CGI::Application::Plugin::ValidateQuery;
2              
3 7     7   328261 use warnings;
  7         16  
  7         263  
4 7     7   39 use strict;
  7         21  
  7         230  
5              
6 7     7   37 use base 'Exporter';
  7         21  
  7         627  
7              
8 7     7   42 use Carp 'croak';
  7         12  
  7         451  
9 7     7   2734 use Params::Validate ':all';
  7         36716  
  7         7491  
10              
11             =head1 NAME
12              
13             CGI::Application::Plugin::ValidateQuery - lightweight query validation for CGI::Application
14              
15             =head1 VERSION
16              
17             Version 1.0.5
18              
19             =cut
20              
21             our $VERSION = '1.0.5';
22              
23             our @EXPORT_OK = qw(
24             validate_query_config
25             validate_app_params
26             validate_query
27             validate_query_error_mode
28             );
29             push @EXPORT_OK, @Params::Validate::EXPORT_OK;
30             our %EXPORT_TAGS = (
31             all => \@EXPORT_OK,
32             types => $Params::Validate::EXPORT_TAGS{types}
33             );
34              
35             local $Params::Validate::NO_VALIDATION = 0;
36              
37             sub validate_query_config {
38 14     14 0 31798 my $self = shift;
39              
40 14         47 my $opts = {@_};
41              
42 14         39 $opts = {map {uc $_ => $opts->{$_}} keys %$opts};
  13         56  
43              
44             # for now, default checking all params. First config arg is legacy.
45 14 50 33     115 if ( defined $opts->{EXTRA_FIELDS_OPTIONAL} or defined $opts->{ALLOW_EXTRA} ) {
46 0         0 delete $opts->{EXTRA_FIELDS_OPTIONAL};
47 0         0 delete $opts->{ALLOW_EXTRA};
48 0         0 $self->{__CAP_VALQUERY_ALLOW_EXTRA} = 1;
49             } else {
50 14         41 $self->{__CAP_VALQUERY_ALLOW_EXTRA} = 0;
51             }
52              
53 14 100       56 $self->{__CAP_VALQUERY_ERROR_MODE} = defined $opts->{ERROR_MODE} ?
54             delete $opts->{ERROR_MODE} : 'validate_query_error_mode';
55              
56 14 100       62 $self->{__CAP_VALQUERY_LOG_LEVEL} = defined $opts->{LOG_LEVEL} ?
57             delete $opts->{LOG_LEVEL} : undef;
58              
59 14 100 100     198 croak 'log_level given but no logging interface exists.'
60             if $self->{__CAP_VALQUERY_LOG_LEVEL} && !$self->can('log');
61              
62 2         287 croak 'Invalid option(s) ('.join(', ', keys %{$opts}).') passed to'
  13         54  
63 13 100       19 .'validate_query_config' if %{$opts};
64             }
65              
66             sub validate_app_params {
67 3     3 1 1579 my $self = shift;
68              
69 3 50       8 return unless @_;
70              
71 3         14 my $query_props = {@_};
72              
73 3         6 $query_props->{allow_extra} = 1;
74 3         8 $query_props->{app_params} = 1;
75              
76 3         8 return _validate($self, $query_props);
77             }
78              
79             sub validate_query {
80 14     14 1 19297 my $self = shift;
81              
82 14 50       46 return unless @_;
83              
84 14         74 return _validate($self, {@_});
85             }
86              
87              
88             sub _validate {
89 17     17   28 my $self = shift;
90 17         24 my $query_props = shift;
91              
92 17   66     94 my $log_level = delete $query_props->{log_level}
93             || $self->{__CAP_VALQUERY_LOG_LEVEL};
94              
95 17   66     133 my $allow_extra = delete($query_props->{extra_fields_optional})
96             || delete($query_props->{allow_extra})
97             || $self->{__CAP_ALLOW_EXTRA};
98              
99 17         34 my $app_params = delete $query_props->{app_params};
100              
101 17 100       64 my $param_obj = $app_params ? $self : $self->query;
102              
103             # filter query_props to support quick regex syntax
104             # turns
105             # key => qr/$regex/
106             # into
107             # key => { regex => qr/$regex/ }
108 17         136 for my $key (keys %$query_props) {
109 77         95 my $val = $query_props->{$key};
110 77 50       188 if ( ref $val eq 'Regexp' ) {
111 0         0 $query_props->{$key} = { regex => $val, type => SCALAR };
112             }
113             }
114              
115 17         30 my %validated;
116 17         22 eval {
117 17         23 my @vars_array;
118 17         53 for my $p ($param_obj->param) {
119 82         457 my @values = $param_obj->param($p);
120 82 100       1503 push @vars_array, ($p, scalar @values > 1 ? \@values : $values[0]);
121             }
122 17         1023 %validated = validate_with(
123             params => \@vars_array,
124             spec => $query_props,
125             allow_extra => $allow_extra
126             );
127             };
128 17 100       3501 if ($@) {
129 7         68 my $log_msg = "Query Validation Failed: $@";
130 7 100       28 $self->log->$log_level($log_msg) if $log_level;
131 7         158 $self->error_mode($self->{__CAP_VALQUERY_ERROR_MODE});
132              
133 7         1132 croak $log_msg;
134             }
135              
136             # Account for default values, and use the expanded -name / -value
137             # syntax for CGI to ensure proper handling of multivalued fields.
138             my $sub = $app_params
139 9     9   33 ? sub { my $p = shift; $param_obj->param($p, $validated{$p}) }
  9         24  
140 10 100   40   58 : sub { my $p = shift; $param_obj->param(-name=>$p, -value=>$validated{$p}) };
  40         61  
  40         153  
141              
142 10         30 map { $sub->($_) } keys %validated;
  49         2502  
143              
144 10         630 return %validated;
145             }
146              
147             sub validate_query_error_mode {
148 1     1 0 158 my $self = shift;
149 1         4 return "Request not understoodThe
150             request submitted could not be understood.";
151             }
152              
153             1;
154              
155             __END__