aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/WebService/Server/XMLRPC.pm')
-rw-r--r--Bugzilla/WebService/Server/XMLRPC.pm92
1 files changed, 79 insertions, 13 deletions
diff --git a/Bugzilla/WebService/Server/XMLRPC.pm b/Bugzilla/WebService/Server/XMLRPC.pm
index 5f9cb4515..98a0ee405 100644
--- a/Bugzilla/WebService/Server/XMLRPC.pm
+++ b/Bugzilla/WebService/Server/XMLRPC.pm
@@ -7,7 +7,10 @@
package Bugzilla::WebService::Server::XMLRPC;
+use 5.10.1;
use strict;
+use warnings;
+
use XMLRPC::Transport::HTTP;
use Bugzilla::WebService::Server;
if ($ENV{MOD_PERL}) {
@@ -18,11 +21,12 @@ if ($ENV{MOD_PERL}) {
use Bugzilla::WebService::Constants;
use Bugzilla::Error;
+use Bugzilla::Util;
use List::MoreUtils qw(none);
-# Allow WebService methods to call XMLRPC::Lite's type method directly
BEGIN {
+ # Allow WebService methods to call XMLRPC::Lite's type method directly
*Bugzilla::WebService::type = sub {
my ($self, $type, $value) = @_;
if ($type eq 'dateTime') {
@@ -31,8 +35,19 @@ BEGIN {
$value = Bugzilla::WebService::Server->datetime_format_outbound($value);
$value =~ s/-//g;
}
+ elsif ($type eq 'email') {
+ $type = 'string';
+ if (Bugzilla->params->{'webservice_email_filter'}) {
+ $value = email_filter($value);
+ }
+ }
return XMLRPC::Data->type($type)->value($value);
};
+
+ # Add support for ETags into XMLRPC WebServices
+ *Bugzilla::WebService::bz_etag = sub {
+ return Bugzilla::WebService::Server->bz_etag($_[1]);
+ };
}
sub initialize {
@@ -46,22 +61,38 @@ sub initialize {
sub make_response {
my $self = shift;
+ my $cgi = Bugzilla->cgi;
$self->SUPER::make_response(@_);
# XMLRPC::Transport::HTTP::CGI doesn't know about Bugzilla carrying around
# its cookies in Bugzilla::CGI, so we need to copy them over.
- foreach my $cookie (@{Bugzilla->cgi->{'Bugzilla_cookie_list'}}) {
+ foreach my $cookie (@{$cgi->{'Bugzilla_cookie_list'}}) {
$self->response->headers->push_header('Set-Cookie', $cookie);
}
# Copy across security related headers from Bugzilla::CGI
- foreach my $header (split(/[\r\n]+/, Bugzilla->cgi->header)) {
+ foreach my $header (split(/[\r\n]+/, $cgi->header)) {
my ($name, $value) = $header =~ /^([^:]+): (.*)/;
if (!$self->response->headers->header($name)) {
$self->response->headers->header($name => $value);
}
}
+
+ # ETag support
+ my $etag = $self->bz_etag;
+ if (!$etag) {
+ my $data = $self->response->as_string;
+ $etag = $self->bz_etag($data);
+ }
+
+ if ($etag && $cgi->check_etag($etag)) {
+ $self->response->headers->push_header('ETag', $etag);
+ $self->response->headers->push_header('status', '304 Not Modified');
+ }
+ elsif ($etag) {
+ $self->response->headers->push_header('ETag', $etag);
+ }
}
sub handle_login {
@@ -85,8 +116,12 @@ sub handle_login {
# This exists to validate input parameters (which XMLRPC::Lite doesn't do)
# and also, in some cases, to more-usefully decode them.
package Bugzilla::XMLRPC::Deserializer;
+
+use 5.10.1;
use strict;
-# We can't use "use base" because XMLRPC::Serializer doesn't return
+use warnings;
+
+# We can't use "use parent" because XMLRPC::Serializer doesn't return
# a true value.
use XMLRPC::Lite;
our @ISA = qw(XMLRPC::Deserializer);
@@ -96,6 +131,15 @@ use Bugzilla::WebService::Constants qw(XMLRPC_CONTENT_TYPE_WHITELIST);
use Bugzilla::WebService::Util qw(fix_credentials);
use Scalar::Util qw(tainted);
+sub new {
+ my $self = shift->SUPER::new(@_);
+ # Initialise XML::Parser to not expand references to entities, to prevent DoS
+ require XML::Parser;
+ my $parser = XML::Parser->new( NoExpand => 1, Handlers => { Default => sub {} } );
+ $self->{_parser}->parser($parser, $parser);
+ return $self;
+}
+
sub deserialize {
my $self = shift;
@@ -123,6 +167,7 @@ sub deserialize {
fix_credentials($params);
Bugzilla->input_params($params);
+
return $som;
}
@@ -186,7 +231,11 @@ sub _validation_subs {
1;
package Bugzilla::XMLRPC::SOM;
+
+use 5.10.1;
use strict;
+use warnings;
+
use XMLRPC::Lite;
our @ISA = qw(XMLRPC::SOM);
use Bugzilla::WebService::Util qw(taint_data);
@@ -209,9 +258,13 @@ sub paramsin {
# 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::XMLRPC::Serializer;
-use Scalar::Util qw(blessed);
+
+use 5.10.1;
use strict;
-# We can't use "use base" because XMLRPC::Serializer doesn't return
+use warnings;
+
+use Scalar::Util qw(blessed reftype);
+# We can't use "use parent" because XMLRPC::Serializer doesn't return
# a true value.
use XMLRPC::Lite;
our @ISA = qw(XMLRPC::Serializer);
@@ -244,8 +297,8 @@ sub envelope {
my $self = shift;
my ($type, $method, $data) = @_;
# If the type isn't a successful response we don't want to change the values.
- if ($type eq 'response'){
- $data = _strip_undefs($data);
+ if ($type eq 'response') {
+ _strip_undefs($data);
}
return $self->SUPER::envelope($type, $method, $data);
}
@@ -256,7 +309,9 @@ sub envelope {
# so it cannot be recursed like the other hash type objects.
sub _strip_undefs {
my ($initial) = @_;
- if (ref $initial eq "HASH" || (blessed $initial && $initial->isa("HASH"))) {
+ my $type = reftype($initial) or return;
+
+ if ($type eq "HASH") {
while (my ($key, $value) = each(%$initial)) {
if ( !defined $value
|| (blessed $value && $value->isa('XMLRPC::Data') && !defined $value->value) )
@@ -265,11 +320,11 @@ sub _strip_undefs {
delete $initial->{$key};
}
else {
- $initial->{$key} = _strip_undefs($value);
+ _strip_undefs($value);
}
}
}
- if (ref $initial eq "ARRAY" || (blessed $initial && $initial->isa("ARRAY"))) {
+ elsif ($type eq "ARRAY") {
for (my $count = 0; $count < scalar @{$initial}; $count++) {
my $value = $initial->[$count];
if ( !defined $value
@@ -280,11 +335,10 @@ sub _strip_undefs {
$count--;
}
else {
- $initial->[$count] = _strip_undefs($value);
+ _strip_undefs($value);
}
}
}
- return $initial;
}
sub BEGIN {
@@ -386,3 +440,15 @@ perl-SOAP-Lite package in versions 0.68-1 and above.
=head1 SEE ALSO
L<Bugzilla::WebService>
+
+=head1 B<Methods in need of POD>
+
+=over
+
+=item make_response
+
+=item initialize
+
+=item handle_login
+
+=back