summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/VNDB/Handler/Releases.pm2
-rw-r--r--lib/VNDB/Util/FormHTML.pm1
-rw-r--r--lib/VNDB/Util/ValidateTemplates.pm102
-rwxr-xr-xutil/vndb.pl75
4 files changed, 104 insertions, 76 deletions
diff --git a/lib/VNDB/Handler/Releases.pm b/lib/VNDB/Handler/Releases.pm
index 7271541e..62ba0c5a 100644
--- a/lib/VNDB/Handler/Releases.pm
+++ b/lib/VNDB/Handler/Releases.pm
@@ -305,7 +305,7 @@ sub edit {
{ post => 'catalog', required => 0, default => '', maxlength => 50 },
{ post => 'languages', multi => 1, enum => [ keys %{$self->{languages}} ] },
{ post => 'website', required => 0, default => '', maxlength => 250, template => 'weburl' },
- { post => 'released', required => 0, default => 0, template => 'uint' },
+ { post => 'released', required => 0, default => 0, template => 'rdate' },
{ post => 'minage' , required => 0, default => -1, enum => $self->{age_ratings} },
{ post => 'notes', required => 0, default => '', maxlength => 10240 },
{ post => 'platforms', required => 0, default => '', multi => 1, enum => [ keys %{$self->{platforms}} ] },
diff --git a/lib/VNDB/Util/FormHTML.pm b/lib/VNDB/Util/FormHTML.pm
index 51d5a4f6..a522599e 100644
--- a/lib/VNDB/Util/FormHTML.pm
+++ b/lib/VNDB/Util/FormHTML.pm
@@ -52,6 +52,7 @@ sub htmlFormError {
li "$field may only contain lowercase alphanumeric characters and a hyphen" if $rule eq 'uname';
li 'Invalid JAN/UPC/EAN' if $rule eq 'gtin';
li "$field: Malformed data or invalid input" if $rule eq 'json';
+ li 'Invalid release date' if $rule eq 'rdate';
if($rule eq 'editsum') {
li; lit 'Please read <a href="/d5.4">the guidelines</a> on how to use the edit summary.'; end;
}
diff --git a/lib/VNDB/Util/ValidateTemplates.pm b/lib/VNDB/Util/ValidateTemplates.pm
new file mode 100644
index 00000000..c92ac12b
--- /dev/null
+++ b/lib/VNDB/Util/ValidateTemplates.pm
@@ -0,0 +1,102 @@
+# This module implements various templates for formValidate()
+
+package VNDB::Util::ValidateTemplates;
+
+use strict;
+use warnings;
+use VNDB::Func 'json_decode';
+use VNDBUtil 'gtintype';
+use Time::Local 'timegm';
+
+
+TUWF::set(
+ validate_templates => {
+ id => { template => 'uint', max => 1<<40 },
+ page => { template => 'uint', max => 1000 },
+ uname => { regex => qr/^[a-z0-9-]*$/, minlength => 2, maxlength => 15 },
+ gtin => { func => \&gtintype },
+ editsum => { maxlength => 5000, minlength => 2 },
+ json => { func => \&json_validate, inherit => ['json_fields','json_maxitems','json_unique','json_sort'], default => [] },
+ rdate => { template => 'uint', min => 0, max => 99999999, func => \&rdate_validate, default => 0 },
+ }
+);
+
+
+# Figure out if a field is treated as a number in kv_validate().
+sub json_validate_is_num {
+ my $opts = shift;
+ return 0 if !$opts->{template};
+ return 1 if $opts->{template} eq 'num' || $opts->{template} eq 'int' || $opts->{template} eq 'uint';
+ my $t = TUWF::set('validate_templates')->{$opts->{template}};
+ return $t && json_validate_is_num($t);
+}
+
+
+sub json_validate_sort {
+ my($sort, $fields, $data) = @_;
+
+ # Figure out which fields need to use number comparison
+ my %nums;
+ for my $k (@$sort) {
+ my $f = (grep $_->{field} eq $k, @$fields)[0];
+ $nums{$k}++ if json_validate_is_num($f);
+ }
+
+ # Sort
+ return [sort {
+ for(@$sort) {
+ my $r = $nums{$_} ? $a->{$_} <=> $b->{$_} : $a->{$_} cmp $b->{$_};
+ return $r if $r;
+ }
+ 0
+ } @$data];
+}
+
+# Special validation function for simple JSON structures as form fields. It can
+# only validate arrays of key-value objects. The key-value objects are then
+# validated using kv_validate.
+# TODO: json_unique implies json_sort on the same fields? These options tend to be the same.
+sub json_validate {
+ my($val, $opts) = @_;
+ my $fields = $opts->{json_fields};
+ my $maxitems = $opts->{json_maxitems};
+ my $unique = $opts->{json_unique};
+ my $sort = $opts->{json_sort};
+ $unique = [$unique] if $unique && !ref $unique;
+ $sort = [$sort] if $sort && !ref $sort;
+
+ my $data = eval { json_decode $val };
+ $_[0] = $@ ? [] : $data;
+ return 0 if $@ || ref $data ne 'ARRAY';
+ return 0 if defined($maxitems) && @$data > $maxitems;
+
+ my %known_fields = map +($_->{field},1), @$fields;
+ my %unique;
+
+ for my $i (0..$#$data) {
+ return 0 if ref $data->[$i] ne 'HASH';
+ # Require that all keys are known and have a scalar value.
+ return 0 if grep !$known_fields{$_} || ref($data->[$i]{$_}), keys %{$data->[$i]};
+ $data->[$i] = kv_validate({ field => sub { $data->[$i]{shift()} } }, $TUWF::OBJ->{_TUWF}{validate_templates}, $fields);
+ return 0 if $data->[$i]{_err};
+ return 0 if $unique && $unique{ join '|||', map $data->[$i]{$_}, @$unique }++;
+ }
+
+ $_[0] = json_validate_sort($sort, $fields, $data) if $sort;
+ return 1;
+}
+
+
+sub rdate_validate {
+ return 0 if $_[0] ne 0 && $_[0] !~ /^(\d{4})(\d{2})(\d{2})$/;
+ my($y, $m, $d) = defined $1 ? ($1, $2, $3) : (0,0,0);
+
+ # Normalization ought to be done in JS, but do it here again because we can't trust browsers
+ ($m, $d) = (0, 0) if $y == 0;
+ $m = 99 if $y == 9999;
+ $d = 99 if $m == 99;
+ $_[0] = $y*10000 + $m*100 + $d;
+
+ return 0 if $y && $d != 99 && !eval { timegm(0, 0, 0, $d, $m-1, $y) };
+ return 1;
+}
diff --git a/util/vndb.pl b/util/vndb.pl
index dfb78afa..51ade736 100755
--- a/util/vndb.pl
+++ b/util/vndb.pl
@@ -16,8 +16,6 @@ use lib $ROOT.'/lib';
use TUWF ':html', 'kv_validate';
-use VNDB::Func 'json_decode';
-use VNDBUtil 'gtintype';
use SkinFile;
@@ -44,14 +42,6 @@ TUWF::set(
pre_request_handler => \&reqinit,
error_404_handler => \&handle404,
log_format => \&logformat,
- validate_templates => {
- id => { template => 'uint', max => 1<<40 },
- page => { template => 'uint', max => 1000 },
- uname => { regex => qr/^[a-z0-9-]*$/, minlength => 2, maxlength => 15 },
- gtin => { func => \&gtintype },
- editsum => { maxlength => 5000, minlength => 2 },
- json => { func => \&json_validate, inherit => ['json_fields','json_maxitems','json_unique','json_sort'], default => [] },
- },
);
TUWF::load_recursive('VNDB::Util', 'VNDB::DB', 'VNDB::Handler');
TUWF::run();
@@ -96,68 +86,3 @@ sub logformat {
sprintf "[%s] %s %s: %s\n", scalar localtime(), $uri,
$self->authInfo->{id} ? 'u'.$self->authInfo->{id} : '-', $msg;
}
-
-
-# Figure out if a field is treated as a number in kv_validate().
-sub json_validate_is_num {
- my $opts = shift;
- return 0 if !$opts->{template};
- return 1 if $opts->{template} eq 'num' || $opts->{template} eq 'int' || $opts->{template} eq 'uint';
- my $t = TUWF::set('validate_templates')->{$opts->{template}};
- return $t && json_validate_is_num($t);
-}
-
-
-sub json_validate_sort {
- my($sort, $fields, $data) = @_;
-
- # Figure out which fields need to use number comparison
- my %nums;
- for my $k (@$sort) {
- my $f = (grep $_->{field} eq $k, @$fields)[0];
- $nums{$k}++ if json_validate_is_num($f);
- }
-
- # Sort
- return [sort {
- for(@$sort) {
- my $r = $nums{$_} ? $a->{$_} <=> $b->{$_} : $a->{$_} cmp $b->{$_};
- return $r if $r;
- }
- 0
- } @$data];
-}
-
-# Special validation function for simple JSON structures as form fields. It can
-# only validate arrays of key-value objects. The key-value objects are then
-# validated using kv_validate.
-# TODO: json_unique implies json_sort on the same fields? These options tend to be the same.
-sub json_validate {
- my($val, $opts) = @_;
- my $fields = $opts->{json_fields};
- my $maxitems = $opts->{json_maxitems};
- my $unique = $opts->{json_unique};
- my $sort = $opts->{json_sort};
- $unique = [$unique] if $unique && !ref $unique;
- $sort = [$sort] if $sort && !ref $sort;
-
- my $data = eval { json_decode $val };
- $_[0] = $@ ? [] : $data;
- return 0 if $@ || ref $data ne 'ARRAY';
- return 0 if defined($maxitems) && @$data > $maxitems;
-
- my %known_fields = map +($_->{field},1), @$fields;
- my %unique;
-
- for my $i (0..$#$data) {
- return 0 if ref $data->[$i] ne 'HASH';
- # Require that all keys are known and have a scalar value.
- return 0 if grep !$known_fields{$_} || ref($data->[$i]{$_}), keys %{$data->[$i]};
- $data->[$i] = kv_validate({ field => sub { $data->[$i]{shift()} } }, $TUWF::OBJ->{_TUWF}{validate_templates}, $fields);
- return 0 if $data->[$i]{_err};
- return 0 if $unique && $unique{ join '|||', map $data->[$i]{$_}, @$unique }++;
- }
-
- $_[0] = json_validate_sort($sort, $fields, $data) if $sort;
- return 1;
-}