NAME
Data::CGIForm - Form Data Interface.
DESCRIPTION
Data::CGIForm is yet another way to parse and handle CGI form data. The main motivation behind this module was a simple specification based validator that could handle multiple values.
You probably don't want to use this module. CGI::Validate is a much more feature complete take on getting this sort of work done. You may then ask why this is on the CPAN, I ask that of myself from time to time....
SYNOPSIS
my %spec = (
username => qr/^([a-z0-9]+)$/,
password => {
regexp => qr/^([a-z0-9+])$/,
filter => [qw(strip_leading_ws, strip_trailing_ws)],
},
email => {
regexp => qr/^([a-z0-9@.]+)$/,
filter => \&qualify_domain,
optional => 1,
errors => {
empty => 'You didn\'t enter an email address.',
invalid => 'Bad [% key %]: "[% value %]"',
},
extra_test => \&check_email_addr,
},
email2 => {
equal_to => email,
errors => {
unequal => 'Both email addresses must be the same.',
},
},
);
my $r = $ENV{'MOD_PERL'} ? Apache::Request->instance : CGI->new;
my $form = Data::CGIForm->new(datasource => $r, spec => \%spec);
my @params = $form->params;
foreach $param (@params) {
next unless my $error_string = $form->error($param);
print STDERR $error_string;
}
if ($form->error('username')) {
handle_error($form->username, $form->error('username'));
}
my $email = $form->param('email');
my $password = $form->password;
Building the Spec
The spec is a hashref describing the format of the data expected, and the rules that that data must match. The keys for this hash are the parameters that you are expecting.
In the most simple use, the value for a key can simply be a regular expression object. For example:
%spec = (
key => qr/.../,
);
For the more complex options, a key should point to a hashref containing the options for that key. The following keys are supported in the hashref:
- equal_to
-
This is simply a bit of syntaxtic sugar. It makes this:
email2 => { equal_to => email, }
The same as:
email2 => { regexp => qr/^(.*)$/, extra_test => sub { my ($textref, $form) = @_; return unless my $value = $form->param('email'); if ($$textref eq $value) { return 1; } else { $form->param( email => ''); $form->param( email2 => ''); $self->errorf(email2 => unequal => $$textref); $self->error( email => $self->error('email2')); return 0; } }, }
equal_to
does not work properly with multiple values. This is a feature. Also, do not useequal_to
with a key more than once. The dragons may come looking for you if you do, and you taste good with ketchup. - regexp
-
The regular expression that the data must match.
- length
-
The exact length that the input must be.
Note: Length is tested after filtering, but before any extra_test is run.
- min_length
-
The minimum length that the input may be.
- max_length
-
The maximum length that the input may be.
- filter
-
The filter (or filters; to have more than one use an array ref) that the data must be passed though before it is validated. See the 'Filters' section below.
- optional
-
boolean. If true then the parameter is optioinal. Note that if the parameter is given, then it is still validated. It can still be marked as an error if parameter is given.
- errors
-
A hashref to the error strings for this parameter. See the Error Strings section below.
- extra_test
-
A codefef (or arrayref of coderefs) of boolean functions that will be used in the validation process. See the Extra Test section below.
Filters
These functions are used to filter the data before that data is validated. In the spec they can be listed as a single filter, or an arrayref of many filters.
There filters are built in, and can be specified by name:
- strip_leading_ws
-
Removes any leading white space from the data.
- strip_trailing_ws
-
Removes any trailing white space from the data.
- strip_ws
-
Removes any white space from the data.
- lc
-
Converts the data to lowercase.
- uc
-
Converts the data to uppercase.
If you with you use your own filter, then list it as a coderef in the spec.
Filters are passed 1 parameter. $_[0] is a scalar ref to the current data being filtered. For example:
sub fix_newlines {
my $textref = shift;
$$textref =~ s/[\n\r]*/\n/sg;
}
Error Strings
For each key in the spec, you can specify different error messagses for different situations. For example:
%spec = (
field => {
errors => {
empty => "You didn't fill this out!"
invalid => "That doesn't look right!"
},
...
},
);
Currently, there are four error types. invalid
is used when the data does not match the validation specification, while empty
is used when no data was given and the field is not optional. unequal
is used when an equal_to pair does not match. length
is used when a length, min_length, or max_length parameter is violated.
Two tags are filled in when the error messages are set:
[% key %] == Becomes ==> The current keyname.
[% value %] == Becomes ==> The value for the current key.
For example
errors => {
invalid => "[% value %] doesn't look like a [% key %]",
}
If a type isn't given, then a default message is used.
Extra Test
Extra tests give the programmer a hook into the validation process.
Extra tests are declared in a similar fasion in the spec to filters, with the exception that everything is a coderef. There are no built in extra tests.
Extra tests functions are passed 3 paramters:
$_[0] is a scalar refernce to the data being tested:
sub is_right_size {
return (${$_[0]} > 100 and ${$_[0]} < 1250);
}
$_[1] is the current Data::CGIForm object. $_[2] is the key name for the data being filtered. For example:
sub check_email {
my ($textref, $form, $key) = @_;
unless (Email::Valid->address($$textref)) {
$form->error(
$key => "address failed $Email::Valid::Details check."
);
return;
}
return 1;
}
Note that just setting the error string does not clear the parameter. You may want to do this yourself to keep with the built in behavior:
sub check_email {
my ($textref, $form, $key) = @_;
unless (Email::Valid->address($$textref)) {
$form->param($key => '');
$form->error(
$key => "address failed $Email::Valid::Details check."
);
return;
}
return 1;
}
METHODS
Data::CGIForm->new()
Creates the Data::CGIForm object.
This should be called in the following matter:
Data::CGIForm->new(datasource => $r, spec => \%spec, %options)
datasource
should be something that has a param()
method, like a CGI object, or a Apache::Request object. %spec
is explained in the specification docs above.
The following options are supported:
- start_param
-
Specifies that a given parameter acts as a switch for validation. If the value from the datasource for this parameter is true, then validation will be skipped and an empty string set as the value for each parameter in the spec.
$form->params
Returns a list of all the parameters that were in the datasource that are called for in the spec.
$form->param($name => $new_value)
Returns the parameter for a given var. If called in scalar context it returns the first value fetched from the datasource, regardless of the number of values.
$new_value
should be a scalar or an array ref.
If $name
is not given then this method returns $form->params
, just like CGI or Apache::Request.
$form->error($param_name => $new_error)
Returns the error string (if an error occcured) for the a given parameter.
If two arguments are passed, this can be used to set the error string.
If no parameter is passed, than it returns boolean. True if an error occured in validating the data, false if no error occured.
$form->errors
Returns a hash of all the errors in param_name => error_message
pairs.
$form->errorf($key, $type, $data)
Sets the error for $key
to the format type $type
, using $data
for the [% value %]
tag.
$form->started
Returns boolean based on if the start_param was set. True if the form was started, false otherwise.
$form->ready
Returns boolean; true if the form is started and there are no errors, false other wise.
AUTOLOAD
Data::CGIForm creates uses AUTOLOAD to create methods for the parameters in the spec. These methods just call $form->param($name)
, but it might prove helpful/elegent.
TODO
Do we want to test new values given to param() against the spec?
Make sure the user hasn't given dangerous equal_to pairs.
AUTHOR
Maintained by: Tim Wilde <twilde@cymru.com>
Originally by: Chris Reinhardt <cpan@triv.org>
COPYRIGHT
Portions Copyright (c) 2007 Tim Wilde. All rights reserved.
Portions Copyright (c) 2006 Dynamic Network Services, Inc. All rights reserved.
Portions Copyright (c) 2002 Chris Reinhardt. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.