diff options
-rw-r--r-- | lib/VNDB/DB/Staff.pm | 11 | ||||
-rw-r--r-- | lib/VNDB/Func.pm | 30 | ||||
-rw-r--r-- | lib/VNDB/Handler/Staff.pm | 28 |
3 files changed, 44 insertions, 25 deletions
diff --git a/lib/VNDB/DB/Staff.pm b/lib/VNDB/DB/Staff.pm index 1b9a10da..4dfe0756 100644 --- a/lib/VNDB/DB/Staff.pm +++ b/lib/VNDB/DB/Staff.pm @@ -126,7 +126,7 @@ sub dbStaffRevisionInsert { my($self, $o) = @_; $self->dbExec('DELETE FROM edit_staff_aliases'); - if ($o->{aid}) { + if($o->{aid}) { $self->dbExec(q| INSERT INTO edit_staff_aliases (id, name, original) VALUES (?, ?, ?)|, $o->{aid}, $o->{name}, $o->{original}); @@ -139,12 +139,11 @@ sub dbStaffRevisionInsert { my %staff = map exists($o->{$_}) ? (qq|"$_" = ?|, $o->{$_}) : (), qw|aid gender lang desc l_wp l_site l_twitter l_anidb|; $self->dbExec('UPDATE edit_staff !H', \%staff) if %staff; - for my $alias (@{$o->{aliases}}) { - if ($alias->[0]) { - $self->dbExec('INSERT INTO edit_staff_aliases (id, name, original) VALUES (!l)', $alias); + for my $a (@{$o->{aliases}}) { + if($a->{aid}) { + $self->dbExec('INSERT INTO edit_staff_aliases (id, name, original) VALUES (!l)', [ @{$a}{qw|aid name orig|} ]); } else { - $self->dbExec('INSERT INTO edit_staff_aliases (name, original) VALUES (?, ?)', - $alias->[1], $alias->[2]); + $self->dbExec('INSERT INTO edit_staff_aliases (name, original) VALUES (?, ?)', $a->{name}, $a->{orig}); } } } diff --git a/lib/VNDB/Func.pm b/lib/VNDB/Func.pm index ac9fdd58..dd3f292e 100644 --- a/lib/VNDB/Func.pm +++ b/lib/VNDB/Func.pm @@ -3,7 +3,7 @@ package VNDB::Func; use strict; use warnings; -use TUWF ':html'; +use TUWF ':html', 'kv_validate'; use Exporter 'import'; use POSIX 'strftime', 'ceil', 'floor'; use JSON::XS; @@ -11,7 +11,7 @@ use VNDBUtil; our @EXPORT = (@VNDBUtil::EXPORT, qw| clearfloat cssicon tagscore mt minage fil_parse fil_serialize parenttags childtags charspoil imgpath imgurl fmtvote - jsonEncode jsonDecode script_json + jsonEncode jsonDecode script_json json_validate mtvoiced mtani mtvnlen mtrlstat mtvnlstat mtbloodt |); @@ -228,6 +228,32 @@ sub script_json { } +# 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. +# Returns the parsed json object on success, undef on error and sets $frm->{_err}. +# Doesn't provide a user-friendly error message if validation fails. It's the +# responsibility of the JS code to handle the interface with the user. +sub json_validate { + my($frm, $name, @fields) = @_; + my $data = eval { jsonDecode $frm->{$name} }; + goto error if $@ || ref $data ne 'ARRAY'; + my %known_fields = map +($_->{field},1), @fields; + for my $i (0..$#$data) { + goto error if ref $data->[$i] ne 'HASH'; + # Require that all keys are known and have a scalar value. + goto error 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); + goto error if $data->[$i]{_err}; + } + + return $data; +error: + push @{$frm->{_err}}, [ 'aliases', 'template', 'json' ] ; + return undef; +} + + # mt() wrappers for data-dependent translation strings that have a special # value for 'unknown'. sub mtvoiced { !$_[0] ? mt '_unknown' : mt '_voiced_'.$_[0]; } diff --git a/lib/VNDB/Handler/Staff.pm b/lib/VNDB/Handler/Staff.pm index 3c8fd7af..2840442b 100644 --- a/lib/VNDB/Handler/Staff.pm +++ b/lib/VNDB/Handler/Staff.pm @@ -215,29 +215,23 @@ sub edit { { post => 'ilock', required => 0 }, ); push @{$frm->{_err}}, 'badeditsum' if !$frm->{editsum} || lc($frm->{editsum}) eq lc($frm->{desc}); + my $aliases = json_validate($frm, 'aliases', + { field => 'name', required => 1, maxlength => 200 }, + { field => 'orig', required => 0, maxlength => 200, default => '' }, + { field => 'aid', required => 0, template => 'int', default => 0 }, + ); - my @aliases; - my $raw_a = eval { jsonDecode $frm->{aliases} }; - push @{$frm->{_err}}, [ 'aliases', 'template', 'json' ] if $@ || ref $raw_a ne 'ARRAY'; if(!$frm->{_err}) { + $aliases = [ sort { $a->{name} cmp $b->{name} } @$aliases ]; my %old_aliases = $sid ? ( map +($_->{id} => 1), @{$self->dbStaffAliasIds($sid)} ) : (); $frm->{primary} = 0 unless exists $old_aliases{$frm->{primary}}; - for my $a (sort { $a->{name} cmp $b->{name} } @$raw_a) { - # check for empty aliases - if($a->{name} =~ /^\s*$/) { - push @{$frm->{_err}}, ['alias_name', 'required']; - last; - } - s/^\s+|\s+$//g for ($a->{name}, $a->{orig}); - # normalize alias id to a number so that the comparison works - # or reset it to zero for newly added aliases. - $a->{aid} *= $old_aliases{$a->{aid}} ? 1 : 0; - push @aliases, $a; - } + # normalize alias id to a number so that the comparison works + # or reset it to zero for newly added aliases. + $_->{aid} *= $old_aliases{$_->{aid}} ? 1 : 0 for (sort { $a->{name} cmp $b->{name} } @$aliases); } if(!$frm->{_err}) { - $frm->{aliases} = jsonEncode \@aliases; + $frm->{aliases} = jsonEncode $aliases; $frm->{ihid} = $frm->{ihid} ?1:0; $frm->{ilock} = $frm->{ilock}?1:0; $frm->{aid} = $frm->{primary} if $sid; @@ -246,7 +240,7 @@ sub edit { return $self->resRedirect("/s$sid", 'post') if $sid && !first { ($frm->{$_}//'') ne ($b4{$_}//'') } keys %b4; - $frm->{aliases} = [ map [ @{$_}{qw|aid name orig|} ], @aliases ]; + $frm->{aliases} = $aliases; my $nrev = $self->dbItemEdit ('s' => $sid ? $s->{cid} : undef, %$frm); return $self->resRedirect("/s$nrev->{iid}.$nrev->{rev}", 'post'); } |