summaryrefslogtreecommitdiff
path: root/util/vndb.pl
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2015-10-03 11:53:21 +0200
committerYorhel <git@yorhel.nl>2015-10-03 11:53:21 +0200
commit728c41ccab0463bbc70817d3baa8575d4006db70 (patch)
tree295df5376ebd8e655e913d49796365e85765d44f /util/vndb.pl
parentf81d7164cffa5067b25b941f1ab6498a8eb5bfb0 (diff)
formValidate: Add json_(maxitems|unique|sort) options to json template
Adds slightly more strict validation and simplifies further processing.
Diffstat (limited to 'util/vndb.pl')
-rwxr-xr-xutil/vndb.pl48
1 files changed, 46 insertions, 2 deletions
diff --git a/util/vndb.pl b/util/vndb.pl
index 3ca6604f..99f15367 100755
--- a/util/vndb.pl
+++ b/util/vndb.pl
@@ -17,7 +17,7 @@ use lib $ROOT.'/lib';
use TUWF ':html', 'kv_validate';
use VNDB::L10N;
-use VNDB::Func 'json_encode', 'json_decode';
+use VNDB::Func 'json_decode';
use VNDBUtil 'gtintype';
use SkinFile;
@@ -55,7 +55,7 @@ TUWF::set(
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'], default => [] },
+ json => { func => \&json_validate, inherit => ['json_fields','json_maxitems','json_unique','json_sort'], default => [] },
},
);
TUWF::load_recursive('VNDB::Util', 'VNDB::DB', 'VNDB::Handler');
@@ -134,22 +134,66 @@ sub logformat {
}
+# 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;
}