summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2008-10-23 20:37:15 +0200
committerYorhel <git@yorhel.nl>2008-10-23 20:37:15 +0200
commit4276f0c419350bf7209bbef9692fdc2d561fae21 (patch)
tree26816af658148a7d9bde70d46b8024cc8dcd073e /lib
parente4480ac65bb2d58bb0d4f10d3669bd9c3cb61149 (diff)
Wrote a form validator
This is basically a rewrite of VNDB::Util::Tools::FormCheck(), only way more readable, with better documentation, added functionality, and most likely less error-prone. I haven't actually tested the function yet, though, but I do know it compiles. Also, commenting code is very unlike me, what the hell is wrong with me!?
Diffstat (limited to 'lib')
-rw-r--r--lib/YAWF/Misc.pm99
1 files changed, 97 insertions, 2 deletions
diff --git a/lib/YAWF/Misc.pm b/lib/YAWF/Misc.pm
index c32f75c..89a0e04 100644
--- a/lib/YAWF/Misc.pm
+++ b/lib/YAWF/Misc.pm
@@ -1,10 +1,105 @@
package YAWF::Misc;
+# Yeah, just put all miscellaneous functions in one module!
+# Geez, talk about being sloppy...
-
+use strict;
+use warnings;
use Exporter 'import';
-our @EXPORT = ('mail');
+
+our @EXPORT = ('mail', 'formValidate');
+
+
+# Some pre-defined templates. It's possible to add templates at any time
+# and from any file by executing something like:
+# $YAWF::Misc::templates{templatename} = qr/regex/;
+our %templates = (
+ mail => qr/^[^@<>]+@[^@.<>]+(?:\.[^@.<>]+)+$/,
+ url => qr/^(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?$/,
+ asciiprint => qr/^[\x20-\x7E]*$/,
+ int => qr/^-?\d+$/,
+ pname => qr/^[a-z][a-z0-9-]*$/,
+);
+
+
+# Arguments: list of hashes representing a form item with validation rules
+# {
+# name => name of the form
+# multi => 0/1, multiple form fields with the same name (see below)
+# default => value to return if the field is left empty
+# required => 0/1, whether this field is required, defaults to 1
+# maxlength => maximum length of the field
+# minlength => minimum required length
+# enum => [ value must be present in a set list ]
+# template => one of the templates as defined in %templates
+# regex => [ qr/ regex /, "message for the user" ]
+# func => [ sub { external subroutine }, "message for the user" ]
+# }
+#
+# Returns a hash with form names as keys and their value as argument, and
+# a special key called '_err' in case there were errors. The value of this
+# hash item is an array of failed test cases, each represented as an array
+# with a list of: name of the field that failed validation and the rule on
+# which the validation failed (the key-value pair specified as argument)
+#
+# If the multi rule is specified, the returned value will be an arrayref
+# with the values of each item. If no fields were found with that name, the
+# arrayref will be empty. The validator will stop checking the other values
+# after one has failed.
+sub formValidate {
+ my($self, @fields) = @_;
+
+ my @err;
+ my %ret;
+
+ for my $f (@fields) {
+ my @values = $f->{multi} ? $self->reqParam($f->{name}) : ( scalar $self->reqParam($f->{name}) );
+ $values[0] = '' if !@values;
+ for (@values) {
+ my $valid = _validate($_, $f);
+ if(!ref $valid) {
+ $_ = $valid;
+ next;
+ }
+ push @err, [ $f->{name}, $$valid, $f->{$$valid} ];
+ last;
+ }
+ $ret{$f->{name}} = $f->{multi} ? \@values : $values[0];
+ }
+
+ $ret{_err} = \@err if @err;
+ return \%ret;
+}
+
+
+# Internal function used by formValidate, checks one value on the validation
+# rules, returns scalarref containing the failed rule on error, new value
+# otherwise
+sub _validate { # value, { rules }
+ my($v, $r) = @_;
+
+ # empty
+ if(!$v && length $v < 1 && $v ne '0') {
+ return \'required' if $r->{required};
+ return exists $r->{default} ? $r->{default} : undef;
+ }
+
+ # length
+ return \'minlength' if $r->{minlength} && length $v < $r->{minlength};
+ return \'maxlength' if $r->{maxlength} && length $v > $r->{maxlength};
+ # enum
+ return \'enum' if $r->{enum} && !grep $_ eq $v, @{$r->{enum}};
+ # template
+ return \'template' if $r->{template} && $v !~ /$templates{$r->{template}}/;
+ # regex
+ return \'regex' if $r->{regex} && $v !~ /$r->{regex}[0]/;
+ # function
+ return \'func' if $r->{func} && !$r->{func}[0]->($v);
+ # passed validation
+ return $v;
+}
+
# A simple mail function, body and headers as arguments. Usage: