# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # This Source Code Form is "Incompatible With Secondary Licenses", as # defined by the Mozilla Public License, v. 2.0. package Bugzilla::WebService::Server; use 5.10.1; use strict; use Bugzilla::Error; use Bugzilla::Util qw(datetime_from); use Scalar::Util qw(blessed); use Digest::MD5 qw(md5_base64); use Storable qw(freeze); sub handle_login { my ($self, $class, $method, $full_method) = @_; # Throw error if the supplied class does not exist or the method is private ThrowCodeError('unknown_method', {method => $full_method}) if (!$class or $method =~ /^_/); eval "require $class"; ThrowCodeError('unknown_method', {method => $full_method}) if $@; return if ($class->login_exempt($method) and !defined Bugzilla->input_params->{Bugzilla_login}); Bugzilla->login(); Bugzilla::Hook::process( 'webservice_before_call', { 'method' => $method, full_method => $full_method }); } sub datetime_format_inbound { my ($self, $time) = @_; my $converted = datetime_from($time, Bugzilla->local_timezone); if (!defined $converted) { ThrowUserError('illegal_date', { date => $time }); } $time = $converted->ymd() . ' ' . $converted->hms(); return $time } sub datetime_format_outbound { my ($self, $date) = @_; return undef if (!defined $date or $date eq ''); my $time = $date; if (blessed($date)) { # We expect this to mean we were sent a datetime object $time->set_time_zone('UTC'); } else { # We always send our time in UTC, for consistency. # passed in value is likely a string, create a datetime object $time = datetime_from($date, 'UTC'); } return $time->iso8601(); } # ETag support sub bz_etag { my ($self, $data) = @_; my $cache = Bugzilla->request_cache; if (defined $data) { # Serialize the data if passed a reference local $Storable::canonical = 1; $data = freeze($data) if ref $data; # Wide characters cause md5_base64() to die. utf8::encode($data) if utf8::is_utf8($data); # Append content_type to the end of the data # string as we want the etag to be unique to # the content_type. We do not need this for # XMLRPC as text/xml is always returned. if (blessed($self) && $self->can('content_type')) { $data .= $self->content_type if $self->content_type; } $cache->{'bz_etag'} = md5_base64($data); } return $cache->{'bz_etag'}; } 1; =head1 NAME Bugzilla::WebService::Server - Base server class for the WebService API =head1 DESCRIPTION Bugzilla::WebService::Server is the base class for the individual WebService API servers such as XMLRPC, JSONRPC, and REST. You never actually create a Bugzilla::WebService::Server directly, you only make subclasses of it. =head1 FUNCTIONS =over =item C This function is used to store an ETag value that will be used when returning the data by the different API server modules such as XMLRPC, or REST. The individual webservice methods can also set the value earlier in the process if needed such as before a unique update token is added. If a value is not set earlier, an etag will automatically be created using the returned data except in some cases when an error has occurred. =back =head1 SEE ALSO L, L, and L. =head1 B =over =item handle_login =item datetime_format_outbound =item datetime_format_inbound =back