summaryrefslogtreecommitdiffstats
path: root/Bugzilla/WebService.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/WebService.pm')
-rwxr-xr-xBugzilla/WebService.pm86
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