File Coverage

blib/lib/HTML/CheckArgs.pm
Criterion Covered Total %
statement 56 61 91.8
branch 16 22 72.7
condition 1 3 33.3
subroutine 12 12 100.0
pod 7 7 100.0
total 92 105 87.6


line stmt bran cond sub pod time code
1             package HTML::CheckArgs;
2              
3             =pod
4              
5             =head1 NAME
6              
7             HTML::CheckArgs - Validate data passed to web applications
8              
9             =head1 SYNOPSIS
10              
11             use HTML::CheckArgs;
12              
13             my @banned_domains = ( 'whitehouse.gov', 'gop.com' );
14             my $config = {
15             email_address => {
16             as => 'email',
17             required => 1,
18             label => 'Email Address',
19             order => 1,
20             params => { banned_domains => \@banned_domains },
21             },
22             num_tickets => {
23             as => 'integer',
24             required => 1,
25             label => 'Number of Tickets',
26             order => 2,
27             params => { min => 0, max => 10 },
28             },
29             };
30              
31             my $handler = HTML::CheckArgs->new( $config );
32             my ( $error_message, $error_code );
33             foreach my $field ( sort { $config->{$a}{order} <=> $config->{$b}{order} } keys %$config ) {
34             if ( $handler->validate( $field, $ARGS{$field} ) ) {
35             $ARGS{$field} = $handler->value;
36             } else {
37             push( @$error_message, $handler->error_message );
38             push( @$error_code, $handler->error_code );
39             }
40             }
41              
42             =head1 DESCRIPTION
43              
44             HTML::CheckArgs validates data passed to web applications. Architecturally,
45             it is based on CGI::Untaint, and we follow that model of extensibility
46             as well.
47              
48             Most of the work is done in the $config hashref. $config's keys are the
49             fieldnames to be validated. The following parameters can be passed in:
50              
51             =over
52              
53             =item B
54              
55             Name of the module that should be used to validate the data. The following modules
56             are available:
57              
58             =over
59              
60             =item cc_expiration
61              
62             Passed a date string in the format YYYYMM, will determine if the string is valid, and
63             if the date is in the future.
64              
65             =item cc_number
66              
67             Validates credit card numbers based on Luhn checksum.
68              
69             =item country
70              
71             Validates 2-character country code or full country name per Georgraphy::Countries.
72              
73             =item date
74              
75             Passed a date string, a format, and a regex of the format, will determine if the string
76             represents a valid date.
77              
78             =item dollar
79              
80             Validates a dollar figure. Can optionally specify minimum and maximum vaues to check
81             against.
82              
83             =item email
84              
85             Uses Email::Valid to check email addresses. Can optionally specify no administrative
86             addresses (e.g. root@domain.com), no government addresses (me@dot.gov), or no addresses
87             from a list of domains passed to the module.
88              
89             =item integer
90              
91             Determines if number is a valid interger. Can optionally specify minimum and maximum
92             values to check against.
93              
94             =item option
95              
96             Determines if a value is a member of a list passed to the module. Useful when the form
97             input is a select or a radio button.
98              
99             =item phone
100              
101             Determines if a string is valid phone number. Only does strict validation on US phone numbers,
102             but other formats could be included.
103              
104             =item postal_code
105              
106             Validates a postal or ZIP code. Only does strict validation on US ZIP codes.
107              
108             =item state
109              
110             Validates a two-character state abbrieviation or full name. Only does strict validation
111             on US values.
112              
113             =item string
114              
115             A catch-all class. Can format the string per the routines in HTML::FormatData, and can
116             also do regex checks, checks on the number of character, number of words, etc.
117              
118             =item url
119              
120             Uses URL::Find to validate the URL. Can optionally check the URL via LWP::UserAgent.
121              
122             =back
123              
124             =item B
125              
126             Set to 1 if the field is required. Default is 0 (not required).
127              
128             =item B
129              
130             The order the fields should be evaluated in.
131              
132             =item B
133              
134             Field name label to be used for user error messages.
135              
136             =item B
137              
138             A flag that can be passed to your error reporting instrument as an
139             indicator of whether the error should be displayed to the user. Default
140             is 0.
141              
142             =item B
143              
144             Extra parameters that should be passed to the specific module
145             validating the data. Passing parameters to a module that does not support
146             use this feature will cause it to 'die'. Passing unknown parameters will
147             also cause it to 'die'.
148              
149             =item B
150              
151             Determines if the value returned should be cleaned up if the value is validated.
152             Set to 1 to preserve the original value. Default is 0 (value will be cleaned).
153             Some modules do not support cleaning the input. If you pass 'noclean' to one of
154             these modules, it will 'die'.
155              
156             =item B
157              
158             Set to 1 if you want the value to be untainted. Default is 0 (don't untaint).
159              
160             Please note that all untainting is done after a successful is_valid call to
161             the specific validation module. If a value is_valid, we assume it is safe to
162             untaint it without further checks, so the regex pattern /(.*)/s is used.
163             If you want more rigorous checking, it is advisable that you improve the
164             is_valid code or do alternate checks before untainting the value.
165              
166             =back
167              
168             =head1 METHODS
169              
170             =cut
171              
172 13     13   13102 use 5.006;
  13         48  
  13         642  
173 13     13   82 use strict;
  13         30  
  13         502  
174 13     13   99 use warnings;
  13         28  
  13         567  
175              
176 13     13   73 use Carp qw( croak );
  13         22  
  13         1009  
177 13     13   86 use Scalar::Util qw( tainted );
  13         34  
  13         10354  
178              
179             our $VERSION = '0.11';
180              
181             =pod
182              
183             =head2 new( $config [, $alt_messages ] )
184              
185             This method creates a new HTML::CheckArgs object, using the $config hashref.
186             Returns the blessed object.
187              
188             An optional $alt_messages parameter -- a hashref of alternate error messages
189             keyed error codes -- can be used to override the default error messages passed
190             back from the modules that perform the actual verification.
191              
192             =cut
193              
194             sub new {
195 30     30 1 447974 my $class = shift;
196 30         58 my $config = shift;
197 30         51 my $alt_messages = shift;
198              
199 30         171 bless { _config => $config, _alt_messages => $alt_messages }, $class;
200             }
201              
202             =pod
203              
204             =head2 accessors
205              
206             The following data can be get/set:
207              
208             =over
209              
210             =item error_code
211              
212             Each error registered has a unique code attached to it, in the format
213             name_of_module_xx, where xx is a numerical code.
214              
215             =item error_message
216              
217             Each error also has a text message suitable for presentation to the
218             user. Creating a custom lookup list based on error codes is certainly
219             possible if you wish to override the default values.
220              
221             =item value
222              
223             If there is an error, 'value' retains the value originally passed in.
224             Otherwise, value has the original value or a cleaned-up version
225             depending on the $config hashref settings.
226              
227             =item config
228              
229             This gets the $config hashref value for a particular key. This is then
230             passed to the specific module called to validate a specific value.
231              
232             =item alt_message
233              
234             This gets the $alt_messages hashref value for a particular key. This is then
235             used to override the default error message associated with a particular code.
236              
237             =back
238              
239             =cut
240              
241             sub error_code {
242 154     154 1 236 my $self = shift;
243 154 100       442 $self->{error_code} = shift if @_;
244 154         425 return $self->{error_code};
245             }
246              
247             sub error_message {
248 94     94 1 124 my $self = shift;
249 94 50       260 $self->{error_message} = shift if @_;
250 94         154 return $self->{error_message};
251             }
252              
253             sub value {
254 156     156 1 2402 my $self = shift;
255 156 100       412 $self->{value} = shift if @_;
256 156         441 return $self->{value};
257             }
258              
259             sub config {
260 66     66 1 96 my $self = shift;
261 66         93 my $field = shift;
262 66         229 return $self->{_config}{$field};
263             }
264              
265             sub alt_message {
266 28     28 1 44 my $self = shift;
267 28         38 my $code = shift;
268 28         113 return $self->{_alt_messages}{$code};
269             }
270              
271             =pod
272              
273             =head2 validate( $field, $value )
274              
275             Passes $field, $value and field-specific $config info
276             to the proper module for validation.
277              
278             Returns true if validation was successful, otherwise false.
279              
280             =cut
281              
282             sub validate {
283 66     66 1 315 my $self = shift;
284 66         108 my $field = shift;
285 66         97 my $value = shift;
286              
287 66         174 my $config = $self->config( $field );
288              
289 66 50       242 croak( "'as' is a required config parameter" ) unless $config->{as};
290              
291             # initialize object vars
292 66         166 $self->value( undef );
293 66         160 $self->error_code( undef );
294 66         225 $self->error_message( undef );
295              
296             # trim leading/trailing whitespace from $value
297 66 100       208 $value =~ s/^\s+// if $value;
298 66 100       206 $value =~ s/\s+$// if $value;
299              
300 66         237 my $module = 'HTML::CheckArgs::' . $config->{as};
301 66         5637 eval "require $module";
302 66 100       3210 croak( "Could not instantiate $module: $@" ) if $@;
303 60         315 my $child = $module->new( $config, $field, $value );
304              
305             # validate
306 60 100       248 unless ( $child->is_valid ) {
307 28         89 $self->error_code( $child->error_code );
308 28 50       87 if ( my $msg = $self->alt_message( $child->error_code ) ) {
309 0         0 $self->error_message( $msg );
310             } else {
311 28         83 $self->error_message( $child->error_message );
312             }
313 28         187 return;
314             }
315              
316             # untaint?
317 30 50 33     103 if ( $config->{untaint} && tainted $child->value ) {
318 0         0 my $value = $child->value;
319 0 0       0 if ( $value =~ m/(.*)/s ) {
320 0         0 $child->value( $1 );
321             } else {
322 0         0 croak( "Could not untaint $value of type " . $config->{as} );
323             }
324             }
325              
326 30         90 $self->value( $child->value );
327 30         117 return 1;
328             }
329              
330             =pod
331              
332             =head1 AUTHOR
333              
334             Eric Folley, Eeric@folley.netE
335              
336             =head1 COPYRIGHT AND LICENSE
337              
338             Copyright 2004-2005 by Eric Folley
339              
340             This library is free software; you can redistribute it and/or modify
341             it under the same terms as Perl itself.
342              
343             =cut
344              
345             1;