diff options
Diffstat (limited to 'Bugzilla/WebService.pm')
-rwxr-xr-x | Bugzilla/WebService.pm | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/Bugzilla/WebService.pm b/Bugzilla/WebService.pm index 615abf68c..3152ef04f 100755 --- a/Bugzilla/WebService.pm +++ b/Bugzilla/WebService.pm @@ -97,6 +97,7 @@ sub initialize { my $self = shift; my %retval = $self->SUPER::initialize(@_); $retval{'serializer'} = Bugzilla::WebService::XMLRPC::Serializer->new; + $retval{'deserializer'} = Bugzilla::WebService::XMLRPC::Deserializer->new; return %retval; } @@ -114,6 +115,74 @@ sub make_response { 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. # See http://rt.cpan.org/Public/Bug/Display.html?id=32952. package Bugzilla::WebService::XMLRPC::Serializer; @@ -356,3 +425,20 @@ would return something like: =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 |