NAME

CGI::FormMagick::Validator - validate data from FormMagick forms

SYNOPSIS

use CGI::FormMagick;

DESCRIPTION

This module provides some common validation routines. Validation routines return the string "OK" if they succeed, or a descriptive message if they fail.

Validation routines provided:

nonblank

The data is not an empty string : $data ne ""

integer

The data is a positive integer.

number

The data is a number (positive and negative real numbers, and scientific notation are OK).

word

The data looks like a single word: $data !~ /\W/

minlength(n)

The data is at least n characters long: length($data) >= $n

maxlength(n)

The data is no more than n characters long: length($data) <= $n

exactlength(n)

The data is exactly n characters long: length($data) E== $n

lengthrange(n,m)

The data is between n and c<m> characters long: length($data) >= $n and length($data) <= $m.

url

The data looks like a (normalish) URL: $data =~ m!(http|ftp)://(\w/.-/+)!

email

The data looks more or less like an internet email address: $data =~ /.+\@.+\..+/

Note: not fully compliant with the entire gamut of RFC 822 addressing ;)

domain_name

The data looks like an internet domain name or hostname.

ip_number

The data looks like a valid IP number.

username

The data looks like a good, valid username

password

The data looks like a good password

date

The data looks like a date. Requires the Time::ParseDate module to be installed.

iso_country_code

The data is a standard 2-letter ISO country code. Requires the Locale::Country module to be installed.

US_state

The data is a standard 2-letter US state abbreviation. Uses Geography::State in non-strict mode, so this module must be installed for it to work.

US_zipcode

The data looks like a valid US zipcode

credit_card_number

The data looks like a valid credit card number. Checks the input for numeric characters only, length, and runs it through the checksumming algorithm used by most (all?) credit cards.

credit_card_expiry

The data looks like a valid credit card expiry date. Checks MM/YY and MM/YYYY format dates and fails if the date is in the past or is more than ten years in the future.

Using more than one validation routine per field

You can use multiple validation routines like this:

VALUE="foo" VALIDATION="my_routine, my_other_routine"

However, there are some requirements on formatting to make sure that FormMagick can parse what you've given it.

  • Parens are optional on subroutines with no args. my_routine is equivalent to my_routine().

  • You MUST put a comma then a space between routine names, eg my_routine, my_other_routine NOT my_routine,my_other_routine.

  • You MUST NOT put a comma between args to a routine, eg my_routine(1,2,3) NOT my_routine(1, 2, 3).

This will be fixed to be more flexible in a later release.

Making your own routines

FormMagick's validation routines may be overridden and others may be added on a per-application basis. To do this, simply define a subroutine in your CGI script that works in a similar way to the routines provided by CGI::FormMagick::Validator and use its name in the VALIDATION attribute in your XML.

The arguments passed to the validation routine are the value of the field (to be validated) and any subsequent arguments given in the VALIDATION attribute. For example:

VALUE="foo" VALIDATION="my_routine"
===> my_routine(foo)

VALUE="foo" VALIDATION="my_routine(42)"
===> my_routine(foo, 42)

The latter type of validation routine is useful for routines like minlength() and lengthrange() which come with CGI::FormMagick::Validator.

Here's an example routine that you might write:

sub my_grep {
    my $data = shift;
    my @list = @_;
    if (grep /$data/, @list) {
        return "OK" 
    } else {
        return "That's not one of: @list"
    }
}

SECURITY CONSIDERATIONS AND METHODS FOR MANUAL VALIDATION

If you use page POST-EVENT or PRE-EVENT routines which perform code which is in any way based on user input, your application may be susceptible to a security exploit.

The exploit can occur as follows:

Imagine you have an application with three pages. Page 1 has fields A, B and C. Page 2 has fields D, E and F. Page 3 has fields G, H and I.

The user fills in page 1 and the data FOR THAT PAGE is validated before they're allowed to move on to page 2. When they fill in page 2, the data FOR THAT PAGE is validated before they can move on. Ditto for page 3.

If the user saves a copy of page 2 and edits it to contain an extra field, "A", with an invalid value, then submits that page back to FormMagick, the added field "A" will NOT be validated.

This is because FormMagick relies on the XML description of the page to know what fields to validate. Only the current page's fields are validated, until the very end when all the fields are revalidated one last time before the FORM POST-EVENT is run. This means that we don't suffer the load of validating everything every time, and it will work fine for most applications.

However, if you need to run PAGE POST-EVENT or PRE-EVENT routines that rely on previous pages' data, you should validate it manually in your POST-EVENT or PRE-EVENT routine. The following methods are used internally by FormMagick for its validation, but may also be useful to developers.

Note: this stuff may be buggy. Please let us know how you go with it.

$fm->validate_field($fieldname | $fieldref)

This routine allows you to validate a specific field by hand if you need to. It returns a string with the error message if validation fails, or the string "OK" on success.

Examples of use:

This is how you'd probably call it from your script:

if ($fm->validate_field("credit_card_number") eq "OK")) { }

FormMagick uses references to a field object, internally:

if ($fm->validate_field($fieldref) eq "OK")) { }

(that's so that FormMagick can easily loop through the fields in a page; you shouldn't need to do that)

$fm->validate_page($number | $name)

This routine allows you to validate a single page worth of fields. It can accept either a page number (counting naturally from one, NOT starting at zero), a page name, or a reference to a page object. You'll probably want to use the name or number; the page reference is used internally by FormMagick's validate_all() routine to loop through all the pages in the form.

This routine returns a hash of errors, with the keys being the names of fields which have errors and the values being the error messages. You can test for whether something's passed validation by testing for a true return value.

Examples: my %errors = $fm->validate_page(3); my %errors = $fm->validate_page("CreditCardDetails"); if (%errors) { ... }

$fm->validate_all()

This routine goes through all the pages that have been visited (using FormMagick's built-in page stack to keep track of which these are) and runs validate_page() on each of them.

Returns a hash of all errors, and set $self->{errors} when done.

DEVELOPER METHODS

The following methods are probably not of interest to anyone except developers of FormMagick

parse_validation_routine ($validation_routine_name)

parse the name of a validation routine into its name and its parameters. returns a 2-element list, $validator and $arg.

do_validation_routine ($self, $validator, $arg, $fielddata)

runs validation functions with arguments.

list_error_messages()

prints a list of error messages caused by validation failures

SEE ALSO

The main perldoc for CGI::FormMagick

AUTHOR

Kirrily "Skud" Robert <skud@infotrope.net>

More information about FormMagick may be found at http://sourceforge.net/projects/formmagick/