Commit 0ee4621e authored by wurblzap%gmail.com's avatar wurblzap%gmail.com

Bug 224577: Bugzilla could use a web services interface.

Patch by Marc Schumann <wurblzap@gmail.com>; r=mkanat; a=myk
parent 79c7d0e9
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
# Contributor(s): Bradley Baetz <bbaetz@student.usyd.edu.au> # Contributor(s): Bradley Baetz <bbaetz@student.usyd.edu.au>
# Erik Stambaugh <erik@dasbistro.com> # Erik Stambaugh <erik@dasbistro.com>
# A. Karl Kornel <karl@kornel.name> # A. Karl Kornel <karl@kornel.name>
# Marc Schumann <wurblzap@gmail.com>
package Bugzilla; package Bugzilla;
...@@ -263,13 +264,37 @@ sub dbh { ...@@ -263,13 +264,37 @@ sub dbh {
return request_cache()->{dbh}; return request_cache()->{dbh};
} }
sub batch { sub error_mode {
my $class = shift; my $class = shift;
my $newval = shift; my $newval = shift;
if (defined $newval) { if (defined $newval) {
request_cache()->{batch} = $newval; request_cache()->{error_mode} = $newval;
} }
return request_cache()->{batch} || 0; return request_cache()->{error_mode}
|| Bugzilla::Constants::ERROR_MODE_WEBPAGE;
}
sub usage_mode {
my $class = shift;
my $newval = shift;
if (defined $newval) {
if ($newval == USAGE_MODE_BROWSER) {
$class->error_mode(ERROR_MODE_WEBPAGE);
}
elsif ($newval == USAGE_MODE_CMDLINE) {
$class->error_mode(ERROR_MODE_DIE);
}
elsif ($newval == USAGE_MODE_WEBSERVICE) {
$class->error_mode(ERROR_MODE_DIE_SOAP_FAULT);
}
else {
ThrowCodeError('usage_mode_invalid',
{'invalid_usage_mode', $newval});
}
request_cache()->{usage_mode} = $newval;
}
return request_cache()->{usage_mode}
|| Bugzilla::Constants::USAGE_MODE_BROWSER;
} }
sub switch_to_shadow_db { sub switch_to_shadow_db {
...@@ -477,12 +502,35 @@ Essentially, causes calls to C<Bugzilla-E<gt>user> to return C<undef>. This has ...@@ -477,12 +502,35 @@ Essentially, causes calls to C<Bugzilla-E<gt>user> to return C<undef>. This has
effect of logging out a user for the current request only; cookies and effect of logging out a user for the current request only; cookies and
database sessions are left intact. database sessions are left intact.
=item C<batch> =item C<error_mode>
Call either C<Bugzilla->error_mode(Bugzilla::Constants::ERROR_MODE_DIE)>
or C<Bugzilla->error_mode(Bugzilla::Constants::ERROR_MODE_DIE_SOAP_FAULT)> to
change this flag's default of C<Bugzilla::Constants::ERROR_MODE_WEBPAGE> and to
indicate that errors should be passed to error mode specific error handlers
rather than being sent to a browser and finished with an exit().
This is useful, for example, to keep C<eval> blocks from producing wild HTML
on errors, making it easier for you to catch them.
(Remember to reset the error mode to its previous value afterwards, though.)
C<Bugzilla->error_mode> will return the current state of this flag.
Note that C<Bugzilla->error_mode> is being called by C<Bugzilla->usage_mode> on
usage mode changes.
=item C<usage_mode>
Call either C<Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_CMDLINE)>
or C<Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_WEBSERVICE)> near the
beginning of your script to change this flag's default of
C<Bugzilla::Constants::USAGE_MODE_BROWSER> and to indicate that Bugzilla is
being called in a non-interactive manner.
This influences error handling because on usage mode changes, C<usage_mode>
calls C<Bugzilla->error_mode> to set an error mode which makes sense for the
usage mode.
Set to true, by calling Bugzilla->batch(1), to indicate that Bugzilla is C<Bugzilla->usage_mode> will return the current state of this flag.
being called in a non-interactive manner and errors should be passed to
die() rather than being sent to a browser and finished with an exit().
Bugzilla->batch will return the current state of this flag.
=item C<dbh> =item C<dbh>
......
...@@ -34,6 +34,7 @@ use base qw(Bugzilla::Auth::Login); ...@@ -34,6 +34,7 @@ use base qw(Bugzilla::Auth::Login);
use constant user_can_create_account => 1; use constant user_can_create_account => 1;
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::WebService::Constants;
use Bugzilla::Util; use Bugzilla::Util;
use Bugzilla::Error; use Bugzilla::Error;
...@@ -58,6 +59,12 @@ sub fail_nodata { ...@@ -58,6 +59,12 @@ sub fail_nodata {
my $cgi = Bugzilla->cgi; my $cgi = Bugzilla->cgi;
my $template = Bugzilla->template; my $template = Bugzilla->template;
if (Bugzilla->error_mode == Bugzilla::Constants::ERROR_MODE_DIE_SOAP_FAULT) {
die SOAP::Fault
->faultcode(ERROR_AUTH_NODATA)
->faultstring('Login Required');
}
# Redirect to SSL if required # Redirect to SSL if required
if (Bugzilla->params->{'sslbase'} ne '' if (Bugzilla->params->{'sslbase'} ne ''
and Bugzilla->params->{'ssl'} ne 'never') and Bugzilla->params->{'ssl'} ne 'never')
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
# Christopher Aillon <christopher@aillon.com> # Christopher Aillon <christopher@aillon.com>
# Shane H. W. Travis <travis@sedsystems.ca> # Shane H. W. Travis <travis@sedsystems.ca>
# Max Kanat-Alexander <mkanat@bugzilla.org> # Max Kanat-Alexander <mkanat@bugzilla.org>
# Marc Schumann <wurblzap@gmail.com>
package Bugzilla::Constants; package Bugzilla::Constants;
use strict; use strict;
...@@ -108,6 +109,14 @@ use File::Basename; ...@@ -108,6 +109,14 @@ use File::Basename;
BUG_STATE_OPEN BUG_STATE_OPEN
USAGE_MODE_BROWSER
USAGE_MODE_CMDLINE
USAGE_MODE_WEBSERVICE
ERROR_MODE_WEBPAGE
ERROR_MODE_DIE
ERROR_MODE_DIE_SOAP_FAULT
DB_MODULE DB_MODULE
ROOT_USER ROOT_USER
ON_WINDOWS ON_WINDOWS
...@@ -290,6 +299,17 @@ use constant FIELD_TYPE_FREETEXT => 1; ...@@ -290,6 +299,17 @@ use constant FIELD_TYPE_FREETEXT => 1;
use constant BUG_STATE_OPEN => ('NEW', 'REOPENED', 'ASSIGNED', use constant BUG_STATE_OPEN => ('NEW', 'REOPENED', 'ASSIGNED',
'UNCONFIRMED'); 'UNCONFIRMED');
# Usage modes. Default USAGE_MODE_BROWSER. Use with Bugzilla->usage_mode.
use constant USAGE_MODE_BROWSER => 0;
use constant USAGE_MODE_CMDLINE => 1;
use constant USAGE_MODE_WEBSERVICE => 2;
# Error modes. Default set by Bugzilla->usage_mode (so ERROR_MODE_WEBPAGE
# usually). Use with Bugzilla->error_mode.
use constant ERROR_MODE_WEBPAGE => 0;
use constant ERROR_MODE_DIE => 1;
use constant ERROR_MODE_DIE_SOAP_FAULT => 2;
# Data about what we require for different databases. # Data about what we require for different databases.
use constant DB_MODULE => { use constant DB_MODULE => {
'mysql' => {db => 'Bugzilla::DB::Mysql', db_version => '4.0.14', 'mysql' => {db => 'Bugzilla::DB::Mysql', db_version => '4.0.14',
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
# Rights Reserved. # Rights Reserved.
# #
# Contributor(s): Bradley Baetz <bbaetz@acm.org> # Contributor(s): Bradley Baetz <bbaetz@acm.org>
# Marc Schumann <wurblzap@gmail.com>
package Bugzilla::Error; package Bugzilla::Error;
...@@ -27,6 +28,7 @@ use base qw(Exporter); ...@@ -27,6 +28,7 @@ use base qw(Exporter);
@Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError); @Bugzilla::Error::EXPORT = qw(ThrowCodeError ThrowTemplateError ThrowUserError);
use Bugzilla::Constants; use Bugzilla::Constants;
use Bugzilla::WebService::Constants;
use Bugzilla::Util; use Bugzilla::Util;
use Date::Format; use Date::Format;
...@@ -74,15 +76,21 @@ sub _throw_error { ...@@ -74,15 +76,21 @@ sub _throw_error {
} }
my $template = Bugzilla->template; my $template = Bugzilla->template;
if (Bugzilla->batch) { if (Bugzilla->error_mode == ERROR_MODE_WEBPAGE) {
print Bugzilla->cgi->header();
$template->process($name, $vars)
|| ThrowTemplateError($template->error());
}
elsif (Bugzilla->error_mode == ERROR_MODE_DIE) {
my $message; my $message;
$template->process($name, $vars, \$message) $template->process($name, $vars, \$message)
|| ThrowTemplateError($template->error()); || ThrowTemplateError($template->error());
die("$message\n"); die("$message\n");
} else { }
print Bugzilla->cgi->header(); elsif (Bugzilla->error_mode == ERROR_MODE_DIE_SOAP_FAULT) {
$template->process($name, $vars) die SOAP::Fault
|| ThrowTemplateError($template->error()); ->faultcode(ERROR_GENERAL)
->faultstring($error);
} }
exit; exit;
} }
...@@ -103,7 +111,7 @@ sub ThrowTemplateError { ...@@ -103,7 +111,7 @@ sub ThrowTemplateError {
Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT); Bugzilla->dbh->bz_unlock_tables(UNLOCK_ABORT);
my $vars = {}; my $vars = {};
if (Bugzilla->batch) { if (Bugzilla->error_mode == ERROR_MODE_DIE) {
die("error: template error: $template_err"); die("error: template error: $template_err");
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
# The Original Code is the Bugzilla Bug Tracking System. # The Original Code is the Bugzilla Bug Tracking System.
# #
# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org> # Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
# Marc Schumann <wurblzap@gmail.com>
package Bugzilla::Install::Requirements; package Bugzilla::Install::Requirements;
...@@ -117,6 +118,10 @@ use constant OPTIONAL_MODULES => [ ...@@ -117,6 +118,10 @@ use constant OPTIONAL_MODULES => [
name => 'Net::LDAP', name => 'Net::LDAP',
version => 0 version => 0
}, },
{
name => 'SOAP::Lite',
version => 0
},
]; ];
# These are only required if you want to use Bugzilla with # These are only required if you want to use Bugzilla with
...@@ -252,6 +257,15 @@ sub check_requirements { ...@@ -252,6 +257,15 @@ sub check_requirements {
" " . install_command("Image::Magick") . "\n\n"; " " . install_command("Image::Magick") . "\n\n";
} }
# Web Services
if (!$have_mod{'SOAP::Lite'}) {
print "If you want your Bugzilla installation to be accessible\n",
"via its Web Service interface, you will need to install\n",
"the SOAP::Lite module by running (as $root):\n\n";
print " SOAP::Lite: " .
install_command("SOAP::Lite") . "\n\n";
}
# Graphical Reports # Graphical Reports
if (!$have_mod{'GD'} || !$have_mod{'GD::Graph'} if (!$have_mod{'GD'} || !$have_mod{'GD::Graph'}
|| !$have_mod{'GD::Text::Align'} || !$have_mod{'GD::Text::Align'}
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
# Christopher Aillon <christopher@aillon.com> # Christopher Aillon <christopher@aillon.com>
# Max Kanat-Alexander <mkanat@bugzilla.org> # Max Kanat-Alexander <mkanat@bugzilla.org>
# Frédéric Buclin <LpSolit@gmail.com> # Frédéric Buclin <LpSolit@gmail.com>
# Marc Schumann <wurblzap@gmail.com>
package Bugzilla::Util; package Bugzilla::Util;
...@@ -63,20 +64,20 @@ sub is_tainted { ...@@ -63,20 +64,20 @@ sub is_tainted {
sub trick_taint { sub trick_taint {
require Carp; require Carp;
Carp::confess("Undef to trick_taint") unless defined $_[0]; Carp::confess("Undef to trick_taint") unless defined $_[0];
my ($match) = $_[0] =~ /^(.*)$/s; my $match = $_[0] =~ /^(.*)$/s;
$_[0] = $match; $_[0] = $match ? $1 : undef;
return (defined($_[0])); return (defined($_[0]));
} }
sub detaint_natural { sub detaint_natural {
my ($match) = $_[0] =~ /^(\d+)$/; my $match = $_[0] =~ /^(\d+)$/;
$_[0] = $match; $_[0] = $match ? $1 : undef;
return (defined($_[0])); return (defined($_[0]));
} }
sub detaint_signed { sub detaint_signed {
my ($match) = $_[0] =~ /^([-+]?\d+)$/; my $match = $_[0] =~ /^([-+]?\d+)$/;
$_[0] = $match; $_[0] = $match ? $1 : undef;
# Remove any leading plus sign. # Remove any leading plus sign.
if (defined($_[0]) && $_[0] =~ /^\+(\d+)$/) { if (defined($_[0]) && $_[0] =~ /^\+(\d+)$/) {
$_[0] = $1; $_[0] = $1;
......
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
package Bugzilla::WebService;
use strict;
use Bugzilla::WebService::Constants;
sub fail_unimplemented {
my $this = shift;
die SOAP::Fault
->faultcode(ERROR_UNIMPLEMENTED)
->faultstring('Service Unimplemented');
}
package Bugzilla::WebService::XMLRPC::Transport::HTTP::CGI;
use strict;
eval 'use base qw(XMLRPC::Transport::HTTP::CGI)';
sub make_response {
my $self = shift;
$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 (@{Bugzilla->cgi->{'Bugzilla_cookie_list'}}) {
$self->response->headers->push_header('Set-Cookie', $_);
}
}
1;
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
package Bugzilla::WebService::Bug;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::WebService::Constants;
use Bugzilla::Util qw(detaint_natural);
use Bugzilla::Bug;
sub get_bug {
my $self = shift;
my ($bug_id) = @_;
Bugzilla->login;
ValidateBugID($bug_id);
return new Bugzilla::Bug($bug_id);
}
1;
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
package Bugzilla::WebService::Bugzilla;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Constants;
sub get_version {
return BUGZILLA_VERSION;
}
1;
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
package Bugzilla::WebService::Constants;
use strict;
use base qw(Exporter);
@Bugzilla::WebService::Constants::EXPORT = qw(
ERROR_AUTH_NODATA
ERROR_UNIMPLEMENTED
ERROR_GENERAL
);
use constant ERROR_AUTH_NODATA => 410;
use constant ERROR_UNIMPLEMENTED => 910;
use constant ERROR_GENERAL => 999;
1;
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
package Bugzilla::WebService::Product;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Product;
sub get_product {
my $self = shift;
my ($product_name) = @_;
Bugzilla->login;
# Bugzilla::Product doesn't do permissions checks, so we can't do the call
# to Bugzilla::Product::new until a permissions check happens here.
$self->fail_unimplemented();
return new Bugzilla::Product({'name' => $product_name});
}
1;
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
package Bugzilla::WebService::User;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla;
use Bugzilla::Constants;
sub login {
my $self = shift;
my ($login, $password, $remember) = @_;
# Convert $remember from a boolean 0/1 value to a CGI-compatible one.
if (defined($remember)) {
$remember = $remember? 'on': '';
}
else {
# Use Bugzilla's default if $remember is not supplied.
$remember =
Bugzilla->params->{'rememberlogin'} eq 'defaulton'? 'on': '';
}
# Make sure the CGI user info class works if necessary.
my $cgi = Bugzilla->cgi;
$cgi->param('Bugzilla_login', $login);
$cgi->param('Bugzilla_password', $password);
$cgi->param('Bugzilla_remember', $remember);
Bugzilla->login;
return Bugzilla->user->id;
}
sub logout {
my $self = shift;
Bugzilla->login(LOGIN_OPTIONAL);
Bugzilla->logout;
}
1;
...@@ -55,8 +55,9 @@ if (chdir("graphs")) { ...@@ -55,8 +55,9 @@ if (chdir("graphs")) {
chdir(".."); chdir("..");
} }
# Let Throw*Error() work correctly outside a web browser. # This is a pure command line script.
Bugzilla->batch(1); Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
my $dbh = Bugzilla->switch_to_shadow_db(); my $dbh = Bugzilla->switch_to_shadow_db();
# To recreate the daily statistics, run "collectstats.pl --regenerate" . # To recreate the daily statistics, run "collectstats.pl --regenerate" .
......
#!/usr/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the “License”); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an “AS
# IS” basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
=head1 NAME
bz_webservice_demo.pl - Show how to talk to Bugzilla via XMLRPC
=head1 SYNOPSIS
C<bz_webservice_demo.pl [options]>
C<bz_webservice_demo.pl --help> for detailed help
=cut
use strict;
use Getopt::Long;
use Pod::Usage;
use File::Basename qw(dirname);
use File::Spec;
use HTTP::Cookies;
use XMLRPC::Lite;
# If you want, say “use Bugzilla::WebService::Constants” here to get access
# to Bugzilla's web service error code constants.
# If you do this, remember to issue a “use lib” pointing to your Bugzilla
# installation directory, too.
my $help;
my $Bugzilla_uri;
my $Bugzilla_login;
my $Bugzilla_password;
my $Bugzilla_remember;
my $bug_id;
my $product_name;
GetOptions('help|h|?' => \$help,
'uri=s' => \$Bugzilla_uri,
'login:s' => \$Bugzilla_login,
'password=s' => \$Bugzilla_password,
'rememberlogin!' => \$Bugzilla_remember,
'bug_id:s' => \$bug_id,
'product_name:s' => \$product_name,
) or pod2usage({'-verbose' => 0, '-exitval' => 1});
=head1 OPTIONS
=over
=item --help, -h, -?
Print a short help message and exit.
=item --uri
URI to Bugzilla's C<xmlrpc.cgi> script, along the lines of
C<http://your.bugzilla.installation/path/to/bugzilla/xmlrpc.cgi>.
=item --login
Bugzilla login name. Specify this together with B<--password> in order to log in.
Specify this without a value in order to log out.
=item --password
Bugzilla password. Specify this together with B<--login> in order to log in.
=item --rememberlogin
Gives access to Bugzilla's “Bugzilla_remember” option.
Specify this option while logging in to do the same thing as ticking the
C<Bugzilla_remember> box on Bugilla's log in form.
Don't specify this option to do the same thing as unchecking the box.
See Bugzilla's rememberlogin parameter for details.
=item --bug_id
Pass a bug ID to have C<bz_webservice_demo.pl> do some bug-related test calls.
=item --product_name
Pass a product name to have C<bz_webservice_demo.pl> do some product-related
test calls.
=back
=head1 DESCRIPTION
=cut
pod2usage({'-verbose' => 1, '-exitval' => 0}) if $help;
_syntaxhelp('URI unspecified') unless $Bugzilla_uri;
# We will use this variable for SOAP call results.
my $soapresult;
# We will use this variable for function call results.
my $result;
# Open our cookie jar. We save it into a file so that we may re-use cookies
# to avoid the need of logging in every time. You're encouraged, but not
# required, to do this in your applications, too.
# Cookies are only saved if Bugzilla's rememberlogin parameter is set to one of
# - on
# - defaulton (and you didn't pass 0 as third parameter to User.login)
# - defaultoff (and you passed 1 as third parameter to User.login)
my $cookie_jar =
new HTTP::Cookies('file' => File::Spec->catdir(dirname($0), 'cookies.txt'),
'autosave' => 1);
=head2 Initialization
Using the XMLRPC::Lite class, you set up a proxy, as shown in this script.
Bugzilla's XMLRPC URI ends in C<xmlrpc.cgi>, so your URI looks along the lines
of C<http://your.bugzilla.installation/path/to/bugzilla/xmlrpc.cgi>.
=cut
my $proxy = XMLRPC::Lite->proxy($Bugzilla_uri,
'cookie_jar' => $cookie_jar);
=head2 Checking Bugzilla's version
To make sure the Bugzilla you're connecting to supports the methods you wish to
call, you may want to compare the result of C<Bugzilla.get_version> to the
minimum required version your application needs.
=cut
$soapresult = $proxy->call('Bugzilla.get_version');
_die_on_fault($soapresult);
print 'Connecting to a Bugzilla of version ' . $soapresult->result() . ".\n";
=head2 Logging In and Out
=head3 Using Bugzilla's Environment Authentication
Use a
C<http://login:password@your.bugzilla.installation/path/to/bugzilla/xmlrpc.cgi>
style URI.
You don't log out if you're using this kind of authentication.
=head3 Using Bugzilla's CGI Variable Authentication
Use the C<User.login> and C<User.logout> calls to log in and out, as shown
in this script.
The C<Bugzilla_remember> parameter is optional.
If omitted, Bugzilla's defaults apply (as specified by its C<rememberlogin>
parameter).
Bugzilla hands back cookies you'll need to pass along during your work calls.
=cut
if (defined($Bugzilla_login)) {
if ($Bugzilla_login ne '') {
# Log in.
$soapresult = $proxy->call('User.login',
$Bugzilla_login, $Bugzilla_password,
$Bugzilla_remember);
_die_on_fault($soapresult);
print "Login successful.\n";
}
else {
# Log out.
$soapresult = $proxy->call('User.logout');
_die_on_fault($soapresult);
print "Logout successful.\n";
}
}
=head2 Retrieving Bug Information
Call C<Bug.get_bug> with the ID of the bug you want to know more of.
The call will return a C<Bugzilla::Bug> object.
=cut
if ($bug_id) {
$soapresult = $proxy->call('Bug.get_bug', $bug_id);
_die_on_fault($soapresult);
$result = $soapresult->result;
foreach (keys(%$result)) {
print "$_: $$result{$_}\n";
}
}
=head2 Retrieving Product Information
Call C<Product.get_product> with the name of the product you want to know more
of.
The call will return a C<Bugzilla::Product> object.
=cut
if ($product_name) {
$soapresult = $proxy->call('Product.get_product', $product_name);
_die_on_fault($soapresult);
$result = $soapresult->result;
if (ref($result) eq 'HASH') {
foreach (keys(%$result)) {
print "$_: $$result{$_}\n";
}
}
else {
print "$result\n";
}
}
=head1 NOTES
=head2 Character Set Encoding
Make sure that your application either uses the same character set
encoding as Bugzilla does, or that it converts correspondingly when using the
web service API.
By default, Bugzilla uses UTF-8 as its character set encoding.
=head1 SEE ALSO
There are code comments in C<bz_webservice_demo.pl> which might be of further
help to you.
=cut
sub _die_on_fault {
my $soapresult = shift;
if ($soapresult->fault) {
my ($package, $filename, $line) = caller;
die $soapresult->faultcode . ' ' . $soapresult->faultstring .
" in SOAP call near $filename line $line.\n";
}
}
sub _syntaxhelp {
my $msg = shift;
print "Error: $msg\n";
pod2usage({'-verbose' => 0, '-exitval' => 1});
}
<!-- <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"> --> <!-- <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"> -->
<!-- $Id: installation.xml,v 1.127 2006/08/14 15:54:25 lpsolit%gmail.com Exp $ --> <!-- $Id: installation.xml,v 1.128 2006/08/19 17:20:24 wurblzap%gmail.com Exp $ -->
<chapter id="installing-bugzilla"> <chapter id="installing-bugzilla">
<title>Installing Bugzilla</title> <title>Installing Bugzilla</title>
...@@ -387,6 +387,13 @@ ...@@ -387,6 +387,13 @@
<listitem> <listitem>
<para> <para>
<link linkend="install-modules-soap-lite">SOAP::Lite</link>
(&min-soap-lite-ver;) for the web service interface
</para>
</listitem>
<listitem>
<para>
<link linkend="install-modules-patchreader">PatchReader</link> <link linkend="install-modules-patchreader">PatchReader</link>
(&min-patchreader-ver;) for pretty HTML view of patches (&min-patchreader-ver;) for pretty HTML view of patches
</para> </para>
...@@ -488,6 +495,14 @@ ...@@ -488,6 +495,14 @@
</para> </para>
</section> </section>
<section id="install-modules-soap">
<title>SOAP::Lite (&min-soap-lite-ver;)</title>
<para>Installing SOAP::Lite enables your Bugzilla installation to be
accessible at a standardized Web Service interface (SOAP/XML-RPC)
by third-party applications via HTTP(S).
</para>
</section>
<section id="install-modules-patchreader"> <section id="install-modules-patchreader">
<title>PatchReader (&min-patchreader-ver;)</title> <title>PatchReader (&min-patchreader-ver;)</title>
......
...@@ -96,7 +96,7 @@ use XML::Twig; ...@@ -96,7 +96,7 @@ use XML::Twig;
# We want to capture errors and handle them here rather than have the Template # We want to capture errors and handle them here rather than have the Template
# code barf all over the place. # code barf all over the place.
Bugzilla->batch(1); Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_CMDLINE);
my $debug = 0; my $debug = 0;
my $mail = ''; my $mail = '';
......
...@@ -559,10 +559,11 @@ if (defined($cgi->upload('data')) || $cgi->param('attachurl')) { ...@@ -559,10 +559,11 @@ if (defined($cgi->upload('data')) || $cgi->param('attachurl')) {
# Add flags, if any. To avoid dying if something goes wrong # Add flags, if any. To avoid dying if something goes wrong
# while processing flags, we will eval() flag validation. # while processing flags, we will eval() flag validation.
# This requires to be in batch mode. # This requires errors to die().
# XXX: this can go away as soon as flag validation is able to # XXX: this can go away as soon as flag validation is able to
# fail without dying. # fail without dying.
Bugzilla->batch(1); my $error_mode_cache = Bugzilla->error_mode;
Bugzilla->error_mode(ERROR_MODE_DIE);
eval { eval {
# Make sure no flags have already been set for this bug. # Make sure no flags have already been set for this bug.
# Impossible? - Well, depends if you hack the URL or not. # Impossible? - Well, depends if you hack the URL or not.
...@@ -571,7 +572,7 @@ eval { ...@@ -571,7 +572,7 @@ eval {
Bugzilla::FlagType::validate($cgi, $id); Bugzilla::FlagType::validate($cgi, $id);
Bugzilla::Flag::process($bug, undef, $timestamp, $cgi); Bugzilla::Flag::process($bug, undef, $timestamp, $cgi);
}; };
Bugzilla->batch(0); Bugzilla->error_mode($error_mode_cache);
if ($@) { if ($@) {
$vars->{'message'} = 'flag_creation_failed'; $vars->{'message'} = 'flag_creation_failed';
$vars->{'flag_creation_error'} = $@; $vars->{'flag_creation_error'} = $@;
......
...@@ -104,7 +104,7 @@ ...@@ -104,7 +104,7 @@
Unable to open the chart datafile <tt>[% filename FILTER html %]</tt>. Unable to open the chart datafile <tt>[% filename FILTER html %]</tt>.
[% ELSIF error == "chart_lines_not_installed" %] [% ELSIF error == "chart_lines_not_installed" %]
[% admindocslinks = {'installation.html#install-perlmodules' => 'Installing perl modules necessary for Charting'} %] [% admindocslinks = {'installation.html#install-perlmodules' => 'Installing Perl modules necessary for Charting'} %]
Charts will not work without the Chart::Lines Perl module being installed. Charts will not work without the Chart::Lines Perl module being installed.
Run checksetup.pl for installation instructions. Run checksetup.pl for installation instructions.
...@@ -137,7 +137,7 @@ ...@@ -137,7 +137,7 @@
and <code>[% type FILTER html %]</code> together. and <code>[% type FILTER html %]</code> together.
[% ELSIF error == "gd_not_installed" %] [% ELSIF error == "gd_not_installed" %]
[% admindocslinks = {'installation.html#install-perlmodules' => 'Installing perl modules necessary for Charting'} %] [% admindocslinks = {'installation.html#install-perlmodules' => 'Installing Perl modules necessary for Charting'} %]
Charts will not work without the GD Perl module being installed. Charts will not work without the GD Perl module being installed.
Run checksetup.pl for installation instructions. Run checksetup.pl for installation instructions.
...@@ -321,6 +321,12 @@ ...@@ -321,6 +321,12 @@
The value "<code>[% value FILTER html %]</code>" is not in the list of The value "<code>[% value FILTER html %]</code>" is not in the list of
legal values for the <em>[% name FILTER html %]</em> setting. legal values for the <em>[% name FILTER html %]</em> setting.
[% ELSIF error == "soap_not_installed" %]
[% admindocslinks = {'installation.html#install-perlmodules' => 'Installing Perl modules'} %]
The XMLRPC interface will not work without the SOAP::Lite Perl module being
installed.
Run checksetup.pl for installation instructions.
[% ELSIF error == "token_generation_error" %] [% ELSIF error == "token_generation_error" %]
Something is seriously wrong with the token generation system. Something is seriously wrong with the token generation system.
...@@ -347,6 +353,9 @@ ...@@ -347,6 +353,9 @@
I could not figure out what you wanted to do. I could not figure out what you wanted to do.
[% END %] [% END %]
[% ELSIF error == "usage_mode_invalid" %]
'[% invalid_usage_mode %]' is not a valid usage mode.
[% ELSIF error == "must_be_patch" %] [% ELSIF error == "must_be_patch" %]
[% title = "Attachment Must Be Patch" %] [% title = "Attachment Must Be Patch" %]
Attachment #[% attach_id FILTER html %] must be a patch. Attachment #[% attach_id FILTER html %] must be a patch.
...@@ -383,9 +392,11 @@ ...@@ -383,9 +392,11 @@
[% END %] [% END %]
[% END %] [% END %]
[%# If we are in batch mode, we want the error message to be plain text, not HTML %] [%# If we are in ERROR_MODE_DIE, we want the error message to be plain text,
# not HTML
%]
[% USE Bugzilla %] [% USE Bugzilla %]
[% IF Bugzilla.batch %] [% IF Bugzilla.error_mode == ERROR_MODE_DIE %]
[% error_message FILTER none %] [% error_message FILTER none %]
[% RETURN %] [% RETURN %]
[% END %] [% END %]
......
...@@ -1422,9 +1422,11 @@ ...@@ -1422,9 +1422,11 @@
[% END %] [% END %]
[% END %] [% END %]
[%# If we are in batch mode, we want the error message to be plain text, not HTML %] [%# If we are in ERROR_MODE_DIE, we want the error message to be plain text,
# not HTML
%]
[% USE Bugzilla %] [% USE Bugzilla %]
[% IF Bugzilla.batch %] [% IF Bugzilla.error_mode == ERROR_MODE_DIE %]
[% error_message FILTER none %] [% error_message FILTER none %]
[% RETURN %] [% RETURN %]
[% END %] [% END %]
......
#!/usr/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
use strict;
use lib qw(.);
use Bugzilla;
use Bugzilla::Constants;
# Use an eval here so that runtests.pl accepts this script even if SOAP-Lite
# is not installed.
eval 'use XMLRPC::Transport::HTTP;
use Bugzilla::WebService;';
$@ && ThrowCodeError('soap_not_installed');
Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_WEBSERVICE);
my $response = Bugzilla::WebService::XMLRPC::Transport::HTTP::CGI
->dispatch_with({'Bugzilla' => 'Bugzilla::WebService::Bugzilla',
'Bug' => 'Bugzilla::WebService::Bug',
'User' => 'Bugzilla::WebService::User',
'Product' => 'Bugzilla::WebService::Product',
})
->handle;
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