Commit 9b0a78fb authored by mkanat%bugzilla.org's avatar mkanat%bugzilla.org

Bug 471942: Make the WebService validate and properly convert input parameters

Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=dkl, a=mkanat
parent 6c6de869
...@@ -97,6 +97,7 @@ sub initialize { ...@@ -97,6 +97,7 @@ sub initialize {
my $self = shift; my $self = shift;
my %retval = $self->SUPER::initialize(@_); my %retval = $self->SUPER::initialize(@_);
$retval{'serializer'} = Bugzilla::WebService::XMLRPC::Serializer->new; $retval{'serializer'} = Bugzilla::WebService::XMLRPC::Serializer->new;
$retval{'deserializer'} = Bugzilla::WebService::XMLRPC::Deserializer->new;
return %retval; return %retval;
} }
...@@ -114,6 +115,74 @@ sub make_response { ...@@ -114,6 +115,74 @@ sub make_response {
1; 1;
# This exists to validate input parameters (which XMLRPC::Lite doesn't do)
# and also, in some cases, to more-usefully decode them.
package Bugzilla::WebService::XMLRPC::Deserializer;
use strict;
# We can't use "use base" because XMLRPC::Serializer doesn't return
# a true value.
eval { require XMLRPC::Lite; };
our @ISA = qw(XMLRPC::Deserializer);
use Bugzilla::Error;
# Some method arguments need to be converted in some way, when they are input.
sub decode_value {
my $self = shift;
my ($type) = @{ $_[0] };
my $value = $self->SUPER::decode_value(@_);
# We only validate/convert certain types here.
return $value if $type !~ /^(?:int|i4|boolean|double|dateTime\.iso8601)$/;
# Though the XML-RPC standard doesn't allow an empty <int>,
# <double>,or <dateTime.iso8601>, we do, and we just say
# "that's undef".
if (grep($type eq $_, qw(int double dateTime))) {
return undef if $value eq '';
}
my $validator = $self->_validation_subs->{$type};
if (!$validator->($value)) {
ThrowUserError('xmlrpc_invalid_value',
{ type => $type, value => $value });
}
# We convert dateTimes to a DB-friendly date format.
if ($type eq 'dateTime.iso8601') {
# We leave off the $ from the end of this regex to allow for possible
# extensions to the XML-RPC date standard.
$value =~ /^(\d{4})(\d{2})(\d{2})T(\d{2}):(\d{2}):(\d{2})/;
$value = "$1-$2-$3 $4:$5:$6";
}
return $value;
}
sub _validation_subs {
my $self = shift;
return $self->{_validation_subs} if $self->{_validation_subs};
# The only place that XMLRPC::Lite stores any sort of validation
# regex is in XMLRPC::Serializer. We want to re-use those regexes here.
my $lookup = Bugzilla::WebService::XMLRPC::Serializer->new->typelookup;
# $lookup is a hash whose values are arrayrefs, and whose keys are the
# names of types. The second item of each arrayref is a subroutine
# that will do our validation for us.
my %validators = map { $_ => $lookup->{$_}->[1] } (keys %$lookup);
# Add a boolean validator
$validators{'boolean'} = sub {$_[0] =~ /^[01]$/};
# Some types have multiple names, or have a different name in
# XMLRPC::Serializer than their standard XML-RPC name.
$validators{'dateTime.iso8601'} = $validators{'dateTime'};
$validators{'i4'} = $validators{'int'};
$self->{_validation_subs} = \%validators;
return \%validators;
}
1;
# This package exists to fix a UTF-8 bug in SOAP::Lite. # This package exists to fix a UTF-8 bug in SOAP::Lite.
# See http://rt.cpan.org/Public/Bug/Display.html?id=32952. # See http://rt.cpan.org/Public/Bug/Display.html?id=32952.
package Bugzilla::WebService::XMLRPC::Serializer; package Bugzilla::WebService::XMLRPC::Serializer;
...@@ -356,3 +425,20 @@ would return something like: ...@@ -356,3 +425,20 @@ would return something like:
=back =back
=head1 EXTENSIONS TO THE XML-RPC STANDARD
=head2 Undefined Values
Normally, XML-RPC does not allow empty values for C<int>, C<double>, or
C<dateTime.iso8601> fields. Bugzilla does--it treats empty values as
C<undef> (called C<NULL> or C<None> in some programming languages).
Bugzilla also accepts a type called C<< <nil> >>, which is always considered
to be C<undef>, no matter what it contains.
=begin private
nil is implemented by XMLRPC::Lite, in XMLRPC::Deserializer::decode_value.
=end private
...@@ -48,11 +48,12 @@ use base qw(Exporter); ...@@ -48,11 +48,12 @@ use base qw(Exporter);
# comment that it was retired. Also, if an error changes its name, you'll # comment that it was retired. Also, if an error changes its name, you'll
# have to fix it here. # have to fix it here.
use constant WS_ERROR_CODE => { use constant WS_ERROR_CODE => {
# Generic Bugzilla::Object errors are 50-99. # Generic errors (Bugzilla::Object and others) are 50-99.
object_not_specified => 50, object_not_specified => 50,
param_required => 50, param_required => 50,
params_required => 50, params_required => 50,
object_does_not_exist => 51, object_does_not_exist => 51,
xmlrpc_invalid_value => 52,
# Bug errors usually occupy the 100-200 range. # Bug errors usually occupy the 100-200 range.
improper_bug_id_field_value => 100, improper_bug_id_field_value => 100,
bug_id_does_not_exist => 101, bug_id_does_not_exist => 101,
......
...@@ -1618,6 +1618,11 @@ ...@@ -1618,6 +1618,11 @@
[% title = "Wrong Token" %] [% title = "Wrong Token" %]
That token cannot be used to create a user account. That token cannot be used to create a user account.
[% ELSIF error == "xmlrpc_invalid_value" %]
"[% value FILTER html %]" is not a valid value for a
&lt;[% type FILTER html %]&gt; field. (See the XML-RPC specification
for details.)
[% ELSIF error == "zero_length_file" %] [% ELSIF error == "zero_length_file" %]
[% title = "File Is Empty" %] [% title = "File Is Empty" %]
The file you are trying to attach is empty, does not exist, or you don't The file you are trying to attach is empty, does not exist, or you don't
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment