Remove docs changes by jwilmoth@starbucks.com.
git-svn-id: svn://10.0.0.236/trunk@265700 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
7cc2d5e854
commit
200d60ec4d
@ -1 +1 @@
|
||||
9229
|
||||
9230
|
||||
@ -1 +1 @@
|
||||
c0dbbc6e69bdefcb49fd9046f7e830880d3ac513
|
||||
1d69e313176b3744e144d3fb8cc58664334cef17
|
||||
@ -29,6 +29,5 @@ Options -Indexes
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteOptions inherit
|
||||
RewriteRule ^rest/(.*)$ rest.cgi/$1 [NE]
|
||||
</IfModule>
|
||||
|
||||
@ -8,10 +8,7 @@ perl:
|
||||
env:
|
||||
- TEST_SUITE=sanity
|
||||
- TEST_SUITE=docs
|
||||
- TEST_SUITE=webservices DB=mysql
|
||||
- TEST_SUITE=selenium DB=mysql
|
||||
- TEST_SUITE=webservices DB=pg
|
||||
- TEST_SUITE=selenium DB=pg
|
||||
- TEST_SUITE=checksetup DB=mysql
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
@ -22,32 +19,14 @@ matrix:
|
||||
- perl: 5.14
|
||||
env: TEST_SUITE=docs
|
||||
- perl: 5.10
|
||||
env: TEST_SUITE=webservices DB=mysql
|
||||
- perl: 5.10
|
||||
env: TEST_SUITE=webservices DB=pg
|
||||
- perl: 5.10
|
||||
env: TEST_SUITE=selenium DB=mysql
|
||||
- perl: 5.10
|
||||
env: TEST_SUITE=selenium DB=pg
|
||||
env: TEST_SUITE=checksetup DB=mysql
|
||||
- perl: 5.12
|
||||
env: TEST_SUITE=webservices DB=mysql
|
||||
- perl: 5.12
|
||||
env: TEST_SUITE=webservices DB=pg
|
||||
- perl: 5.12
|
||||
env: TEST_SUITE=selenium DB=mysql
|
||||
- perl: 5.12
|
||||
env: TEST_SUITE=selenium DB=pg
|
||||
env: TEST_SUITE=checksetup DB=mysql
|
||||
- perl: 5.14
|
||||
env: TEST_SUITE=webservices DB=mysql
|
||||
- perl: 5.14
|
||||
env: TEST_SUITE=webservices DB=pg
|
||||
- perl: 5.14
|
||||
env: TEST_SUITE=selenium DB=mysql
|
||||
- perl: 5.14
|
||||
env: TEST_SUITE=selenium DB=pg
|
||||
env: TEST_SUITE=checksetup DB=mysql
|
||||
|
||||
before_install:
|
||||
- git clone https://github.com/bugzilla/qa.git -b master qa
|
||||
- git clone https://github.com/bugzilla/qa.git -b 4.4 qa
|
||||
|
||||
install: true
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# We want any compile errors to get to the browser, if possible.
|
||||
BEGIN {
|
||||
@ -122,8 +121,8 @@ sub init_page {
|
||||
#
|
||||
# This code must go here. It cannot go anywhere in Bugzilla::CGI, because
|
||||
# it uses Template, and that causes various dependency loops.
|
||||
if (!grep { $_ eq $script } SHUTDOWNHTML_EXEMPT
|
||||
and Bugzilla->params->{'shutdownhtml'})
|
||||
if (Bugzilla->params->{"shutdownhtml"}
|
||||
&& !grep { $_ eq $script } SHUTDOWNHTML_EXEMPT)
|
||||
{
|
||||
# Allow non-cgi scripts to exit silently (without displaying any
|
||||
# message), if desired. At this point, no DBI call has been made
|
||||
@ -397,13 +396,6 @@ sub logout_request {
|
||||
# there. Don't rely on it: use Bugzilla->user->login instead!
|
||||
}
|
||||
|
||||
sub markdown {
|
||||
return if !Bugzilla->feature('markdown');
|
||||
|
||||
require Bugzilla::Markdown;
|
||||
return $_[0]->request_cache->{markdown} ||= Bugzilla::Markdown->new();
|
||||
}
|
||||
|
||||
sub job_queue {
|
||||
require Bugzilla::JobQueue;
|
||||
return $_[0]->request_cache->{job_queue} ||= Bugzilla::JobQueue->new();
|
||||
@ -659,16 +651,13 @@ sub memcached {
|
||||
# Per-process cleanup. Note that this is a plain subroutine, not a method,
|
||||
# so we don't have $class available.
|
||||
sub _cleanup {
|
||||
my $cache = Bugzilla->request_cache;
|
||||
my $main = $cache->{dbh_main};
|
||||
my $shadow = $cache->{dbh_shadow};
|
||||
my $main = Bugzilla->request_cache->{dbh_main};
|
||||
my $shadow = Bugzilla->request_cache->{dbh_shadow};
|
||||
foreach my $dbh ($main, $shadow) {
|
||||
next if !$dbh;
|
||||
$dbh->bz_rollback_transaction() if $dbh->bz_in_transaction;
|
||||
$dbh->disconnect;
|
||||
}
|
||||
my $smtp = $cache->{smtp};
|
||||
$smtp->disconnect if $smtp;
|
||||
clear_request_cache();
|
||||
|
||||
# These are both set by CGI.pm but need to be undone so that
|
||||
@ -760,7 +749,7 @@ If you ever need a L<Bugzilla::Template> object while you're already
|
||||
processing a template, use this. Also use it if you want to specify
|
||||
the language to use. If no argument is passed, it uses the last
|
||||
language set. If the argument is "" (empty string), the language is
|
||||
reset to the current one (the one used by C<Bugzilla-E<gt>template>).
|
||||
reset to the current one (the one used by Bugzilla->template).
|
||||
|
||||
=item C<cgi>
|
||||
|
||||
@ -878,8 +867,8 @@ specify this argument, all fields will be returned.
|
||||
|
||||
=item C<error_mode>
|
||||
|
||||
Call either C<Bugzilla-E<gt>error_mode(Bugzilla::Constants::ERROR_MODE_DIE)>
|
||||
or C<Bugzilla-E<gt>error_mode(Bugzilla::Constants::ERROR_MODE_DIE_SOAP_FAULT)> to
|
||||
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().
|
||||
@ -888,24 +877,24 @@ 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-E<gt>error_mode> will return the current state of this flag.
|
||||
C<Bugzilla->error_mode> will return the current state of this flag.
|
||||
|
||||
Note that C<Bugzilla-E<gt>error_mode> is being called by C<Bugzilla-E<gt>usage_mode> on
|
||||
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-E<gt>usage_mode(Bugzilla::Constants::USAGE_MODE_CMDLINE)>
|
||||
or C<Bugzilla-E<gt>usage_mode(Bugzilla::Constants::USAGE_MODE_XMLRPC)> near the
|
||||
Call either C<Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_CMDLINE)>
|
||||
or C<Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_XMLRPC)> 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-E<gt>error_mode> to set an error mode which makes sense for the
|
||||
calls C<Bugzilla->error_mode> to set an error mode which makes sense for the
|
||||
usage mode.
|
||||
|
||||
C<Bugzilla-E<gt>usage_mode> will return the current state of this flag.
|
||||
C<Bugzilla->usage_mode> will return the current state of this flag.
|
||||
|
||||
=item C<installation_mode>
|
||||
|
||||
@ -944,9 +933,9 @@ Change the database object to refer to the main database.
|
||||
|
||||
=item C<params>
|
||||
|
||||
The current Parameters of Bugzilla, as a hashref. If C<data/params.json>
|
||||
does not exist, then we return an empty hashref. If C<data/params.json>
|
||||
is unreadable or is not valid, we C<die>.
|
||||
The current Parameters of Bugzilla, as a hashref. If C<data/params>
|
||||
does not exist, then we return an empty hashref. If C<data/params>
|
||||
is unreadable or is not valid perl, we C<die>.
|
||||
|
||||
=item C<local_timezone>
|
||||
|
||||
@ -954,10 +943,6 @@ Returns the local timezone of the Bugzilla installation,
|
||||
as a DateTime::TimeZone object. This detection is very time
|
||||
consuming, so we cache this information for future references.
|
||||
|
||||
=item C<markdown>
|
||||
|
||||
The current L<Markdown|Bugzilla::Markdown> object, to be used for Markdown rendering.
|
||||
|
||||
=item C<job_queue>
|
||||
|
||||
Returns a L<Bugzilla::JobQueue> that you can use for queueing jobs.
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Attachment;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
@ -308,8 +307,7 @@ sub is_viewable {
|
||||
|
||||
=item C<data>
|
||||
|
||||
Returns the content of the attachment.
|
||||
As a side-effect, sets $self->is_on_filesystem.
|
||||
the content of the attachment
|
||||
|
||||
=back
|
||||
|
||||
@ -326,16 +324,10 @@ sub data {
|
||||
undef,
|
||||
$self->id);
|
||||
|
||||
# Setting the property here is cheap, as opposed to making an extra
|
||||
# query later, and hitting the filesystem to see if the file is
|
||||
# still there.
|
||||
$self->{is_on_filesystem} = 0;
|
||||
# If there's no attachment data in the database, the attachment is stored
|
||||
# in a local file, so retrieve it from there.
|
||||
if (length($self->{data}) == 0) {
|
||||
if (open(AH, $self->_get_local_filename())) {
|
||||
# file is actually on disk.
|
||||
$self->{is_on_filesystem} = 1;
|
||||
local $/;
|
||||
binmode AH;
|
||||
$self->{data} = <AH>;
|
||||
@ -348,36 +340,9 @@ sub data {
|
||||
|
||||
=over
|
||||
|
||||
=item C<is_on_filesystem>
|
||||
|
||||
Returns true if the attachment is stored on disk (via maxlocalattachment
|
||||
parameter), as opposed to in the database.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
# When the attachment is on the filesystem, you can let the backend
|
||||
# (nginx, apache, lighttpd) serve it for you if it supports the X-Sendfile
|
||||
# feature. This means that the attachment CGI script may have a reduced
|
||||
# footprint. e.g. bug 906010 and bug 1073241.
|
||||
|
||||
sub is_on_filesystem {
|
||||
my $self = shift;
|
||||
return $self->{is_on_filesystem} if exists $self->{is_on_filesystem};
|
||||
# In order to serve an attachment, you also send the datasize in the
|
||||
# content-length header. Making additional queries which are exactly
|
||||
# the same as found in the datasize code path is just wasteful.
|
||||
my $datasize = $self->datasize;
|
||||
return $self->{is_on_filesystem};
|
||||
}
|
||||
|
||||
=over
|
||||
|
||||
=item C<datasize>
|
||||
|
||||
Returns the length (in bytes) of the attachment content.
|
||||
As a side-effect, sets $self->is_on_filesystem.
|
||||
the length (in bytes) of the attachment content
|
||||
|
||||
=back
|
||||
|
||||
@ -404,17 +369,11 @@ sub datasize {
|
||||
WHERE id = ?",
|
||||
undef, $self->id) || 0;
|
||||
|
||||
# Setting the property here is cheap, as opposed to making an extra
|
||||
# query later, and hitting the filesystem to see if the file is
|
||||
# still there.
|
||||
$self->{is_on_filesystem} = 0;
|
||||
# If there's no attachment data in the database, either the attachment
|
||||
# is stored in a local file, and so retrieve its size from the file,
|
||||
# or the attachment has been deleted.
|
||||
unless ($self->{datasize}) {
|
||||
if (open(AH, $self->_get_local_filename())) {
|
||||
# file is actually on disk.
|
||||
$self->{is_on_filesystem} = 1;
|
||||
binmode AH;
|
||||
$self->{datasize} = (stat(AH))[7];
|
||||
close(AH);
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Attachment::PatchReader;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Config;
|
||||
use IO::Select;
|
||||
@ -23,18 +22,17 @@ use Bugzilla::Util;
|
||||
use constant PERLIO_IS_ENABLED => $Config{useperlio};
|
||||
|
||||
sub process_diff {
|
||||
my ($attachment, $format) = @_;
|
||||
my ($attachment, $format, $context) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $lc = Bugzilla->localconfig;
|
||||
my $vars = {};
|
||||
|
||||
require PatchReader::Raw;
|
||||
my $reader = new PatchReader::Raw;
|
||||
my ($reader, $last_reader) = setup_patch_readers(undef, $context);
|
||||
|
||||
if ($format eq 'raw') {
|
||||
require PatchReader::DiffPrinter::raw;
|
||||
$reader->sends_data_to(new PatchReader::DiffPrinter::raw());
|
||||
$last_reader->sends_data_to(new PatchReader::DiffPrinter::raw());
|
||||
# Actually print out the patch.
|
||||
print $cgi->header(-type => 'text/plain');
|
||||
disable_utf8();
|
||||
@ -72,7 +70,7 @@ sub process_diff {
|
||||
$vars->{'description'} = $attachment->description;
|
||||
$vars->{'other_patches'} = \@other_patches;
|
||||
|
||||
setup_template_patch_reader($reader, $vars);
|
||||
setup_template_patch_reader($last_reader, $format, $context, $vars);
|
||||
# The patch is going to be displayed in a HTML page and if the utf8
|
||||
# param is enabled, we have to encode attachment data as utf8.
|
||||
if (Bugzilla->params->{'utf8'}) {
|
||||
@ -84,13 +82,11 @@ sub process_diff {
|
||||
}
|
||||
|
||||
sub process_interdiff {
|
||||
my ($old_attachment, $new_attachment, $format) = @_;
|
||||
my ($old_attachment, $new_attachment, $format, $context) = @_;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $lc = Bugzilla->localconfig;
|
||||
my $vars = {};
|
||||
|
||||
require PatchReader::Raw;
|
||||
|
||||
# Encode attachment data as utf8 if it's going to be displayed in a HTML
|
||||
# page using the UTF-8 encoding.
|
||||
if ($format ne 'raw' && Bugzilla->params->{'utf8'}) {
|
||||
@ -180,11 +176,10 @@ sub process_interdiff {
|
||||
$warning = 'interdiff3';
|
||||
}
|
||||
|
||||
my $reader = new PatchReader::Raw;
|
||||
|
||||
my ($reader, $last_reader) = setup_patch_readers("", $context);
|
||||
if ($format eq 'raw') {
|
||||
require PatchReader::DiffPrinter::raw;
|
||||
$reader->sends_data_to(new PatchReader::DiffPrinter::raw());
|
||||
$last_reader->sends_data_to(new PatchReader::DiffPrinter::raw());
|
||||
# Actually print out the patch.
|
||||
print $cgi->header(-type => 'text/plain');
|
||||
disable_utf8();
|
||||
@ -197,7 +192,7 @@ sub process_interdiff {
|
||||
$vars->{'newid'} = $new_attachment->id;
|
||||
$vars->{'new_desc'} = $new_attachment->description;
|
||||
|
||||
setup_template_patch_reader($reader, $vars);
|
||||
setup_template_patch_reader($last_reader, $format, $context, $vars);
|
||||
}
|
||||
$reader->iterate_string('interdiff #' . $old_attachment->id .
|
||||
' #' . $new_attachment->id, $stdout);
|
||||
@ -212,6 +207,7 @@ sub get_unified_diff {
|
||||
|
||||
# Bring in the modules we need.
|
||||
require PatchReader::Raw;
|
||||
require PatchReader::FixPatchRoot;
|
||||
require PatchReader::DiffPrinter::raw;
|
||||
require PatchReader::PatchInfoGrabber;
|
||||
require File::Temp;
|
||||
@ -223,6 +219,14 @@ sub get_unified_diff {
|
||||
my $reader = new PatchReader::Raw;
|
||||
my $last_reader = $reader;
|
||||
|
||||
# Fixes patch root (makes canonical if possible).
|
||||
if (Bugzilla->params->{'cvsroot'}) {
|
||||
my $fix_patch_root =
|
||||
new PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'});
|
||||
$last_reader->sends_data_to($fix_patch_root);
|
||||
$last_reader = $fix_patch_root;
|
||||
}
|
||||
|
||||
# Grabs the patch file info.
|
||||
my $patch_info_grabber = new PatchReader::PatchInfoGrabber();
|
||||
$last_reader->sends_data_to($patch_info_grabber);
|
||||
@ -269,8 +273,46 @@ sub warn_if_interdiff_might_fail {
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub setup_patch_readers {
|
||||
my ($diff_root, $context) = @_;
|
||||
|
||||
# Parameters:
|
||||
# format=raw|html
|
||||
# context=patch|file|0-n
|
||||
# collapsed=0|1
|
||||
# headers=0|1
|
||||
|
||||
# Define the patch readers.
|
||||
# The reader that reads the patch in (whatever its format).
|
||||
require PatchReader::Raw;
|
||||
my $reader = new PatchReader::Raw;
|
||||
my $last_reader = $reader;
|
||||
# Fix the patch root if we have a cvs root.
|
||||
if (Bugzilla->params->{'cvsroot'}) {
|
||||
require PatchReader::FixPatchRoot;
|
||||
$last_reader->sends_data_to(new PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'}));
|
||||
$last_reader->sends_data_to->diff_root($diff_root) if defined($diff_root);
|
||||
$last_reader = $last_reader->sends_data_to;
|
||||
}
|
||||
|
||||
# Add in cvs context if we have the necessary info to do it
|
||||
if ($context ne 'patch' && Bugzilla->localconfig->{cvsbin}
|
||||
&& Bugzilla->params->{'cvsroot_get'})
|
||||
{
|
||||
require PatchReader::AddCVSContext;
|
||||
# We need to set $cvsbin as global, because PatchReader::CVSClient
|
||||
# needs it in order to find 'cvs'.
|
||||
$main::cvsbin = Bugzilla->localconfig->{cvsbin};
|
||||
$last_reader->sends_data_to(
|
||||
new PatchReader::AddCVSContext($context, Bugzilla->params->{'cvsroot_get'}));
|
||||
$last_reader = $last_reader->sends_data_to;
|
||||
}
|
||||
|
||||
return ($reader, $last_reader);
|
||||
}
|
||||
|
||||
sub setup_template_patch_reader {
|
||||
my ($last_reader, $vars) = @_;
|
||||
my ($last_reader, $format, $context, $vars) = @_;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
my $template = Bugzilla->template;
|
||||
|
||||
@ -285,15 +327,22 @@ sub setup_template_patch_reader {
|
||||
}
|
||||
|
||||
$vars->{'collapsed'} = $cgi->param('collapsed');
|
||||
$vars->{'context'} = $context;
|
||||
$vars->{'do_context'} = Bugzilla->localconfig->{cvsbin}
|
||||
&& Bugzilla->params->{'cvsroot_get'} && !$vars->{'newid'};
|
||||
|
||||
# Print everything out.
|
||||
print $cgi->header(-type => 'text/html');
|
||||
|
||||
$last_reader->sends_data_to(new PatchReader::DiffPrinter::template($template,
|
||||
'attachment/diff-header.html.tmpl',
|
||||
'attachment/diff-file.html.tmpl',
|
||||
'attachment/diff-footer.html.tmpl',
|
||||
$vars));
|
||||
"attachment/diff-header.$format.tmpl",
|
||||
"attachment/diff-file.$format.tmpl",
|
||||
"attachment/diff-footer.$format.tmpl",
|
||||
{ %{$vars},
|
||||
bonsai_url => Bugzilla->params->{'bonsai_url'},
|
||||
lxr_url => Bugzilla->params->{'lxr_url'},
|
||||
lxr_root => Bugzilla->params->{'lxr_root'},
|
||||
}));
|
||||
}
|
||||
|
||||
1;
|
||||
@ -314,4 +363,6 @@ __END__
|
||||
|
||||
=item process_interdiff
|
||||
|
||||
=item setup_patch_readers
|
||||
|
||||
=back
|
||||
|
||||
@ -9,8 +9,6 @@ package Bugzilla::Auth;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use fields qw(
|
||||
_info_getter
|
||||
_verifier
|
||||
@ -32,7 +30,7 @@ sub new {
|
||||
my $self = fields::new($class);
|
||||
|
||||
$params ||= {};
|
||||
$params->{Login} ||= Bugzilla->params->{'user_info_class'} . ',Cookie,APIKey';
|
||||
$params->{Login} ||= Bugzilla->params->{'user_info_class'} . ',Cookie';
|
||||
$params->{Verify} ||= Bugzilla->params->{'user_verify_class'};
|
||||
|
||||
$self->{_info_getter} = new Bugzilla::Auth::Login::Stack($params->{Login});
|
||||
@ -46,6 +44,7 @@ sub new {
|
||||
|
||||
sub login {
|
||||
my ($self, $type) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
# Get login info from the cookie, form, environment variables, etc.
|
||||
my $login_info = $self->{_info_getter}->get_login_info();
|
||||
|
||||
@ -9,8 +9,6 @@ package Bugzilla::Auth::Login;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use fields qw();
|
||||
|
||||
# Determines whether or not a user can logout. It's really a subroutine,
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
# 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::Auth::Login::APIKey;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(Bugzilla::Auth::Login);
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::User::APIKey;
|
||||
use Bugzilla::Util;
|
||||
use Bugzilla::Error;
|
||||
|
||||
use constant requires_persistence => 0;
|
||||
use constant requires_verification => 0;
|
||||
use constant can_login => 0;
|
||||
use constant can_logout => 0;
|
||||
|
||||
# This method is only available to web services. An API key can never
|
||||
# be used to authenticate a Web request.
|
||||
sub get_login_info {
|
||||
my ($self) = @_;
|
||||
my $params = Bugzilla->input_params;
|
||||
my ($user_id, $login_cookie);
|
||||
|
||||
my $api_key_text = trim(delete $params->{'Bugzilla_api_key'});
|
||||
if (!i_am_webservice() || !$api_key_text) {
|
||||
return { failure => AUTH_NODATA };
|
||||
}
|
||||
|
||||
my $api_key = Bugzilla::User::APIKey->new({ name => $api_key_text });
|
||||
|
||||
if (!$api_key or $api_key->api_key ne $api_key_text) {
|
||||
# The second part checks the correct capitalisation. Silly MySQL
|
||||
ThrowUserError("api_key_not_valid");
|
||||
}
|
||||
elsif ($api_key->revoked) {
|
||||
ThrowUserError('api_key_revoked');
|
||||
}
|
||||
|
||||
$api_key->update_last_used();
|
||||
|
||||
return { user_id => $api_key->user_id };
|
||||
}
|
||||
|
||||
1;
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Login::CGI;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Auth::Login);
|
||||
use constant user_can_create_account => 1;
|
||||
|
||||
@ -9,15 +9,13 @@ package Bugzilla::Auth::Login::Cookie;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(Bugzilla::Auth::Login);
|
||||
use fields qw(_login_token);
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::Token;
|
||||
use Bugzilla::Util;
|
||||
use Bugzilla::Error;
|
||||
|
||||
use List::Util qw(first);
|
||||
|
||||
@ -51,20 +49,6 @@ sub get_login_info {
|
||||
@{$cgi->{'Bugzilla_cookie_list'}};
|
||||
$user_id = $cookie->value if $cookie;
|
||||
}
|
||||
|
||||
# If the call is for a web service, and an api token is provided, check
|
||||
# it is valid.
|
||||
if (i_am_webservice() && Bugzilla->input_params->{Bugzilla_api_token}) {
|
||||
my $api_token = Bugzilla->input_params->{Bugzilla_api_token};
|
||||
my ($token_user_id, undef, undef, $token_type)
|
||||
= Bugzilla::Token::GetTokenData($api_token);
|
||||
if (!defined $token_type
|
||||
|| $token_type ne 'api_token'
|
||||
|| $user_id != $token_user_id)
|
||||
{
|
||||
ThrowUserError('auth_invalid_token', { token => $api_token });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# If no cookies were provided, we also look for a login token
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Login::Env;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Auth::Login);
|
||||
|
||||
@ -25,6 +24,7 @@ use constant extern_id_used => 1;
|
||||
|
||||
sub get_login_info {
|
||||
my ($self) = @_;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
my $env_id = $ENV{Bugzilla->params->{"auth_env_id"}} || '';
|
||||
my $env_email = $ENV{Bugzilla->params->{"auth_env_email"}} || '';
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Login::Stack;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(Bugzilla::Auth::Login);
|
||||
use fields qw(
|
||||
|
||||
@ -9,8 +9,6 @@ package Bugzilla::Auth::Persist::Cookie;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use fields qw();
|
||||
|
||||
use Bugzilla::Constants;
|
||||
|
||||
@ -9,8 +9,6 @@ package Bugzilla::Auth::Verify;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use fields qw();
|
||||
|
||||
use Bugzilla::Constants;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Verify::DB;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Auth::Verify);
|
||||
|
||||
@ -56,19 +55,10 @@ sub check_credentials {
|
||||
};
|
||||
}
|
||||
|
||||
# Force the user to change their password if it does not meet the current
|
||||
# criteria. This should usually only happen if the criteria has changed.
|
||||
if (Bugzilla->usage_mode == USAGE_MODE_BROWSER &&
|
||||
Bugzilla->params->{password_check_on_login})
|
||||
{
|
||||
my $check = validate_password_check($password);
|
||||
if ($check) {
|
||||
return {
|
||||
failure => AUTH_ERROR,
|
||||
user_error => $check,
|
||||
details => { locked_user => $user }
|
||||
}
|
||||
}
|
||||
# Force the user to type a longer password if it's too short.
|
||||
if (length($password) < USER_PASSWORD_MIN_LENGTH) {
|
||||
return { failure => AUTH_ERROR, user_error => 'password_current_too_short',
|
||||
details => { locked_user => $user } };
|
||||
}
|
||||
|
||||
# The user's credentials are okay, so delete any outstanding
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Verify::LDAP;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(Bugzilla::Auth::Verify);
|
||||
use fields qw(
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Verify::RADIUS;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Auth::Verify);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Auth::Verify::Stack;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use base qw(Bugzilla::Auth::Verify);
|
||||
use fields qw(
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Bug;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Attachment;
|
||||
use Bugzilla::Constants;
|
||||
@ -49,7 +48,7 @@ use parent qw(Bugzilla::Object Exporter);
|
||||
|
||||
use constant DB_TABLE => 'bugs';
|
||||
use constant ID_FIELD => 'bug_id';
|
||||
use constant NAME_FIELD => 'bug_id';
|
||||
use constant NAME_FIELD => 'alias';
|
||||
use constant LIST_ORDER => ID_FIELD;
|
||||
# Bugs have their own auditing table, bugs_activity.
|
||||
use constant AUDIT_CREATES => 0;
|
||||
@ -65,6 +64,7 @@ sub DB_COLUMNS {
|
||||
my @custom_names = map {$_->name} @custom;
|
||||
|
||||
my @columns = (qw(
|
||||
alias
|
||||
assigned_to
|
||||
bug_file_loc
|
||||
bug_id
|
||||
@ -207,6 +207,7 @@ sub UPDATE_COLUMNS {
|
||||
Bugzilla->active_custom_fields;
|
||||
my @custom_names = map {$_->name} @custom;
|
||||
my @columns = qw(
|
||||
alias
|
||||
assigned_to
|
||||
bug_file_loc
|
||||
bug_severity
|
||||
@ -312,20 +313,11 @@ sub new {
|
||||
# If we get something that looks like a word (not a number),
|
||||
# make it the "name" param.
|
||||
if (!defined $param
|
||||
|| (!ref($param) && $param !~ /^\d+$/)
|
||||
|| (ref($param) && $param->{id} !~ /^\d+$/))
|
||||
|| (!ref($param) && $param =~ /\D/)
|
||||
|| (ref($param) && $param->{id} =~ /\D/))
|
||||
{
|
||||
if ($param) {
|
||||
my $alias = ref($param) ? $param->{id} : $param;
|
||||
my $bug_id = bug_alias_to_id($alias);
|
||||
if (! $bug_id) {
|
||||
my $error_self = {};
|
||||
bless $error_self, $class;
|
||||
$error_self->{'bug_id'} = $alias;
|
||||
$error_self->{'error'} = 'InvalidBugId';
|
||||
return $error_self;
|
||||
}
|
||||
$param = { id => $bug_id,
|
||||
$param = { name => ref($param) ? $param->{id} : $param,
|
||||
cache => ref($param) ? $param->{cache} : 0 };
|
||||
}
|
||||
else {
|
||||
@ -555,9 +547,6 @@ sub _preload_referenced_bugs {
|
||||
foreach my $bug (@$referenced_bugs) {
|
||||
$bug->object_cache_set();
|
||||
}
|
||||
|
||||
# preload bug visibility
|
||||
Bugzilla->user->visible_bugs(\@referenced_bug_ids);
|
||||
}
|
||||
|
||||
sub possible_duplicates {
|
||||
@ -694,22 +683,18 @@ sub create {
|
||||
unless defined $params->{rep_platform};
|
||||
# Make sure a comment is always defined.
|
||||
$params->{comment} = '' unless defined $params->{comment};
|
||||
$params->{is_markdown} = 0
|
||||
unless defined $params->{is_markdown} && $params->{is_markdown} eq '1';
|
||||
|
||||
$class->check_required_create_fields($params);
|
||||
$params = $class->run_create_validators($params);
|
||||
|
||||
# These are not a fields in the bugs table, so we don't pass them to
|
||||
# insert_create_data.
|
||||
my $bug_aliases = delete $params->{alias};
|
||||
my $cc_ids = delete $params->{cc};
|
||||
my $groups = delete $params->{groups};
|
||||
my $depends_on = delete $params->{dependson};
|
||||
my $blocked = delete $params->{blocked};
|
||||
my $keywords = delete $params->{keywords};
|
||||
my $creation_comment = delete $params->{comment};
|
||||
my $is_markdown = delete $params->{is_markdown};
|
||||
my $see_also = delete $params->{see_also};
|
||||
|
||||
# We don't want the bug to appear in the system until it's correctly
|
||||
@ -797,19 +782,11 @@ sub create {
|
||||
|
||||
# We now have a bug id so we can fill this out
|
||||
$creation_comment->{'bug_id'} = $bug->id;
|
||||
$creation_comment->{'is_markdown'} = $is_markdown;
|
||||
|
||||
# Insert the comment. We always insert a comment on bug creation,
|
||||
# but sometimes it's blank.
|
||||
Bugzilla::Comment->insert_create_data($creation_comment);
|
||||
|
||||
# Set up aliases
|
||||
my $sth_aliases = $dbh->prepare('INSERT INTO bugs_aliases (alias, bug_id) VALUES (?, ?)');
|
||||
foreach my $alias (@$bug_aliases) {
|
||||
trick_taint($alias);
|
||||
$sth_aliases->execute($alias, $bug->bug_id);
|
||||
}
|
||||
|
||||
Bugzilla::Hook::process('bug_end_of_create', { bug => $bug,
|
||||
timestamp => $timestamp,
|
||||
});
|
||||
@ -930,25 +907,6 @@ sub update {
|
||||
$changes->{cc} = [$removed_names, $added_names];
|
||||
}
|
||||
|
||||
# Aliases
|
||||
my $old_aliases = $old_bug->alias;
|
||||
my $new_aliases = $self->alias;
|
||||
my ($removed_aliases, $added_aliases) = diff_arrays($old_aliases, $new_aliases);
|
||||
|
||||
foreach my $alias (@$removed_aliases) {
|
||||
$dbh->do('DELETE FROM bugs_aliases WHERE bug_id = ? AND alias = ?',
|
||||
undef, $self->id, $alias);
|
||||
}
|
||||
foreach my $alias (@$added_aliases) {
|
||||
trick_taint($alias);
|
||||
$dbh->do('INSERT INTO bugs_aliases (bug_id, alias) VALUES (?,?)',
|
||||
undef, $self->id, $alias);
|
||||
}
|
||||
# If any changes were found, record it in the activity log
|
||||
if (scalar @$removed_aliases || scalar @$added_aliases) {
|
||||
$changes->{alias} = [join(', ', @$removed_aliases), join(', ', @$added_aliases)];
|
||||
}
|
||||
|
||||
# Keywords
|
||||
my @old_kw_ids = map { $_->id } @{$old_bug->keyword_objects};
|
||||
my @new_kw_ids = map { $_->id } @{$self->keyword_objects};
|
||||
@ -1030,6 +988,12 @@ sub update {
|
||||
join(', ', @added_names)];
|
||||
}
|
||||
|
||||
# Flags
|
||||
my ($removed, $added) = Bugzilla::Flag->update_flags($self, $old_bug, $delta_ts);
|
||||
if ($removed || $added) {
|
||||
$changes->{'flagtypes.name'} = [$removed, $added];
|
||||
}
|
||||
|
||||
# Comments
|
||||
foreach my $comment (@{$self->{added_comments} || []}) {
|
||||
# Override the Comment's timestamp to be identical to the update
|
||||
@ -1052,9 +1016,6 @@ sub update {
|
||||
$user->id, $delta_ts, $comment->id);
|
||||
}
|
||||
|
||||
# Clear the cache of comments
|
||||
delete $self->{comments};
|
||||
|
||||
# Insert the values into the multiselect value tables
|
||||
my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT}
|
||||
Bugzilla->active_custom_fields;
|
||||
@ -1087,12 +1048,6 @@ sub update {
|
||||
join(', ', map { $_->name } @$added_see)];
|
||||
}
|
||||
|
||||
# Flags
|
||||
my ($removed, $added) = Bugzilla::Flag->update_flags($self, $old_bug, $delta_ts);
|
||||
if ($removed || $added) {
|
||||
$changes->{'flagtypes.name'} = [$removed, $added];
|
||||
}
|
||||
|
||||
$_->update foreach @{ $self->{_update_ref_bugs} || [] };
|
||||
delete $self->{_update_ref_bugs};
|
||||
|
||||
@ -1140,13 +1095,6 @@ sub update {
|
||||
$self->update_user_last_visit($user, $delta_ts);
|
||||
}
|
||||
|
||||
# If a user is no longer involved, remove their last visit entry
|
||||
my $last_visits =
|
||||
Bugzilla::BugUserLastVisit->match({ bug_id => $self->id });
|
||||
foreach my $lv (@$last_visits) {
|
||||
$lv->remove_from_db() unless $lv->user->is_involved_in_bug($self);
|
||||
}
|
||||
|
||||
# Update bug ignore data if user wants to ignore mail for this bug
|
||||
if (exists $self->{'bug_ignored'}) {
|
||||
my $bug_ignored_changed;
|
||||
@ -1362,38 +1310,32 @@ sub _send_bugmail {
|
||||
#####################################################################
|
||||
|
||||
sub _check_alias {
|
||||
my ($invocant, $aliases) = @_;
|
||||
$aliases = ref $aliases ? $aliases : [split(/[\s,]+/, $aliases)];
|
||||
my ($invocant, $alias) = @_;
|
||||
$alias = trim($alias);
|
||||
return undef if (!$alias);
|
||||
|
||||
# Remove empty aliases
|
||||
@$aliases = grep { $_ } @$aliases;
|
||||
|
||||
foreach my $alias (@$aliases) {
|
||||
$alias = trim($alias);
|
||||
|
||||
# Make sure the alias isn't too long.
|
||||
if (length($alias) > 40) {
|
||||
ThrowUserError("alias_too_long");
|
||||
}
|
||||
# Make sure the alias isn't just a number.
|
||||
if ($alias =~ /^\d+$/) {
|
||||
ThrowUserError("alias_is_numeric", { alias => $alias });
|
||||
}
|
||||
# Make sure the alias has no commas or spaces.
|
||||
if ($alias =~ /[, ]/) {
|
||||
ThrowUserError("alias_has_comma_or_space", { alias => $alias });
|
||||
}
|
||||
# Make sure the alias is unique, or that it's already our alias.
|
||||
my $other_bug = new Bugzilla::Bug($alias);
|
||||
if (!$other_bug->{error}
|
||||
&& (!ref $invocant || $other_bug->id != $invocant->id))
|
||||
{
|
||||
ThrowUserError("alias_in_use", { alias => $alias,
|
||||
bug_id => $other_bug->id });
|
||||
}
|
||||
# Make sure the alias isn't too long.
|
||||
if (length($alias) > 20) {
|
||||
ThrowUserError("alias_too_long");
|
||||
}
|
||||
# Make sure the alias isn't just a number.
|
||||
if ($alias =~ /^\d+$/) {
|
||||
ThrowUserError("alias_is_numeric", { alias => $alias });
|
||||
}
|
||||
# Make sure the alias has no commas or spaces.
|
||||
if ($alias =~ /[, ]/) {
|
||||
ThrowUserError("alias_has_comma_or_space", { alias => $alias });
|
||||
}
|
||||
# Make sure the alias is unique, or that it's already our alias.
|
||||
my $other_bug = new Bugzilla::Bug($alias);
|
||||
if (!$other_bug->{error}
|
||||
&& (!ref $invocant || $other_bug->id != $invocant->id))
|
||||
{
|
||||
ThrowUserError("alias_in_use", { alias => $alias,
|
||||
bug_id => $other_bug->id });
|
||||
}
|
||||
|
||||
return $aliases;
|
||||
return $alias;
|
||||
}
|
||||
|
||||
sub _check_assigned_to {
|
||||
@ -2430,15 +2372,7 @@ sub set_all {
|
||||
# there are lots of things that want to check if we added a comment.
|
||||
$self->add_comment($params->{'comment'}->{'body'},
|
||||
{ isprivate => $params->{'comment'}->{'is_private'},
|
||||
work_time => $params->{'work_time'},
|
||||
is_markdown => $params->{'comment'}->{'is_markdown'} });
|
||||
}
|
||||
|
||||
if (exists $params->{alias} && $params->{alias}{set}) {
|
||||
$params->{alias} = {
|
||||
add => $params->{alias}{set},
|
||||
remove => $self->alias,
|
||||
};
|
||||
work_time => $params->{'work_time'} });
|
||||
}
|
||||
|
||||
my %normal_set_all;
|
||||
@ -2465,7 +2399,6 @@ sub set_all {
|
||||
}
|
||||
|
||||
$self->_add_remove($params, 'cc');
|
||||
$self->_add_remove($params, 'alias');
|
||||
|
||||
# Theoretically you could move a product without ever specifying
|
||||
# a new assignee or qa_contact, or adding/removing any CCs. So,
|
||||
@ -2482,13 +2415,14 @@ sub _add_remove {
|
||||
my ($self, $params, $name) = @_;
|
||||
my @add = @{ $params->{$name}->{add} || [] };
|
||||
my @remove = @{ $params->{$name}->{remove} || [] };
|
||||
$name =~ s/s$// if $name ne 'alias';
|
||||
$name =~ s/s$//;
|
||||
my $add_method = "add_$name";
|
||||
my $remove_method = "remove_$name";
|
||||
$self->$add_method($_) foreach @add;
|
||||
$self->$remove_method($_) foreach @remove;
|
||||
}
|
||||
|
||||
sub set_alias { $_[0]->set('alias', $_[1]); }
|
||||
sub set_assigned_to {
|
||||
my ($self, $value) = @_;
|
||||
$self->set('assigned_to', $value);
|
||||
@ -2905,21 +2839,6 @@ sub remove_cc {
|
||||
@$cc_users = grep { $_->id != $user->id } @$cc_users;
|
||||
}
|
||||
|
||||
sub add_alias {
|
||||
my ($self, $alias) = @_;
|
||||
return if !$alias;
|
||||
my $aliases = $self->_check_alias($alias);
|
||||
$alias = $aliases->[0];
|
||||
my $bug_aliases = $self->alias;
|
||||
push(@$bug_aliases, $alias) if !grep($_ eq $alias, @$bug_aliases);
|
||||
}
|
||||
|
||||
sub remove_alias {
|
||||
my ($self, $alias) = @_;
|
||||
my $bug_aliases = $self->alias;
|
||||
@$bug_aliases = grep { $_ ne $alias } @$bug_aliases;
|
||||
}
|
||||
|
||||
# $bug->add_comment("comment", {isprivate => 1, work_time => 10.5,
|
||||
# type => CMT_NORMAL, extra_data => $data});
|
||||
sub add_comment {
|
||||
@ -3247,6 +3166,7 @@ sub tags {
|
||||
# These are accessors that don't need to access the database.
|
||||
# Keep them in alphabetical order.
|
||||
|
||||
sub alias { return $_[0]->{alias} }
|
||||
sub bug_file_loc { return $_[0]->{bug_file_loc} }
|
||||
sub bug_id { return $_[0]->{bug_id} }
|
||||
sub bug_severity { return $_[0]->{bug_severity} }
|
||||
@ -3356,24 +3276,6 @@ sub actual_time {
|
||||
return $self->{'actual_time'};
|
||||
}
|
||||
|
||||
sub alias {
|
||||
my ($self) = @_;
|
||||
return $self->{'alias'} if exists $self->{'alias'};
|
||||
return [] if $self->{'error'};
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
$self->{'alias'} = $dbh->selectcol_arrayref(
|
||||
q{SELECT alias
|
||||
FROM bugs_aliases
|
||||
WHERE bug_id = ?
|
||||
ORDER BY alias},
|
||||
undef, $self->bug_id);
|
||||
|
||||
$self->{'alias'} = [] if !scalar(@{$self->{'alias'}});
|
||||
|
||||
return $self->{'alias'};
|
||||
}
|
||||
|
||||
sub any_flags_requesteeble {
|
||||
my ($self) = @_;
|
||||
return $self->{'any_flags_requesteeble'}
|
||||
@ -3951,11 +3853,6 @@ sub choices {
|
||||
my @resolutions = grep($_->name, @{ $resolution_field->legal_values });
|
||||
$choices{'resolution'} = \@resolutions;
|
||||
|
||||
foreach my $key (keys %choices) {
|
||||
my $value = $self->$key;
|
||||
$choices{$key} = [grep { $_->is_active || $_->name eq $value } @{ $choices{$key} }];
|
||||
}
|
||||
|
||||
$self->{'choices'} = \%choices;
|
||||
return $self->{'choices'};
|
||||
}
|
||||
@ -3970,7 +3867,7 @@ sub bug_alias_to_id {
|
||||
my $dbh = Bugzilla->dbh;
|
||||
trick_taint($alias);
|
||||
return $dbh->selectrow_array(
|
||||
"SELECT bug_id FROM bugs_aliases WHERE alias = ?", undef, $alias);
|
||||
"SELECT bug_id FROM bugs WHERE alias = ?", undef, $alias);
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
@ -4599,16 +4496,6 @@ __END__
|
||||
|
||||
Ensures the accessors for custom fields are always created.
|
||||
|
||||
=item C<add_alias($alias)>
|
||||
|
||||
Adds an alias to the internal respresentation of the bug. You will need to
|
||||
call L<update> to make the changes permanent.
|
||||
|
||||
=item C<remove_alias($alias)>
|
||||
|
||||
Removes an alias from the internal respresentation of the bug. You will need to
|
||||
call L<update> to make the changes permanent.
|
||||
|
||||
=item C<update_user_last_visit($user, $last_visit)>
|
||||
|
||||
Creates or updates a L<Bugzilla::BugUserLastVisit> for this bug and the supplied
|
||||
@ -4776,6 +4663,8 @@ $user, the timestamp given as $last_visit.
|
||||
|
||||
=item remove_group
|
||||
|
||||
=item set_alias
|
||||
|
||||
=item set_dup_id
|
||||
|
||||
=item set_target_milestone
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugMail;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::User;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::Bugzilla;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::Bugzilla::Local;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl::Bugzilla);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::Debian;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::GitHub;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
@ -22,10 +21,8 @@ sub should_handle {
|
||||
|
||||
# GitHub issue URLs have only one form:
|
||||
# https://github.com/USER_OR_TEAM_OR_ORGANIZATION_NAME/REPOSITORY_NAME/issues/111
|
||||
# GitHub pull request URLs have only one form:
|
||||
# https://github.com/USER_OR_TEAM_OR_ORGANIZATION_NAME/REPOSITORY_NAME/pull/111
|
||||
return (lc($uri->authority) eq 'github.com'
|
||||
and $uri->path =~ m!^/[^/]+/[^/]+/(?:issues|pull)/\d+$!) ? 1 : 0;
|
||||
and $uri->path =~ m|^/[^/]+/[^/]+/issues/\d+$|) ? 1 : 0;
|
||||
}
|
||||
|
||||
sub _check_value {
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::Google;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::JIRA;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::Launchpad;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::MantisBT;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::SourceForge;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
@ -22,18 +21,12 @@ sub should_handle {
|
||||
|
||||
# SourceForge tracker URLs have only one form:
|
||||
# http://sourceforge.net/tracker/?func=detail&aid=111&group_id=111&atid=111
|
||||
# SourceForge Allura ticket URLs have several forms:
|
||||
# http://sourceforge.net/p/project/bugs/12345/
|
||||
# http://sourceforge.net/p/project/feature-requests/12345/
|
||||
# http://sourceforge.net/p/project/patches/12345/
|
||||
# http://sourceforge.net/p/project/support-requests/12345/
|
||||
return (lc($uri->authority) eq 'sourceforge.net'
|
||||
and (($uri->path eq '/tracker/'
|
||||
and $uri->query_param('func') eq 'detail'
|
||||
and $uri->query_param('aid')
|
||||
and $uri->query_param('group_id')
|
||||
and $uri->query_param('atid'))
|
||||
or $uri->path =~ m!^/p/[^/]+/(?:bugs|feature-requests|patches|support-requests)/\d+/?$!)) ? 1 : 0;
|
||||
and $uri->path =~ m|/tracker/|
|
||||
and $uri->query_param('func') eq 'detail'
|
||||
and $uri->query_param('aid')
|
||||
and $uri->query_param('group_id')
|
||||
and $uri->query_param('atid')) ? 1 : 0;
|
||||
}
|
||||
|
||||
sub _check_value {
|
||||
@ -44,11 +37,6 @@ sub _check_value {
|
||||
# Remove any # part if there is one.
|
||||
$uri->fragment(undef);
|
||||
|
||||
# Make sure the trailing slash is present
|
||||
my $path = $uri->path;
|
||||
$path =~ s!/*$!/!;
|
||||
$uri->path($path);
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUrl::Trac;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::BugUrl);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::BugUserLastVisit;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
@ -39,13 +38,6 @@ sub bug_id { return $_[0]->{bug_id} }
|
||||
sub user_id { return $_[0]->{user_id} }
|
||||
sub last_visit_ts { return $_[0]->{last_visit_ts} }
|
||||
|
||||
sub user {
|
||||
my $self = shift;
|
||||
|
||||
$self->{user} //= Bugzilla::User->new({ id => $self->user_id, cache => 1 });
|
||||
return $self->{user};
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
@ -88,6 +80,4 @@ listed below.
|
||||
|
||||
=item C<last_visit_ts>
|
||||
|
||||
=item C<user>
|
||||
|
||||
=back
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::CGI;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(CGI);
|
||||
|
||||
@ -362,7 +361,6 @@ sub header {
|
||||
|
||||
sub param {
|
||||
my $self = shift;
|
||||
local $CGI::LIST_CONTEXT_WARN = 0;
|
||||
|
||||
# When we are just requesting the value of a parameter...
|
||||
if (scalar(@_) == 1) {
|
||||
@ -374,7 +372,10 @@ sub param {
|
||||
if (!scalar(@result)
|
||||
&& $self->request_method && $self->request_method eq 'POST')
|
||||
{
|
||||
@result = $self->url_param(@_);
|
||||
# Some servers fail to set the QUERY_STRING parameter, which
|
||||
# causes undef issues
|
||||
$ENV{'QUERY_STRING'} = '' unless exists $ENV{'QUERY_STRING'};
|
||||
@result = $self->SUPER::url_param(@_);
|
||||
}
|
||||
|
||||
# Fix UTF-8-ness of input parameters.
|
||||
@ -399,14 +400,6 @@ sub param {
|
||||
return $self->SUPER::param(@_);
|
||||
}
|
||||
|
||||
sub url_param {
|
||||
my $self = shift;
|
||||
# Some servers fail to set the QUERY_STRING parameter, which
|
||||
# causes undef issues
|
||||
$ENV{'QUERY_STRING'} //= '';
|
||||
return $self->SUPER::url_param(@_);
|
||||
}
|
||||
|
||||
sub _fix_utf8 {
|
||||
my $input = shift;
|
||||
# The is_utf8 is here in case CGI gets smart about utf8 someday.
|
||||
@ -738,8 +731,6 @@ L<CGI|CGI>, L<CGI::Cookie|CGI::Cookie>
|
||||
|
||||
=item param
|
||||
|
||||
=item url_param
|
||||
|
||||
=item header
|
||||
|
||||
=back
|
||||
|
||||
@ -15,7 +15,6 @@ package Bugzilla::Chart;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::Util;
|
||||
@ -96,8 +95,9 @@ sub init {
|
||||
if ($self->{'datefrom'} && $self->{'dateto'} &&
|
||||
$self->{'datefrom'} > $self->{'dateto'})
|
||||
{
|
||||
ThrowUserError('misarranged_dates', { 'datefrom' => scalar $cgi->param('datefrom'),
|
||||
'dateto' => scalar $cgi->param('dateto') });
|
||||
ThrowUserError("misarranged_dates",
|
||||
{'datefrom' => $cgi->param('datefrom'),
|
||||
'dateto' => $cgi->param('dateto')});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Classification;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Field;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Comment;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
@ -43,7 +42,6 @@ use constant DB_COLUMNS => qw(
|
||||
already_wrapped
|
||||
type
|
||||
extra_data
|
||||
is_markdown
|
||||
);
|
||||
|
||||
use constant UPDATE_COLUMNS => qw(
|
||||
@ -66,7 +64,6 @@ use constant VALIDATORS => {
|
||||
work_time => \&_check_work_time,
|
||||
thetext => \&_check_thetext,
|
||||
isprivate => \&_check_isprivate,
|
||||
is_markdown => \&Bugzilla::Object::check_boolean,
|
||||
extra_data => \&_check_extra_data,
|
||||
type => \&_check_type,
|
||||
};
|
||||
@ -179,7 +176,6 @@ sub body { return $_[0]->{'thetext'}; }
|
||||
sub bug_id { return $_[0]->{'bug_id'}; }
|
||||
sub creation_ts { return $_[0]->{'bug_when'}; }
|
||||
sub is_private { return $_[0]->{'isprivate'}; }
|
||||
sub is_markdown { return $_[0]->{'is_markdown'}; }
|
||||
sub work_time {
|
||||
# Work time is returned as a string (see bug 607909)
|
||||
return 0 if $_[0]->{'work_time'} + 0 == 0;
|
||||
@ -277,7 +273,6 @@ sub body_full {
|
||||
sub set_is_private { $_[0]->set('isprivate', $_[1]); }
|
||||
sub set_type { $_[0]->set('type', $_[1]); }
|
||||
sub set_extra_data { $_[0]->set('extra_data', $_[1]); }
|
||||
sub set_is_markdown { $_[0]->set('is_markdown', $_[1]); }
|
||||
|
||||
sub add_tag {
|
||||
my ($self, $tag) = @_;
|
||||
@ -526,10 +521,6 @@ C<string> Time spent as related to this comment.
|
||||
|
||||
C<boolean> Comment is marked as private.
|
||||
|
||||
=item C<is_markdown>
|
||||
|
||||
C<boolean> Whether this comment needs L<Markdown|Bugzilla::Markdown> rendering to be applied.
|
||||
|
||||
=item C<already_wrapped>
|
||||
|
||||
If this comment is stored in the database word-wrapped, this will be C<1>.
|
||||
@ -625,16 +616,6 @@ A string, the full text of the comment as it would be displayed to an end-user.
|
||||
|
||||
=cut
|
||||
|
||||
=head2 Modifiers
|
||||
|
||||
=over
|
||||
|
||||
=item C<set_is_markdown>
|
||||
|
||||
Sets whether this comment needs L<Markdown|Bugzilla::Markdown> rendering to be applied.
|
||||
|
||||
=back
|
||||
|
||||
=head1 B<Methods in need of POD>
|
||||
|
||||
=over
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Comment::TagWeights;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Component;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object);
|
||||
|
||||
|
||||
@ -9,19 +9,12 @@ package Bugzilla::Config;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Exporter);
|
||||
use autodie qw(:default);
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Hook;
|
||||
use Bugzilla::Util qw(trick_taint);
|
||||
|
||||
use JSON::XS;
|
||||
use File::Slurp;
|
||||
use Data::Dumper;
|
||||
use File::Temp;
|
||||
use File::Basename;
|
||||
|
||||
# Don't export localvars by default - people should have to explicitly
|
||||
# ask for it, as a (probably futile) attempt to stop code using it
|
||||
@ -98,35 +91,8 @@ sub SetParam {
|
||||
sub update_params {
|
||||
my ($params) = @_;
|
||||
my $answer = Bugzilla->installation_answers;
|
||||
my $datadir = bz_locations()->{'datadir'};
|
||||
my $param;
|
||||
|
||||
# If the old data/params file using Data::Dumper output still exists,
|
||||
# read it. It will be deleted once the parameters are stored in the new
|
||||
# data/params.json file.
|
||||
my $old_file = "$datadir/params";
|
||||
|
||||
if (-e $old_file) {
|
||||
require Safe;
|
||||
my $s = new Safe;
|
||||
|
||||
$s->rdo($old_file);
|
||||
die "Error reading $old_file: $!" if $!;
|
||||
die "Error evaluating $old_file: $@" if $@;
|
||||
|
||||
# Now read the param back out from the sandbox.
|
||||
$param = \%{ $s->varglob('param') };
|
||||
}
|
||||
else {
|
||||
# Rename params.js to params.json if checksetup.pl
|
||||
# was executed with an earlier version of this change
|
||||
rename "$old_file.js", "$old_file.json"
|
||||
if -e "$old_file.js" && !-e "$old_file.json";
|
||||
|
||||
# Read the new data/params.json file.
|
||||
$param = read_param_file();
|
||||
}
|
||||
|
||||
my $param = read_param_file();
|
||||
my %new_params;
|
||||
|
||||
# If we didn't return any param values, then this is a new installation.
|
||||
@ -185,19 +151,16 @@ sub update_params {
|
||||
}
|
||||
|
||||
# Old mail_delivery_method choices contained no uppercase characters
|
||||
my $mta = $param->{'mail_delivery_method'};
|
||||
if ($mta) {
|
||||
if ($mta !~ /[A-Z]/) {
|
||||
my %translation = (
|
||||
'sendmail' => 'Sendmail',
|
||||
'smtp' => 'SMTP',
|
||||
'qmail' => 'Qmail',
|
||||
'testfile' => 'Test',
|
||||
'none' => 'None');
|
||||
$param->{'mail_delivery_method'} = $translation{$mta};
|
||||
}
|
||||
# This will force the parameter to be reset to its default value.
|
||||
delete $param->{'mail_delivery_method'} if $param->{'mail_delivery_method'} eq 'Qmail';
|
||||
if (exists $param->{'mail_delivery_method'}
|
||||
&& $param->{'mail_delivery_method'} !~ /[A-Z]/) {
|
||||
my $method = $param->{'mail_delivery_method'};
|
||||
my %translation = (
|
||||
'sendmail' => 'Sendmail',
|
||||
'smtp' => 'SMTP',
|
||||
'qmail' => 'Qmail',
|
||||
'testfile' => 'Test',
|
||||
'none' => 'None');
|
||||
$param->{'mail_delivery_method'} = $translation{$method};
|
||||
}
|
||||
|
||||
# Convert the old "ssl" parameter to the new "ssl_redirect" parameter.
|
||||
@ -247,6 +210,7 @@ sub update_params {
|
||||
}
|
||||
|
||||
# Write any old parameters to old-params.txt
|
||||
my $datadir = bz_locations()->{'datadir'};
|
||||
my $old_param_file = "$datadir/old-params.txt";
|
||||
if (scalar(keys %oldparams)) {
|
||||
my $op_file = new IO::File($old_param_file, '>>', 0600)
|
||||
@ -256,9 +220,12 @@ sub update_params {
|
||||
" and so have been\nmoved from your parameters file into",
|
||||
" $old_param_file:\n";
|
||||
|
||||
local $Data::Dumper::Terse = 1;
|
||||
local $Data::Dumper::Indent = 0;
|
||||
|
||||
my $comma = "";
|
||||
foreach my $item (keys %oldparams) {
|
||||
print $op_file "\n\n$item:\n" . $oldparams{$item} . "\n";
|
||||
print $op_file "\n\n$item:\n" . Data::Dumper->Dump([$oldparams{$item}]) . "\n";
|
||||
print "${comma}$item";
|
||||
$comma = ", ";
|
||||
}
|
||||
@ -289,11 +256,6 @@ sub update_params {
|
||||
|
||||
write_params($param);
|
||||
|
||||
if (-e $old_file) {
|
||||
unlink $old_file;
|
||||
say "$old_file has been converted into $old_file.json, using the JSON format.";
|
||||
}
|
||||
|
||||
# Return deleted params and values so that checksetup.pl has a chance
|
||||
# to convert old params to new data.
|
||||
return %oldparams;
|
||||
@ -302,10 +264,22 @@ sub update_params {
|
||||
sub write_params {
|
||||
my ($param_data) = @_;
|
||||
$param_data ||= Bugzilla->params;
|
||||
my $param_file = bz_locations()->{'datadir'} . '/params.json';
|
||||
|
||||
my $json_data = JSON::XS->new->canonical->pretty->encode($param_data);
|
||||
write_file($param_file, { binmode => ':utf8', atomic => 1 }, \$json_data);
|
||||
my $datadir = bz_locations()->{'datadir'};
|
||||
my $param_file = "$datadir/params";
|
||||
|
||||
local $Data::Dumper::Sortkeys = 1;
|
||||
|
||||
my ($fh, $tmpname) = File::Temp::tempfile('params.XXXXX',
|
||||
DIR => $datadir );
|
||||
|
||||
print $fh (Data::Dumper->Dump([$param_data], ['*param']))
|
||||
|| die "Can't write param file: $!";
|
||||
|
||||
close $fh;
|
||||
|
||||
rename $tmpname, $param_file
|
||||
or die "Can't rename $tmpname to $param_file: $!";
|
||||
|
||||
# It's not common to edit parameters and loading
|
||||
# Bugzilla::Install::Filesystem is slow.
|
||||
@ -319,23 +293,21 @@ sub write_params {
|
||||
|
||||
sub read_param_file {
|
||||
my %params;
|
||||
my $file = bz_locations()->{'datadir'} . '/params.json';
|
||||
my $datadir = bz_locations()->{'datadir'};
|
||||
if (-e "$datadir/params") {
|
||||
# Note that checksetup.pl sets file permissions on '$datadir/params'
|
||||
|
||||
if (-e $file) {
|
||||
my $data;
|
||||
read_file($file, binmode => ':utf8', buf_ref => \$data);
|
||||
# Using Safe mode is _not_ a guarantee of safety if someone does
|
||||
# manage to write to the file. However, it won't hurt...
|
||||
# See bug 165144 for not needing to eval this at all
|
||||
my $s = new Safe;
|
||||
|
||||
# If params.json has been manually edited and e.g. some quotes are
|
||||
# missing, we don't want JSON::XS to leak the content of the file
|
||||
# to all users in its error message, so we have to eval'uate it.
|
||||
%params = eval { %{JSON::XS->new->decode($data)} };
|
||||
if ($@) {
|
||||
my $error_msg = (basename($0) eq 'checksetup.pl') ?
|
||||
$@ : 'run checksetup.pl to see the details.';
|
||||
die "Error parsing $file: $error_msg";
|
||||
}
|
||||
# JSON::XS doesn't detaint data for us.
|
||||
trick_taint($params{$_}) foreach keys %params;
|
||||
$s->rdo("$datadir/params");
|
||||
die "Error reading $datadir/params: $!" if $!;
|
||||
die "Error evaluating $datadir/params: $@" if $@;
|
||||
|
||||
# Now read the param back out from the sandbox
|
||||
%params = %{$s->varglob('param')};
|
||||
}
|
||||
elsif ($ENV{'SERVER_SOFTWARE'}) {
|
||||
# We're in a CGI, but the params file doesn't exist. We can't
|
||||
@ -345,7 +317,7 @@ sub read_param_file {
|
||||
# so that the user sees the error.
|
||||
require CGI::Carp;
|
||||
CGI::Carp->import('fatalsToBrowser');
|
||||
die "The $file file does not exist."
|
||||
die "The $datadir/params file does not exist."
|
||||
. ' You probably need to run checksetup.pl.',
|
||||
}
|
||||
return \%params;
|
||||
@ -401,7 +373,7 @@ specified.
|
||||
Description: Writes the parameters to disk.
|
||||
|
||||
Params: C<$params> (optional) - A hashref to write to the disk
|
||||
instead of C<Bugzilla-E<gt>params>. Used only by
|
||||
instead of C<Bugzilla->params>. Used only by
|
||||
C<update_params>.
|
||||
|
||||
Returns: nothing
|
||||
@ -409,12 +381,12 @@ Returns: nothing
|
||||
=item C<read_param_file()>
|
||||
|
||||
Description: Most callers should never need this. This is used
|
||||
by C<Bugzilla-E<gt>params> to directly read C<$datadir/params.json>
|
||||
and load it into memory. Use C<Bugzilla-E<gt>params> instead.
|
||||
by C<Bugzilla->params> to directly read C<$datadir/params>
|
||||
and load it into memory. Use C<Bugzilla->params> instead.
|
||||
|
||||
Params: none
|
||||
|
||||
Returns: A hashref containing the current params in C<$datadir/params.json>.
|
||||
Returns: A hashref containing the current params in C<$datadir/params>.
|
||||
|
||||
=item C<param_panels()>
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Admin;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Advanced;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Attachment;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
@ -37,14 +36,6 @@ sub get_param_list {
|
||||
default => 0
|
||||
},
|
||||
|
||||
{
|
||||
name => 'xsendfile_header',
|
||||
type => 's',
|
||||
choices => ['off', 'X-Sendfile', 'X-Accel-Redirect', 'X-LIGHTTPD-send-file'],
|
||||
default => 'off',
|
||||
checker => \&check_multi
|
||||
},
|
||||
|
||||
{
|
||||
name => 'maxattachmentsize',
|
||||
type => 't',
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Auth;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
@ -114,14 +113,7 @@ sub get_param_list {
|
||||
'letters_numbers_specialchars' ],
|
||||
default => 'no_constraints',
|
||||
checker => \&check_multi
|
||||
},
|
||||
|
||||
{
|
||||
name => 'password_check_on_login',
|
||||
type => 'b',
|
||||
default => '1'
|
||||
},
|
||||
);
|
||||
} );
|
||||
return @param_list;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::BugChange;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
use Bugzilla::Status;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::BugFields;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
use Bugzilla::Field;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Common;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Email::Address;
|
||||
use Socket;
|
||||
@ -29,7 +28,7 @@ use parent qw(Exporter);
|
||||
check_mail_delivery_method check_notification check_utf8
|
||||
check_bug_status check_smtp_auth check_theschwartz_available
|
||||
check_maxattachmentsize check_email check_smtp_ssl
|
||||
check_comment_taggers_group check_smtp_server
|
||||
check_comment_taggers_group
|
||||
);
|
||||
|
||||
# Checking functions for the various values
|
||||
@ -342,33 +341,6 @@ sub check_notification {
|
||||
return "";
|
||||
}
|
||||
|
||||
sub check_smtp_server {
|
||||
my $host = shift;
|
||||
my $port;
|
||||
|
||||
if ($host =~ /:/) {
|
||||
($host, $port) = split(/:/, $host, 2);
|
||||
unless ($port && detaint_natural($port)) {
|
||||
return "Invalid port. It must be an integer (typically 25, 465 or 587)";
|
||||
}
|
||||
}
|
||||
trick_taint($host);
|
||||
# Let's first try to connect using SSL. If this fails, we fall back to
|
||||
# an unencrypted connection.
|
||||
foreach my $method (['Net::SMTP::SSL', 465], ['Net::SMTP', 25]) {
|
||||
my ($class, $default_port) = @$method;
|
||||
next if $class eq 'Net::SMTP::SSL' && !Bugzilla->feature('smtp_ssl');
|
||||
eval "require $class";
|
||||
my $smtp = $class->new($host, Port => $port || $default_port, Timeout => 5);
|
||||
if ($smtp) {
|
||||
# The connection works!
|
||||
$smtp->quit;
|
||||
return '';
|
||||
}
|
||||
}
|
||||
return "Cannot connect to $host" . ($port ? " using port $port" : "");
|
||||
}
|
||||
|
||||
sub check_smtp_auth {
|
||||
my $username = shift;
|
||||
if ($username and !Bugzilla->feature('smtp_auth')) {
|
||||
@ -525,8 +497,6 @@ valid group is provided.
|
||||
|
||||
=item check_shadowdb
|
||||
|
||||
=item check_smtp_server
|
||||
|
||||
=item check_smtp_auth
|
||||
|
||||
=item check_url
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Core;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::DependencyGraph;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
@ -21,7 +20,7 @@ sub get_param_list {
|
||||
{
|
||||
name => 'webdotbase',
|
||||
type => 't',
|
||||
default => '',
|
||||
default => 'http://www.research.att.com/~north/cgi-bin/webdot.cgi/%urlbase%',
|
||||
checker => \&check_webdotbase
|
||||
},
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::General;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::GroupSecurity;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
use Bugzilla::Group;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::LDAP;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,9 +9,15 @@ package Bugzilla::Config::MTA;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
# Return::Value 1.666002 pollutes the error log with warnings about this
|
||||
# deprecated module. We have to set NO_CLUCK = 1 before loading Email::Send
|
||||
# to disable these warnings.
|
||||
BEGIN {
|
||||
$Return::Value::NO_CLUCK = 1;
|
||||
}
|
||||
use Email::Send;
|
||||
|
||||
our $sortkey = 1200;
|
||||
|
||||
@ -21,7 +27,9 @@ sub get_param_list {
|
||||
{
|
||||
name => 'mail_delivery_method',
|
||||
type => 's',
|
||||
choices => ['Sendmail', 'SMTP', 'Test', 'None'],
|
||||
# Bugzilla is not ready yet to send mails to newsgroups, and 'IO'
|
||||
# is of no use for now as we already have our own 'Test' mode.
|
||||
choices => [grep {$_ ne 'NNTP' && $_ ne 'IO'} Email::Send->new()->all_mailers(), 'None'],
|
||||
default => 'Sendmail',
|
||||
checker => \&check_mail_delivery_method
|
||||
},
|
||||
@ -42,8 +50,7 @@ sub get_param_list {
|
||||
{
|
||||
name => 'smtpserver',
|
||||
type => 't',
|
||||
default => 'localhost',
|
||||
checker => \&check_smtp_server
|
||||
default => 'localhost'
|
||||
},
|
||||
{
|
||||
name => 'smtp_username',
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Memcached;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
52
mozilla/webtools/bugzilla/Bugzilla/Config/PatchViewer.pm
Normal file
52
mozilla/webtools/bugzilla/Bugzilla/Config/PatchViewer.pm
Normal file
@ -0,0 +1,52 @@
|
||||
# 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::Config::PatchViewer;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
our $sortkey = 1300;
|
||||
|
||||
sub get_param_list {
|
||||
my $class = shift;
|
||||
my @param_list = (
|
||||
{
|
||||
name => 'cvsroot',
|
||||
type => 't',
|
||||
default => '',
|
||||
},
|
||||
|
||||
{
|
||||
name => 'cvsroot_get',
|
||||
type => 't',
|
||||
default => '',
|
||||
},
|
||||
|
||||
{
|
||||
name => 'bonsai_url',
|
||||
type => 't',
|
||||
default => ''
|
||||
},
|
||||
|
||||
{
|
||||
name => 'lxr_url',
|
||||
type => 't',
|
||||
default => ''
|
||||
},
|
||||
|
||||
{
|
||||
name => 'lxr_root',
|
||||
type => 't',
|
||||
default => '',
|
||||
} );
|
||||
return @param_list;
|
||||
}
|
||||
|
||||
1;
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::Query;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::RADIUS;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::ShadowDB;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Config::UserMatch;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Config::Common;
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Constants;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Exporter);
|
||||
|
||||
@ -26,8 +25,6 @@ use Memoize;
|
||||
|
||||
bz_locations
|
||||
|
||||
CONCATENATE_ASSETS
|
||||
|
||||
IS_NULL
|
||||
NOT_NULL
|
||||
|
||||
@ -193,14 +190,6 @@ use Memoize;
|
||||
AUDIT_REMOVE
|
||||
|
||||
MOST_FREQUENT_THRESHOLD
|
||||
|
||||
MARKDOWN_TAB_WIDTH
|
||||
|
||||
EMAIL_LIMIT_PER_MINUTE
|
||||
EMAIL_LIMIT_PER_HOUR
|
||||
EMAIL_LIMIT_EXCEPTION
|
||||
|
||||
JOB_QUEUE_VIEW_MAX_JOBS
|
||||
);
|
||||
|
||||
@Bugzilla::Constants::EXPORT_OK = qw(contenttypes);
|
||||
@ -208,7 +197,7 @@ use Memoize;
|
||||
# CONSTANTS
|
||||
#
|
||||
# Bugzilla version
|
||||
use constant BUGZILLA_VERSION => "5.1";
|
||||
use constant BUGZILLA_VERSION => "4.5.4+";
|
||||
|
||||
# A base link to the current REST Documentation. We place it here
|
||||
# as it will need to be updated to whatever the current release is.
|
||||
@ -218,11 +207,6 @@ use constant REST_DOC => "http://www.bugzilla.org/docs/tip/en/html/api/";
|
||||
use constant REMOTE_FILE => 'http://updates.bugzilla.org/bugzilla-update.xml';
|
||||
use constant LOCAL_FILE => 'bugzilla-update.xml'; # Relative to datadir.
|
||||
|
||||
# When true CSS and JavaScript assets will be concatanted and minified at
|
||||
# run-time, to reduce the number of requests required to render a page.
|
||||
# Setting this to a false value can help debugging.
|
||||
use constant CONCATENATE_ASSETS => 1;
|
||||
|
||||
# These are unique values that are unlikely to match a string or a number,
|
||||
# to be used in criteria for match() functions and other things. They start
|
||||
# and end with spaces because most Bugzilla stuff has trim() called on it,
|
||||
@ -643,22 +627,6 @@ use constant AUDIT_REMOVE => '__remove__';
|
||||
# on the "Most frequently reported bugs" page.
|
||||
use constant MOST_FREQUENT_THRESHOLD => 2;
|
||||
|
||||
# The number of spaces used to represent each tab character
|
||||
# by Markdown engine
|
||||
use constant MARKDOWN_TAB_WIDTH => 2;
|
||||
|
||||
# The maximum number of emails per minute and hour a recipient can receive.
|
||||
# Email will be queued/backlogged to avoid exceeeding these limits.
|
||||
# Setting a limit to 0 will disable this feature.
|
||||
use constant EMAIL_LIMIT_PER_MINUTE => 1000;
|
||||
use constant EMAIL_LIMIT_PER_HOUR => 2500;
|
||||
# Don't change this exception message.
|
||||
use constant EMAIL_LIMIT_EXCEPTION => "email_limit_exceeded\n";
|
||||
|
||||
# The maximum number of jobs to show when viewing the job queue
|
||||
# (view_job_queue.cgi).
|
||||
use constant JOB_QUEUE_VIEW_MAX_JOBS => 500;
|
||||
|
||||
sub bz_locations {
|
||||
# Force memoize() to re-compute data per project, to avoid
|
||||
# sharing the same data across different installations.
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::DB;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use DBI;
|
||||
|
||||
@ -17,7 +16,6 @@ use DBI;
|
||||
use parent -norequire, qw(DBI::db);
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Mailer;
|
||||
use Bugzilla::Install::Requirements;
|
||||
use Bugzilla::Install::Util qw(install_string);
|
||||
use Bugzilla::Install::Localconfig;
|
||||
@ -115,6 +113,7 @@ sub connect_shadow {
|
||||
}
|
||||
|
||||
sub connect_main {
|
||||
my $lc = Bugzilla->localconfig;
|
||||
return _connect(Bugzilla->localconfig);
|
||||
}
|
||||
|
||||
@ -580,11 +579,8 @@ sub bz_add_column {
|
||||
my $current_def = $self->bz_column_info($table, $name);
|
||||
|
||||
if (!$current_def) {
|
||||
# REFERENCES need to happen later and not be created right away
|
||||
my $trimmed_def = dclone($new_def);
|
||||
delete $trimmed_def->{REFERENCES};
|
||||
my @statements = $self->_bz_real_schema->get_add_column_ddl(
|
||||
$table, $name, $trimmed_def,
|
||||
$table, $name, $new_def,
|
||||
defined $init_value ? $self->quote($init_value) : undef);
|
||||
print get_text('install_column_add',
|
||||
{ column => $name, table => $table }) . "\n"
|
||||
@ -1219,7 +1215,6 @@ sub bz_commit_transaction {
|
||||
} elsif ($self->bz_in_transaction) {
|
||||
$self->commit();
|
||||
$self->{private_bz_transaction_count} = 0;
|
||||
Bugzilla::Mailer->send_staged_mail();
|
||||
} else {
|
||||
ThrowCodeError('not_in_transaction');
|
||||
}
|
||||
@ -2320,11 +2315,7 @@ values to.
|
||||
|
||||
=item C<$name> - the name of the new column
|
||||
|
||||
=item C<$definition> - A hashref abstract column definition for the new column.
|
||||
Note, if a C<REFERENCES> definition is included to create a foreign key
|
||||
relationship, it will be created later instead of when the column is added.
|
||||
Normally foreign keys are added by C<checksetup.pl> at the end all at the same
|
||||
time.
|
||||
=item C<\%definition> - Abstract column definition for the new column
|
||||
|
||||
=item C<$init_value> (optional) - An initial value to set the column
|
||||
to. Required if your column is NOT NULL and has no DEFAULT set.
|
||||
|
||||
@ -23,7 +23,6 @@ package Bugzilla::DB::Mysql;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::DB);
|
||||
|
||||
@ -87,17 +86,16 @@ sub new {
|
||||
|
||||
bless ($self, $class);
|
||||
|
||||
# Check for MySQL modes.
|
||||
# Bug 321645 - disable MySQL strict mode, if set
|
||||
my ($var, $sql_mode) = $self->selectrow_array(
|
||||
"SHOW VARIABLES LIKE 'sql\\_mode'");
|
||||
|
||||
# Disable ANSI and strict modes, else Bugzilla will crash.
|
||||
if ($sql_mode) {
|
||||
# STRICT_TRANS_TABLE or STRICT_ALL_TABLES enable MySQL strict mode,
|
||||
# causing bug 321645. TRADITIONAL sets these modes (among others) as
|
||||
# well, so it has to be stipped as well
|
||||
my $new_sql_mode =
|
||||
join(",", grep {$_ !~ /^(?:ANSI|STRICT_(?:TRANS|ALL)_TABLES|TRADITIONAL)$/}
|
||||
join(",", grep {$_ !~ /^STRICT_(?:TRANS|ALL)_TABLES|TRADITIONAL$/}
|
||||
split(/,/, $sql_mode));
|
||||
|
||||
if ($sql_mode ne $new_sql_mode) {
|
||||
@ -294,6 +292,7 @@ sub _bz_get_initial_schema {
|
||||
sub bz_check_server_version {
|
||||
my $self = shift;
|
||||
|
||||
my $lc = Bugzilla->localconfig;
|
||||
if (lc(Bugzilla->localconfig->{db_name}) eq 'mysql') {
|
||||
die "It is not safe to run Bugzilla inside a database named 'mysql'.\n"
|
||||
. " Please pick a different value for \$db_name in localconfig.\n";
|
||||
|
||||
@ -23,7 +23,6 @@ package Bugzilla::DB::Oracle;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::DB);
|
||||
|
||||
@ -722,7 +721,6 @@ package Bugzilla::DB::Oracle::st;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent -norequire, qw(DBI::st);
|
||||
|
||||
|
||||
@ -23,7 +23,6 @@ package Bugzilla::DB::Pg;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::Version;
|
||||
@ -231,9 +230,6 @@ sub bz_setup_database {
|
||||
my $self = shift;
|
||||
$self->SUPER::bz_setup_database(@_);
|
||||
|
||||
my ($has_plpgsql) = $self->selectrow_array("SELECT COUNT(*) FROM pg_language WHERE lanname = 'plpgsql'");
|
||||
$self->do('CREATE LANGUAGE plpgsql') unless $has_plpgsql;
|
||||
|
||||
# Custom Functions
|
||||
|
||||
# -Copyright © 2013 Joshua D. Burns (JDBurnZ) and Message In Action LLC
|
||||
|
||||
@ -17,7 +17,6 @@ package Bugzilla::DB::Schema;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Error;
|
||||
use Bugzilla::Hook;
|
||||
@ -278,8 +277,11 @@ use constant ABSTRACT_SCHEMA => {
|
||||
remaining_time => {TYPE => 'decimal(7,2)',
|
||||
NOTNULL => 1, DEFAULT => '0'},
|
||||
deadline => {TYPE => 'DATETIME'},
|
||||
alias => {TYPE => 'varchar(20)'},
|
||||
],
|
||||
INDEXES => [
|
||||
bugs_alias_idx => {FIELDS => ['alias'],
|
||||
TYPE => 'UNIQUE'},
|
||||
bugs_assigned_to_idx => ['assigned_to'],
|
||||
bugs_creation_ts_idx => ['creation_ts'],
|
||||
bugs_delta_ts_idx => ['delta_ts'],
|
||||
@ -356,21 +358,6 @@ use constant ABSTRACT_SCHEMA => {
|
||||
],
|
||||
},
|
||||
|
||||
bugs_aliases => {
|
||||
FIELDS => [
|
||||
alias => {TYPE => 'varchar(40)', NOTNULL => 1},
|
||||
bug_id => {TYPE => 'INT3',
|
||||
REFERENCES => {TABLE => 'bugs',
|
||||
COLUMN => 'bug_id',
|
||||
DELETE => 'CASCADE'}},
|
||||
],
|
||||
INDEXES => [
|
||||
bugs_aliases_bug_id_idx => ['bug_id'],
|
||||
bugs_aliases_alias_idx => {FIELDS => ['alias'],
|
||||
TYPE => 'UNIQUE'},
|
||||
],
|
||||
},
|
||||
|
||||
cc => {
|
||||
FIELDS => [
|
||||
bug_id => {TYPE => 'INT3', NOTNULL => 1,
|
||||
@ -410,8 +397,7 @@ use constant ABSTRACT_SCHEMA => {
|
||||
DEFAULT => 'FALSE'},
|
||||
type => {TYPE => 'INT2', NOTNULL => 1,
|
||||
DEFAULT => '0'},
|
||||
extra_data => {TYPE => 'varchar(255)'},
|
||||
is_markdown => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'}
|
||||
extra_data => {TYPE => 'varchar(255)'}
|
||||
],
|
||||
INDEXES => [
|
||||
longdescs_bug_id_idx => [qw(bug_id work_time)],
|
||||
@ -1191,7 +1177,7 @@ use constant ABSTRACT_SCHEMA => {
|
||||
issuedate => {TYPE => 'DATETIME', NOTNULL => 1} ,
|
||||
token => {TYPE => 'varchar(16)', NOTNULL => 1,
|
||||
PRIMARYKEY => 1},
|
||||
tokentype => {TYPE => 'varchar(16)', NOTNULL => 1} ,
|
||||
tokentype => {TYPE => 'varchar(8)', NOTNULL => 1} ,
|
||||
eventdata => {TYPE => 'TINYTEXT'},
|
||||
],
|
||||
INDEXES => [
|
||||
@ -1630,28 +1616,6 @@ use constant ABSTRACT_SCHEMA => {
|
||||
],
|
||||
},
|
||||
|
||||
# BUGMAIL
|
||||
# -------
|
||||
|
||||
mail_staging => {
|
||||
FIELDS => [
|
||||
id => {TYPE => 'INTSERIAL', PRIMARYKEY => 1, NOTNULL => 1},
|
||||
message => {TYPE => 'LONGBLOB', NOTNULL => 1},
|
||||
],
|
||||
},
|
||||
|
||||
email_rates => {
|
||||
FIELDS => [
|
||||
id => {TYPE => 'INTSERIAL', NOTNULL => 1,
|
||||
PRIMARYKEY => 1},
|
||||
recipient => {TYPE => 'varchar(255)', NOTNULL => 1},
|
||||
message_ts => {TYPE => 'DATETIME', NOTNULL => 1},
|
||||
],
|
||||
INDEXES => [
|
||||
email_rates_idx => [qw(recipient message_ts)],
|
||||
],
|
||||
},
|
||||
|
||||
# THESCHWARTZ TABLES
|
||||
# ------------------
|
||||
# Note: In the standard TheSchwartz schema, most integers are unsigned,
|
||||
@ -1769,26 +1733,6 @@ use constant ABSTRACT_SCHEMA => {
|
||||
bug_user_last_visit_last_visit_ts_idx => ['last_visit_ts'],
|
||||
],
|
||||
},
|
||||
|
||||
user_api_keys => {
|
||||
FIELDS => [
|
||||
id => {TYPE => 'INTSERIAL', NOTNULL => 1,
|
||||
PRIMARYKEY => 1},
|
||||
user_id => {TYPE => 'INT3', NOTNULL => 1,
|
||||
REFERENCES => {TABLE => 'profiles',
|
||||
COLUMN => 'userid',
|
||||
DELETE => 'CASCADE'}},
|
||||
api_key => {TYPE => 'VARCHAR(40)', NOTNULL => 1},
|
||||
description => {TYPE => 'VARCHAR(255)'},
|
||||
revoked => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
||||
DEFAULT => 'FALSE'},
|
||||
last_used => {TYPE => 'DATETIME'},
|
||||
],
|
||||
INDEXES => [
|
||||
user_api_keys_api_key_idx => {FIELDS => ['api_key'], TYPE => 'UNIQUE'},
|
||||
user_api_keys_user_id_idx => ['user_id'],
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
# Foreign Keys are added in Bugzilla::DB::bz_add_field_tables
|
||||
|
||||
@ -15,7 +15,6 @@ package Bugzilla::DB::Schema::Mysql;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Error;
|
||||
|
||||
|
||||
@ -15,7 +15,6 @@ package Bugzilla::DB::Schema::Oracle;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::DB::Schema);
|
||||
use Carp qw(confess);
|
||||
|
||||
@ -15,7 +15,6 @@ package Bugzilla::DB::Schema::Pg;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::DB::Schema);
|
||||
use Storable qw(dclone);
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::DB::Schema::Sqlite;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::DB::Schema);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::DB::Sqlite;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::DB);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Error;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Exporter);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Extension;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Error;
|
||||
|
||||
@ -59,7 +59,6 @@ package Bugzilla::Field;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Exporter Bugzilla::Object);
|
||||
@Bugzilla::Field::EXPORT = qw(check_field get_field_id get_legal_field_values);
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Field::Choice;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Field::ChoiceInterface;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Error;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Flag;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
@ -454,15 +453,14 @@ sub create {
|
||||
sub update {
|
||||
my $self = shift;
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my $timestamp = shift || $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
|
||||
my $timestamp = shift || $dbh->selectrow_array('SELECT NOW()');
|
||||
|
||||
my $changes = $self->SUPER::update(@_);
|
||||
|
||||
if (scalar(keys %$changes)) {
|
||||
$dbh->do('UPDATE flags SET modification_date = ? WHERE id = ?',
|
||||
undef, ($timestamp, $self->id));
|
||||
$self->{'modification_date'} =
|
||||
format_time($timestamp, '%Y.%m.%d %T', Bugzilla->local_timezone);
|
||||
$self->{'modification_date'} = format_time($timestamp, '%Y.%m.%d %T');
|
||||
Bugzilla->memcached->clear({ table => 'flags', id => $self->id });
|
||||
}
|
||||
return $changes;
|
||||
@ -933,117 +931,6 @@ sub extract_flags_from_cgi {
|
||||
|
||||
=over
|
||||
|
||||
=item C<multi_extract_flags_from_cgi($bug, $hr_vars)>
|
||||
|
||||
Checks whether or not there are new flags to create and returns an
|
||||
array of hashes. This array is then passed to Flag::create(). This differs
|
||||
from the previous sub-routine as it is called for changing multiple bugs
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub multi_extract_flags_from_cgi {
|
||||
my ($class, $bug, $vars, $skip) = @_;
|
||||
my $cgi = Bugzilla->cgi;
|
||||
|
||||
my $match_status = Bugzilla::User::match_field({
|
||||
'^requestee(_type)?-(\d+)$' => { 'type' => 'multi' },
|
||||
}, undef, $skip);
|
||||
|
||||
$vars->{'match_field'} = 'requestee';
|
||||
if ($match_status == USER_MATCH_FAILED) {
|
||||
$vars->{'message'} = 'user_match_failed';
|
||||
}
|
||||
elsif ($match_status == USER_MATCH_MULTIPLE) {
|
||||
$vars->{'message'} = 'user_match_multiple';
|
||||
}
|
||||
|
||||
# Extract a list of flag type IDs from field names.
|
||||
my @flagtype_ids = map(/^flag_type-(\d+)$/ ? $1 : (), $cgi->param());
|
||||
|
||||
my (@new_flags, @flags);
|
||||
|
||||
# Get a list of active flag types available for this product/component.
|
||||
my $flag_types = Bugzilla::FlagType::match(
|
||||
{ 'product_id' => $bug->{'product_id'},
|
||||
'component_id' => $bug->{'component_id'},
|
||||
'is_active' => 1 });
|
||||
|
||||
foreach my $flagtype_id (@flagtype_ids) {
|
||||
# Checks if there are unexpected flags for the product/component.
|
||||
if (!scalar(grep { $_->id == $flagtype_id } @$flag_types)) {
|
||||
$vars->{'message'} = 'unexpected_flag_types';
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $flag_type (@$flag_types) {
|
||||
my $type_id = $flag_type->id;
|
||||
|
||||
# Bug flags are only valid for bugs
|
||||
next unless ($flag_type->target_type eq 'bug');
|
||||
|
||||
# We are only interested in flags the user tries to create.
|
||||
next unless scalar(grep { $_ == $type_id } @flagtype_ids);
|
||||
|
||||
# Get the flags of this type already set for this bug.
|
||||
my $current_flags = $class->match(
|
||||
{ 'type_id' => $type_id,
|
||||
'target_type' => 'bug',
|
||||
'bug_id' => $bug->bug_id });
|
||||
|
||||
# We will update existing flags (instead of creating new ones)
|
||||
# if the flag exists and the user has not chosen the 'always add'
|
||||
# option
|
||||
my $update = scalar(@$current_flags) && ! $cgi->param("flags_add-$type_id");
|
||||
|
||||
my $status = $cgi->param("flag_type-$type_id");
|
||||
trick_taint($status);
|
||||
|
||||
my @logins = $cgi->param("requestee_type-$type_id");
|
||||
if ($status eq "?" && scalar(@logins)) {
|
||||
foreach my $login (@logins) {
|
||||
if ($update) {
|
||||
foreach my $current_flag (@$current_flags) {
|
||||
push (@flags, { id => $current_flag->id,
|
||||
status => $status,
|
||||
requestee => $login,
|
||||
skip_roe => $skip });
|
||||
}
|
||||
}
|
||||
else {
|
||||
push (@new_flags, { type_id => $type_id,
|
||||
status => $status,
|
||||
requestee => $login,
|
||||
skip_roe => $skip });
|
||||
}
|
||||
|
||||
last unless $flag_type->is_multiplicable;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($update) {
|
||||
foreach my $current_flag (@$current_flags) {
|
||||
push (@flags, { id => $current_flag->id,
|
||||
status => $status });
|
||||
}
|
||||
}
|
||||
else {
|
||||
push (@new_flags, { type_id => $type_id,
|
||||
status => $status });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Return the list of flags to update and/or to create.
|
||||
return (\@flags, \@new_flags);
|
||||
}
|
||||
|
||||
=pod
|
||||
|
||||
=over
|
||||
|
||||
=item C<notify($flag, $old_flag, $object, $timestamp)>
|
||||
|
||||
Sends an email notification about a flag being created, fulfilled
|
||||
@ -1124,32 +1011,18 @@ sub notify {
|
||||
$default_lang = Bugzilla::User->new()->setting('lang');
|
||||
}
|
||||
|
||||
# Get comments on the bug
|
||||
my $all_comments = $bug->comments({ after => $bug->lastdiffed });
|
||||
@$all_comments = grep { $_->type || $_->body =~ /\S/ } @$all_comments;
|
||||
|
||||
# Get public only comments
|
||||
my $public_comments = [ grep { !$_->is_private } @$all_comments ];
|
||||
|
||||
foreach my $to (keys %recipients) {
|
||||
# Add threadingmarker to allow flag notification emails to be the
|
||||
# threaded similar to normal bug change emails.
|
||||
my $thread_user_id = $recipients{$to} ? $recipients{$to}->id : 0;
|
||||
|
||||
# We only want to show private comments to users in the is_insider group
|
||||
my $comments = $recipients{$to} && $recipients{$to}->is_insider
|
||||
? $all_comments : $public_comments;
|
||||
|
||||
my $vars = {
|
||||
flag => $flag,
|
||||
old_flag => $old_flag,
|
||||
to => $to,
|
||||
date => $timestamp,
|
||||
bug => $bug,
|
||||
attachment => $attachment,
|
||||
threadingmarker => build_thread_marker($bug->id, $thread_user_id),
|
||||
new_comments => $comments,
|
||||
};
|
||||
my $vars = { 'flag' => $flag,
|
||||
'old_flag' => $old_flag,
|
||||
'to' => $to,
|
||||
'date' => $timestamp,
|
||||
'bug' => $bug,
|
||||
'attachment' => $attachment,
|
||||
'threadingmarker' => build_thread_marker($bug->id, $thread_user_id) };
|
||||
|
||||
my $lang = $recipients{$to} ?
|
||||
$recipients{$to}->setting('lang') : $default_lang;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::FlagType;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
@ -41,7 +40,6 @@ use Bugzilla::Util;
|
||||
use Bugzilla::Group;
|
||||
|
||||
use Email::Address;
|
||||
use List::MoreUtils qw(uniq);
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
@ -380,6 +378,8 @@ sub set_clusions {
|
||||
if (!$products{$prod_id}) {
|
||||
$params->{id} = $prod_id;
|
||||
$products{$prod_id} = Bugzilla::Product->check($params);
|
||||
$user->in_group('editcomponents', $prod_id)
|
||||
|| ThrowUserError('product_access_denied', $params);
|
||||
}
|
||||
$prod_name = $products{$prod_id}->name;
|
||||
|
||||
@ -405,22 +405,6 @@ sub set_clusions {
|
||||
$clusions{"$prod_name:$comp_name"} = "$prod_id:$comp_id";
|
||||
$clusions_as_hash{$prod_id}->{$comp_id} = 1;
|
||||
}
|
||||
|
||||
# Check the user has the editcomponent permission on products that are changing
|
||||
if (! $user->in_group('editcomponents')) {
|
||||
my $current_clusions = $self->$category;
|
||||
my ($removed, $added)
|
||||
= diff_arrays([ values %$current_clusions ], [ values %clusions ]);
|
||||
my @changed_product_ids
|
||||
= uniq map { substr($_, 0, index($_, ':')) } @$removed, @$added;
|
||||
foreach my $product_id (@changed_product_ids) {
|
||||
$user->in_group('editcomponents', $product_id)
|
||||
|| ThrowUserError('product_access_denied',
|
||||
{ name => $products{$product_id}->name });
|
||||
}
|
||||
}
|
||||
|
||||
# Set the changes
|
||||
$self->{$category} = \%clusions;
|
||||
$self->{"${category}_as_hash"} = \%clusions_as_hash;
|
||||
$self->{"_update_$category"} = 1;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Group;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
@ -56,10 +55,8 @@ use constant UPDATE_COLUMNS => qw(
|
||||
);
|
||||
|
||||
# Parameters that are lists of groups.
|
||||
use constant GROUP_PARAMS => qw(
|
||||
chartgroup comment_taggers_group debug_group insidergroup
|
||||
querysharegroup timetrackinggroup
|
||||
);
|
||||
use constant GROUP_PARAMS => qw(chartgroup insidergroup timetrackinggroup
|
||||
querysharegroup);
|
||||
|
||||
###############################
|
||||
#### Accessors ######
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Hook;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub process {
|
||||
my ($name, $args) = @_;
|
||||
@ -1033,6 +1032,9 @@ Params:
|
||||
|
||||
=item C<email> - The C<Email::MIME> object that's about to be sent.
|
||||
|
||||
=item C<mailer_args> - An arrayref that's passed as C<mailer_args> to
|
||||
L<Email::Send/new>.
|
||||
|
||||
=back
|
||||
|
||||
=head2 object_before_create
|
||||
@ -1704,26 +1706,6 @@ The current JSONRPC, XMLRPC, or REST object.
|
||||
|
||||
=back
|
||||
|
||||
=head2 webservice_status_code_map
|
||||
|
||||
This hook allows an extension to change the status codes returned by
|
||||
specific webservice errors. The valid internal error codes that Bugzilla
|
||||
generates, and the status codes they map to by default, are defined in the
|
||||
C<WS_ERROR_CODE> constant in C<Bugzilla::WebService::Constants>. When
|
||||
remapping an error, you may wish to use an existing status code constant.
|
||||
Such constants are also in C<Bugzilla::WebService::Constants> and start
|
||||
with C<STATUS_*> such as C<STATUS_BAD_REQUEST>.
|
||||
|
||||
Params:
|
||||
|
||||
=over
|
||||
|
||||
=item C<status_code_map>
|
||||
|
||||
A hash reference containing the current status code mapping.
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Bugzilla::Extension>
|
||||
|
||||
@ -17,7 +17,6 @@ package Bugzilla::Install;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Component;
|
||||
use Bugzilla::Config qw(:admin);
|
||||
@ -90,8 +89,6 @@ sub SETTINGS {
|
||||
bugmail_new_prefix => { options => ['on', 'off'], default => 'on' },
|
||||
# 2013-07-26 joshi_sunil@in.com -- Bug 669535
|
||||
possible_duplicates => { options => ['on', 'off'], default => 'on' },
|
||||
# 2014-05-24 koosha.khajeh@gmail.com -- Bug 1014164
|
||||
use_markdown => { options => ['on', 'off'], default => 'on' },
|
||||
}
|
||||
};
|
||||
|
||||
@ -135,13 +132,11 @@ use constant SYSTEM_GROUPS => (
|
||||
},
|
||||
{
|
||||
name => 'bz_canusewhineatothers',
|
||||
description => 'Can configure queries and schedules for periodic'
|
||||
. ' reports to be run and sent via email to other users and groups',
|
||||
description => 'Can configure whine reports for other users',
|
||||
},
|
||||
{
|
||||
name => 'bz_canusewhines',
|
||||
description => 'Can configure queries and schedules for periodic'
|
||||
. ' reports to be run and sent via email to themselves',
|
||||
description => 'User can configure whine reports for self',
|
||||
# inherited_by means that users in the groups listed below are
|
||||
# automatically members of bz_canusewhines.
|
||||
inherited_by => ['editbugs', 'bz_canusewhineatothers'],
|
||||
@ -219,8 +214,8 @@ sub update_system_groups {
|
||||
|
||||
# Create most of the system groups
|
||||
foreach my $definition (SYSTEM_GROUPS) {
|
||||
my $group = new Bugzilla::Group({ name => $definition->{name} });
|
||||
if (!$group) {
|
||||
my $exists = new Bugzilla::Group({ name => $definition->{name} });
|
||||
if (!$exists) {
|
||||
$definition->{isbuggroup} = 0;
|
||||
$definition->{silently} = !$editbugs_exists;
|
||||
my $inherited_by = delete $definition->{inherited_by};
|
||||
@ -236,10 +231,6 @@ sub update_system_groups {
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($group->description ne $definition->{description}) {
|
||||
$group->set_description($definition->{description});
|
||||
$group->update();
|
||||
}
|
||||
}
|
||||
|
||||
$dbh->bz_commit_transaction();
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Install::CPAN;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
|
||||
@ -12,7 +12,6 @@ package Bugzilla::Install::DB;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Hook;
|
||||
@ -273,6 +272,10 @@ sub update_table_definitions {
|
||||
$dbh->bz_add_column('attachments', 'isprivate',
|
||||
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
|
||||
|
||||
$dbh->bz_add_column("bugs", "alias", {TYPE => "varchar(20)"});
|
||||
$dbh->bz_add_index('bugs', 'bugs_alias_idx',
|
||||
{TYPE => 'UNIQUE', FIELDS => [qw(alias)]});
|
||||
|
||||
_move_quips_into_db();
|
||||
|
||||
$dbh->bz_drop_column("namedqueries", "watchfordiffs");
|
||||
@ -716,20 +719,6 @@ sub update_table_definitions {
|
||||
'bug_user_last_visit_last_visit_ts_idx',
|
||||
['last_visit_ts']);
|
||||
|
||||
# 2014-07-14 sgreen@redhat.com - Bug 726696
|
||||
$dbh->bz_alter_column('tokens', 'tokentype',
|
||||
{TYPE => 'varchar(16)', NOTNULL => 1});
|
||||
|
||||
# 2014-07-27 LpSolit@gmail.com - Bug 1044561
|
||||
_fix_user_api_keys_indexes();
|
||||
|
||||
# 2014-08-11 sgreen@redhat.com - Bug 1012506
|
||||
_update_alias();
|
||||
|
||||
# 2014-08-14 koosha.khajeh@gmail.com - Bug 330707
|
||||
$dbh->bz_add_column('longdescs', 'is_markdown',
|
||||
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'});
|
||||
|
||||
################################################################
|
||||
# New --TABLE-- changes should go *** A B O V E *** this point #
|
||||
################################################################
|
||||
@ -2561,7 +2550,7 @@ sub _fix_whine_queries_title_and_op_sys_value {
|
||||
undef, "Other", "other");
|
||||
if (Bugzilla->params->{'defaultopsys'} eq 'other') {
|
||||
# We can't actually fix the param here, because WriteParams() will
|
||||
# make $datadir/params.json unwriteable to the webservergroup.
|
||||
# make $datadir/params unwriteable to the webservergroup.
|
||||
# It's too much of an ugly hack to copy the permission-fixing code
|
||||
# down to here. (It would create more potential future bugs than
|
||||
# it would solve problems.)
|
||||
@ -3888,33 +3877,6 @@ sub _fix_components_primary_key {
|
||||
}
|
||||
}
|
||||
|
||||
sub _fix_user_api_keys_indexes {
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
if ($dbh->bz_index_info('user_api_keys', 'user_api_keys_key')) {
|
||||
$dbh->bz_drop_index('user_api_keys', 'user_api_keys_key');
|
||||
$dbh->bz_add_index('user_api_keys', 'user_api_keys_api_key_idx',
|
||||
{ FIELDS => ['api_key'], TYPE => 'UNIQUE' });
|
||||
}
|
||||
if ($dbh->bz_index_info('user_api_keys', 'user_api_keys_user_id')) {
|
||||
$dbh->bz_drop_index('user_api_keys', 'user_api_keys_user_id');
|
||||
$dbh->bz_add_index('user_api_keys', 'user_api_keys_user_id_idx', ['user_id']);
|
||||
}
|
||||
}
|
||||
|
||||
sub _update_alias {
|
||||
my $dbh = Bugzilla->dbh;
|
||||
return unless $dbh->bz_column_info('bugs', 'alias');
|
||||
|
||||
# We need to move the aliases from the bugs table to the bugs_aliases table
|
||||
$dbh->do(q{
|
||||
INSERT INTO bugs_aliases (bug_id, alias)
|
||||
SELECT bug_id, alias FROM bugs WHERE alias IS NOT NULL
|
||||
});
|
||||
|
||||
$dbh->bz_drop_column('bugs', 'alias');
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
@ -17,7 +17,6 @@ package Bugzilla::Install::Filesystem;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Error;
|
||||
@ -31,7 +30,6 @@ use File::Path;
|
||||
use File::Basename;
|
||||
use File::Copy qw(move);
|
||||
use File::Spec;
|
||||
use File::Slurp;
|
||||
use IO::File;
|
||||
use POSIX ();
|
||||
|
||||
@ -167,13 +165,12 @@ sub FILESYSTEM {
|
||||
'contrib/README' => { perms => OWNER_WRITE },
|
||||
'contrib/*/README' => { perms => OWNER_WRITE },
|
||||
'contrib/Bugzilla.pm' => { perms => OWNER_WRITE },
|
||||
'contrib/replyrc' => { perms => OWNER_WRITE },
|
||||
'docs/bugzilla.ent' => { perms => OWNER_WRITE },
|
||||
'docs/makedocs.pl' => { perms => OWNER_EXECUTE },
|
||||
'docs/style.css' => { perms => WS_SERVE },
|
||||
'docs/*/rel_notes.txt' => { perms => WS_SERVE },
|
||||
'docs/*/README.docs' => { perms => OWNER_WRITE },
|
||||
"$datadir/params.json" => { perms => CGI_WRITE },
|
||||
"$datadir/params" => { perms => CGI_WRITE },
|
||||
"$datadir/old-params.txt" => { perms => OWNER_WRITE },
|
||||
"$extensionsdir/create.pl" => { perms => OWNER_EXECUTE },
|
||||
"$extensionsdir/*/*.pl" => { perms => WS_EXECUTE },
|
||||
@ -369,7 +366,7 @@ EOT
|
||||
|
||||
"$assetsdir/.htaccess" => { perms => WS_SERVE, contents => <<EOT
|
||||
# Allow access to .css files
|
||||
<FilesMatch \\.(css|js)\$>
|
||||
<FilesMatch \\.css\$>
|
||||
Allow from all
|
||||
</FilesMatch>
|
||||
|
||||
@ -412,7 +409,6 @@ sub update_filesystem {
|
||||
|
||||
my $datadir = bz_locations->{'datadir'};
|
||||
my $graphsdir = bz_locations->{'graphsdir'};
|
||||
my $assetsdir = bz_locations->{'assetsdir'};
|
||||
# If the graphs/ directory doesn't exist, we're upgrading from
|
||||
# a version old enough that we need to update the $datadir/mining
|
||||
# format.
|
||||
@ -453,13 +449,6 @@ sub update_filesystem {
|
||||
_rename_file($oldparamsfile, "$datadir/$oldparamsfile");
|
||||
}
|
||||
|
||||
# Remove old assets htaccess file to force recreation with correct values.
|
||||
if (-e "$assetsdir/.htaccess") {
|
||||
if (read_file("$assetsdir/.htaccess") =~ /<FilesMatch \\\.css\$>/) {
|
||||
unlink("$assetsdir/.htaccess");
|
||||
}
|
||||
}
|
||||
|
||||
_create_files(%files);
|
||||
if ($params->{index_html}) {
|
||||
_create_files(%{$fs->{index_html}});
|
||||
@ -503,7 +492,7 @@ EOT
|
||||
|
||||
_remove_empty_css_files();
|
||||
_convert_single_file_skins();
|
||||
_remove_dynamic_assets();
|
||||
_remove_dynamic_css_files();
|
||||
}
|
||||
|
||||
sub _remove_empty_css_files {
|
||||
@ -548,14 +537,10 @@ sub _convert_single_file_skins {
|
||||
}
|
||||
}
|
||||
|
||||
# delete all automatically generated css/js files to force recreation at the
|
||||
# next request.
|
||||
sub _remove_dynamic_assets {
|
||||
my @files = (
|
||||
glob(bz_locations()->{assetsdir} . '/*.css'),
|
||||
glob(bz_locations()->{assetsdir} . '/*.js'),
|
||||
);
|
||||
foreach my $file (@files) {
|
||||
# delete all automatically generated css files to force recreation at the next
|
||||
# request.
|
||||
sub _remove_dynamic_css_files {
|
||||
foreach my $file (glob(bz_locations()->{assetsdir} . '/*.css')) {
|
||||
unlink($file);
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,6 @@ package Bugzilla::Install::Localconfig;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Install::Util qw(bin_loc install_string);
|
||||
@ -100,6 +99,10 @@ use constant LOCALCONFIG_VARS => (
|
||||
name => 'index_html',
|
||||
default => 0,
|
||||
},
|
||||
{
|
||||
name => 'cvsbin',
|
||||
default => sub { bin_loc('cvs') },
|
||||
},
|
||||
{
|
||||
name => 'interdiffbin',
|
||||
default => sub { bin_loc('interdiff') },
|
||||
|
||||
@ -15,7 +15,6 @@ package Bugzilla::Install::Requirements;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Install::Util qw(install_string bin_loc
|
||||
@ -23,6 +22,13 @@ use Bugzilla::Install::Util qw(install_string bin_loc
|
||||
use List::Util qw(max);
|
||||
use Term::ANSIColor;
|
||||
|
||||
# Return::Value 1.666002 pollutes the error log with warnings about this
|
||||
# deprecated module. We have to set NO_CLUCK = 1 before loading Email::Send
|
||||
# in have_vers() to disable these warnings.
|
||||
BEGIN {
|
||||
$Return::Value::NO_CLUCK = 1;
|
||||
}
|
||||
|
||||
use parent qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
REQUIRED_MODULES
|
||||
@ -124,11 +130,12 @@ sub REQUIRED_MODULES {
|
||||
module => 'Template',
|
||||
version => '2.24'
|
||||
},
|
||||
# 1.300011 has a debug mode for SMTP and automatically pass -i to sendmail.
|
||||
# 2.04 implement the "Test" method (to write to data/mailer.testfile).
|
||||
{
|
||||
package => 'Email-Sender',
|
||||
module => 'Email::Sender',
|
||||
version => '1.300011',
|
||||
package => 'Email-Send',
|
||||
module => 'Email::Send',
|
||||
version => ON_WINDOWS ? '2.16' : '2.04',
|
||||
blacklist => ['^2\.196$']
|
||||
},
|
||||
{
|
||||
package => 'Email-MIME',
|
||||
@ -158,12 +165,6 @@ sub REQUIRED_MODULES {
|
||||
module => 'File::Slurp',
|
||||
version => '9999.13',
|
||||
},
|
||||
{
|
||||
package => 'JSON-XS',
|
||||
module => 'JSON::XS',
|
||||
# 2.0 is the first version that will work with JSON::RPC.
|
||||
version => '2.01',
|
||||
},
|
||||
);
|
||||
|
||||
if (ON_WINDOWS) {
|
||||
@ -296,6 +297,13 @@ sub OPTIONAL_MODULES {
|
||||
version => 0,
|
||||
feature => ['jsonrpc', 'rest'],
|
||||
},
|
||||
{
|
||||
package => 'JSON-XS',
|
||||
module => 'JSON::XS',
|
||||
# 2.0 is the first version that will work with JSON::RPC.
|
||||
version => '2.0',
|
||||
feature => ['jsonrpc_faster'],
|
||||
},
|
||||
{
|
||||
package => 'Test-Taint',
|
||||
module => 'Test::Taint',
|
||||
@ -349,8 +357,8 @@ sub OPTIONAL_MODULES {
|
||||
{
|
||||
package => 'TheSchwartz',
|
||||
module => 'TheSchwartz',
|
||||
# 1.10 supports declining of jobs.
|
||||
version => 1.10,
|
||||
# 1.07 supports the prioritization of jobs.
|
||||
version => 1.07,
|
||||
feature => ['jobqueue'],
|
||||
},
|
||||
{
|
||||
@ -396,22 +404,6 @@ sub OPTIONAL_MODULES {
|
||||
version => '0',
|
||||
feature => ['memcached'],
|
||||
},
|
||||
|
||||
# Markdown
|
||||
{
|
||||
package => 'Text-Markdown',
|
||||
module => 'Text::Markdown',
|
||||
version => '1.0.26',
|
||||
feature => ['markdown'],
|
||||
},
|
||||
|
||||
# Documentation
|
||||
{
|
||||
package => 'File-Copy-Recursive',
|
||||
module => 'File::Copy::Recursive',
|
||||
version => 0,
|
||||
feature => ['documentation'],
|
||||
}
|
||||
);
|
||||
|
||||
my $extra_modules = _get_extension_requirements('OPTIONAL_MODULES');
|
||||
@ -435,7 +427,6 @@ use constant FEATURE_FILES => (
|
||||
'Bugzilla/JobQueue/*', 'jobqueue.pl'],
|
||||
patch_viewer => ['Bugzilla/Attachment/PatchReader.pm'],
|
||||
updates => ['Bugzilla/Update.pm'],
|
||||
markdown => ['Bugzilla/Markdown.pm'],
|
||||
memcached => ['Bugzilla/Memcache.pm'],
|
||||
);
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@ package Bugzilla::Install::Util;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
|
||||
|
||||
@ -9,14 +9,23 @@ package Bugzilla::Job::BugMail;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::BugMail;
|
||||
BEGIN { eval "use parent qw(Bugzilla::Job::Mailer)"; }
|
||||
|
||||
sub process_job {
|
||||
my ($class, $arg) = @_;
|
||||
Bugzilla::BugMail::dequeue($arg->{vars});
|
||||
sub work {
|
||||
my ($class, $job) = @_;
|
||||
my $success = eval {
|
||||
Bugzilla::BugMail::dequeue($job->arg->{vars});
|
||||
1;
|
||||
};
|
||||
if (!$success) {
|
||||
$job->failed($@);
|
||||
undef $@;
|
||||
}
|
||||
else {
|
||||
$job->completed;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@ -9,9 +9,7 @@ package Bugzilla::Job::Mailer;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Mailer;
|
||||
BEGIN { eval "use parent qw(TheSchwartz::Worker)"; }
|
||||
|
||||
@ -33,14 +31,10 @@ sub retry_delay {
|
||||
|
||||
sub work {
|
||||
my ($class, $job) = @_;
|
||||
eval { $class->process_job($job->arg) };
|
||||
if (my $error = $@) {
|
||||
if ($error eq EMAIL_LIMIT_EXCEPTION) {
|
||||
$job->declined();
|
||||
}
|
||||
else {
|
||||
$job->failed($error);
|
||||
}
|
||||
my $msg = $job->arg->{msg};
|
||||
my $success = eval { MessageToMTA($msg, 1); 1; };
|
||||
if (!$success) {
|
||||
$job->failed($@);
|
||||
undef $@;
|
||||
}
|
||||
else {
|
||||
@ -48,9 +42,4 @@ sub work {
|
||||
}
|
||||
}
|
||||
|
||||
sub process_job {
|
||||
my ($class, $arg) = @_;
|
||||
MessageToMTA($arg->{msg}, 1);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::JobQueue;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Error;
|
||||
|
||||
@ -13,7 +13,6 @@ package Bugzilla::JobQueue::Runner;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Cwd qw(abs_path);
|
||||
use File::Basename;
|
||||
@ -80,7 +79,6 @@ sub gd_more_opt {
|
||||
return (
|
||||
'pidfile=s' => \$self->{gd_args}{pidfile},
|
||||
'n=s' => \$self->{gd_args}{progname},
|
||||
'j=s@' => \$self->{gd_args}{job_name},
|
||||
);
|
||||
}
|
||||
|
||||
@ -211,12 +209,10 @@ sub gd_run {
|
||||
sub _do_work {
|
||||
my ($self, $fn) = @_;
|
||||
|
||||
my @job_name = @{ $self->{gd_args}{job_name} // [] };
|
||||
my $jq = Bugzilla->job_queue();
|
||||
$jq->set_verbose($self->{debug});
|
||||
$jq->set_pidfile($self->{gd_pidfile});
|
||||
while (my ($key, $module) = each %{ Bugzilla::JobQueue->job_map() }) {
|
||||
next if @job_name and ! grep { $_ eq $key } @job_name;
|
||||
foreach my $module (values %{ Bugzilla::JobQueue->job_map() }) {
|
||||
eval "use $module";
|
||||
$jq->can_do($module);
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Keyword;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Mailer;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Exporter);
|
||||
@Bugzilla::Mailer::EXPORT = qw(MessageToMTA build_thread_marker);
|
||||
@ -23,26 +22,26 @@ use Date::Format qw(time2str);
|
||||
|
||||
use Encode qw(encode);
|
||||
use Encode::MIME::Header;
|
||||
use Email::Address;
|
||||
use Email::MIME;
|
||||
use Email::Sender::Simple qw(sendmail);
|
||||
use Email::Sender::Transport::SMTP::Persistent;
|
||||
use Bugzilla::Sender::Transport::Sendmail;
|
||||
# Return::Value 1.666002 pollutes the error log with warnings about this
|
||||
# deprecated module. We have to set NO_CLUCK = 1 before loading Email::Send
|
||||
# to disable these warnings.
|
||||
BEGIN {
|
||||
$Return::Value::NO_CLUCK = 1;
|
||||
}
|
||||
use Email::Send;
|
||||
|
||||
sub MessageToMTA {
|
||||
my ($msg, $send_now) = (@_);
|
||||
my $method = Bugzilla->params->{'mail_delivery_method'};
|
||||
return if $method eq 'None';
|
||||
|
||||
if (Bugzilla->params->{'use_mailer_queue'}
|
||||
&& ! $send_now
|
||||
&& ! Bugzilla->dbh->bz_in_transaction()
|
||||
) {
|
||||
if (Bugzilla->params->{'use_mailer_queue'} and !$send_now) {
|
||||
Bugzilla->job_queue->insert('send_mail', { msg => $msg });
|
||||
return;
|
||||
}
|
||||
|
||||
my $dbh = Bugzilla->dbh;
|
||||
|
||||
my $email;
|
||||
if (ref $msg) {
|
||||
$email = $msg;
|
||||
@ -52,58 +51,12 @@ sub MessageToMTA {
|
||||
# Email::MIME doesn't do this for us. We use \015 (CR) and \012 (LF)
|
||||
# directly because Perl translates "\n" depending on what platform
|
||||
# you're running on. See http://perldoc.perl.org/perlport.html#Newlines
|
||||
# We check for multiple CRs because of this Template-Toolkit bug:
|
||||
# https://rt.cpan.org/Ticket/Display.html?id=43345
|
||||
$msg =~ s/(?:\015+)?\012/\015\012/msg;
|
||||
$email = new Email::MIME($msg);
|
||||
}
|
||||
|
||||
# If we're called from within a transaction, we don't want to send the
|
||||
# email immediately, in case the transaction is rolled back. Instead we
|
||||
# insert it into the mail_staging table, and bz_commit_transaction calls
|
||||
# send_staged_mail() after the transaction is committed.
|
||||
if (! $send_now && $dbh->bz_in_transaction()) {
|
||||
# The e-mail string may contain tainted values.
|
||||
my $string = $email->as_string;
|
||||
trick_taint($string);
|
||||
$dbh->do("INSERT INTO mail_staging (message) VALUES(?)", undef, $string);
|
||||
return;
|
||||
}
|
||||
|
||||
# Ensure that we are not sending emails too quickly to recipients.
|
||||
if (Bugzilla->params->{use_mailer_queue}
|
||||
&& (EMAIL_LIMIT_PER_MINUTE || EMAIL_LIMIT_PER_HOUR))
|
||||
{
|
||||
$dbh->do(
|
||||
"DELETE FROM email_rates WHERE message_ts < "
|
||||
. $dbh->sql_date_math('LOCALTIMESTAMP(0)', '-', '1', 'HOUR'));
|
||||
|
||||
my $recipient = $email->header('To');
|
||||
|
||||
if (EMAIL_LIMIT_PER_MINUTE) {
|
||||
my $minute_rate = $dbh->selectrow_array(
|
||||
"SELECT COUNT(*)
|
||||
FROM email_rates
|
||||
WHERE recipient = ? AND message_ts >= "
|
||||
. $dbh->sql_date_math('LOCALTIMESTAMP(0)', '-', '1', 'MINUTE'),
|
||||
undef,
|
||||
$recipient);
|
||||
if ($minute_rate >= EMAIL_LIMIT_PER_MINUTE) {
|
||||
die EMAIL_LIMIT_EXCEPTION;
|
||||
}
|
||||
}
|
||||
if (EMAIL_LIMIT_PER_HOUR) {
|
||||
my $hour_rate = $dbh->selectrow_array(
|
||||
"SELECT COUNT(*)
|
||||
FROM email_rates
|
||||
WHERE recipient = ? AND message_ts >= "
|
||||
. $dbh->sql_date_math('LOCALTIMESTAMP(0)', '-', '1', 'HOUR'),
|
||||
undef,
|
||||
$recipient);
|
||||
if ($hour_rate >= EMAIL_LIMIT_PER_HOUR) {
|
||||
die EMAIL_LIMIT_EXCEPTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# We add this header to uniquely identify all email that we
|
||||
# send as coming from this Bugzilla installation.
|
||||
#
|
||||
@ -139,14 +92,21 @@ sub MessageToMTA {
|
||||
|
||||
my $from = $email->header('From');
|
||||
|
||||
my $hostname;
|
||||
my $transport;
|
||||
my ($hostname, @args);
|
||||
my $mailer_class = $method;
|
||||
if ($method eq "Sendmail") {
|
||||
$mailer_class = 'Bugzilla::Send::Sendmail';
|
||||
if (ON_WINDOWS) {
|
||||
$transport = Bugzilla::Sender::Transport::Sendmail->new({ sendmail => SENDMAIL_EXE });
|
||||
$Email::Send::Sendmail::SENDMAIL = SENDMAIL_EXE;
|
||||
}
|
||||
else {
|
||||
$transport = Bugzilla::Sender::Transport::Sendmail->new();
|
||||
push @args, "-i";
|
||||
# We want to make sure that we pass *only* an email address.
|
||||
if ($from) {
|
||||
my ($email_obj) = Email::Address->parse($from);
|
||||
if ($email_obj) {
|
||||
my $from_email = $email_obj->address;
|
||||
push(@args, "-f$from_email") if $from_email;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -154,7 +114,7 @@ sub MessageToMTA {
|
||||
# address, but other mailers won't.
|
||||
my $urlbase = Bugzilla->params->{'urlbase'};
|
||||
$urlbase =~ m|//([^:/]+)[:/]?|;
|
||||
$hostname = $1 || 'localhost';
|
||||
$hostname = $1;
|
||||
$from .= "\@$hostname" if $from !~ /@/;
|
||||
$email->header_set('From', $from);
|
||||
|
||||
@ -165,19 +125,16 @@ sub MessageToMTA {
|
||||
}
|
||||
|
||||
if ($method eq "SMTP") {
|
||||
my ($host, $port) = split(/:/, Bugzilla->params->{'smtpserver'}, 2);
|
||||
$transport = Bugzilla->request_cache->{smtp} //=
|
||||
Email::Sender::Transport::SMTP::Persistent->new({
|
||||
host => $host,
|
||||
defined($port) ? (port => $port) : (),
|
||||
sasl_username => Bugzilla->params->{'smtp_username'},
|
||||
sasl_password => Bugzilla->params->{'smtp_password'},
|
||||
helo => $hostname,
|
||||
ssl => Bugzilla->params->{'smtp_ssl'},
|
||||
debug => Bugzilla->params->{'smtp_debug'} });
|
||||
push @args, Host => Bugzilla->params->{"smtpserver"},
|
||||
username => Bugzilla->params->{"smtp_username"},
|
||||
password => Bugzilla->params->{"smtp_password"},
|
||||
Hello => $hostname,
|
||||
ssl => Bugzilla->params->{'smtp_ssl'},
|
||||
Debug => Bugzilla->params->{'smtp_debug'};
|
||||
}
|
||||
|
||||
Bugzilla::Hook::process('mailer_before_send', { email => $email });
|
||||
Bugzilla::Hook::process('mailer_before_send',
|
||||
{ email => $email, mailer_args => \@args });
|
||||
|
||||
return if $email->header('to') eq '';
|
||||
|
||||
@ -212,23 +169,13 @@ sub MessageToMTA {
|
||||
close TESTFILE;
|
||||
}
|
||||
else {
|
||||
# This is useful for Sendmail, so we put it out here.
|
||||
# This is useful for both Sendmail and Qmail, so we put it out here.
|
||||
local $ENV{PATH} = SENDMAIL_PATH;
|
||||
eval { sendmail($email, { transport => $transport }) };
|
||||
if ($@) {
|
||||
ThrowCodeError('mail_send_error', { msg => $@->message, mail => $email });
|
||||
}
|
||||
}
|
||||
|
||||
# insert into email_rates
|
||||
if (Bugzilla->params->{use_mailer_queue}
|
||||
&& (EMAIL_LIMIT_PER_MINUTE || EMAIL_LIMIT_PER_HOUR))
|
||||
{
|
||||
$dbh->do(
|
||||
"INSERT INTO email_rates(recipient, message_ts) VALUES (?, LOCALTIMESTAMP(0))",
|
||||
undef,
|
||||
$email->header('To')
|
||||
);
|
||||
my $mailer = Email::Send->new({ mailer => $mailer_class,
|
||||
mailer_args => \@args });
|
||||
my $retval = $mailer->send($email);
|
||||
ThrowCodeError('mail_send_error', { msg => $retval, mail => $email })
|
||||
if !$retval;
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,50 +208,14 @@ sub build_thread_marker {
|
||||
return $threadingmarker;
|
||||
}
|
||||
|
||||
sub send_staged_mail {
|
||||
my $dbh = Bugzilla->dbh;
|
||||
my @ids;
|
||||
my $emails
|
||||
= $dbh->selectall_arrayref("SELECT id, message FROM mail_staging");
|
||||
|
||||
foreach my $row (@$emails) {
|
||||
MessageToMTA($row->[1]);
|
||||
push(@ids, $row->[0]);
|
||||
}
|
||||
|
||||
if (@ids) {
|
||||
$dbh->do("DELETE FROM mail_staging WHERE " . $dbh->sql_in('id', \@ids));
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Bugzilla::Mailer - Provides methods for sending email
|
||||
|
||||
=head1 METHODS
|
||||
=head1 B<Methods in need of POD>
|
||||
|
||||
=over
|
||||
|
||||
=item C<MessageToMTA>
|
||||
=item build_thread_marker
|
||||
|
||||
Sends the passed message to the mail transfer agent.
|
||||
|
||||
The actual behaviour depends on a number of factors: if called from within a
|
||||
database transaction, the message will be staged and sent when the transaction
|
||||
is committed. If email queueing is enabled, the message will be sent to
|
||||
TheSchwartz job queue where it will be processed by the jobqueue daemon, else
|
||||
the message is sent immediately.
|
||||
|
||||
=item C<build_thread_marker>
|
||||
|
||||
Builds header suitable for use as a threading marker in email notifications.
|
||||
|
||||
=item C<send_staged_mail>
|
||||
|
||||
Sends all staged messages -- called after a database transaction is committed.
|
||||
=item MessageToMTA
|
||||
|
||||
=back
|
||||
|
||||
@ -1,520 +0,0 @@
|
||||
# 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::Markdown;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Template;
|
||||
|
||||
use Digest::MD5 qw(md5_hex);
|
||||
|
||||
use parent qw(Text::Markdown);
|
||||
|
||||
@Bugzilla::Markdown::EXPORT = qw(new);
|
||||
|
||||
# Regex to match balanced [brackets]. See Friedl's
|
||||
# "Mastering Regular Expressions", 2nd Ed., pp. 328-331.
|
||||
our ($g_nested_brackets, $g_nested_parens);
|
||||
$g_nested_brackets = qr{
|
||||
(?> # Atomic matching
|
||||
[^\[\]]+ # Anything other than brackets
|
||||
|
|
||||
\[
|
||||
(??{ $g_nested_brackets }) # Recursive set of nested brackets
|
||||
\]
|
||||
)*
|
||||
}x;
|
||||
# Doesn't allow for whitespace, because we're using it to match URLs:
|
||||
$g_nested_parens = qr{
|
||||
(?> # Atomic matching
|
||||
[^()\s]+ # Anything other than parens or whitespace
|
||||
|
|
||||
\(
|
||||
(??{ $g_nested_parens }) # Recursive set of nested brackets
|
||||
\)
|
||||
)*
|
||||
}x;
|
||||
|
||||
our %g_escape_table;
|
||||
foreach my $char (split //, '\\`*_{}[]()>#+-.!~') {
|
||||
$g_escape_table{$char} = md5_hex($char);
|
||||
}
|
||||
$g_escape_table{'<'} = md5_hex('<');
|
||||
|
||||
sub new {
|
||||
my $invocant = shift;
|
||||
my $class = ref $invocant || $invocant;
|
||||
return $class->SUPER::new(tab_width => MARKDOWN_TAB_WIDTH,
|
||||
# Bugzilla uses HTML not XHTML
|
||||
empty_element_suffix => '>');
|
||||
}
|
||||
|
||||
sub markdown {
|
||||
my $self = shift;
|
||||
my $text = shift;
|
||||
my $user = Bugzilla->user;
|
||||
|
||||
if ($user->settings->{use_markdown}->{is_enabled}
|
||||
&& $user->setting('use_markdown') eq 'on')
|
||||
{
|
||||
return $self->SUPER::markdown($text, @_);
|
||||
}
|
||||
|
||||
return Bugzilla::Template::quoteUrls($text);
|
||||
}
|
||||
|
||||
sub _Markdown {
|
||||
my $self = shift;
|
||||
my $text = shift;
|
||||
|
||||
$text = Bugzilla::Template::quoteUrls($text, undef, undef, undef, undef, 1);
|
||||
|
||||
return $self->SUPER::_Markdown($text, @_);
|
||||
}
|
||||
|
||||
sub _RunSpanGamut {
|
||||
# These are all the transformations that occur *within* block-level
|
||||
# tags like paragraphs, headers, and list items.
|
||||
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text = $self->_DoCodeSpans($text);
|
||||
$text = $self->_EscapeSpecialCharsWithinTagAttributes($text);
|
||||
$text = $self->_EscapeSpecialChars($text);
|
||||
|
||||
$text = $self->_DoAnchors($text);
|
||||
|
||||
# Strikethroughs is Bugzilla's extension
|
||||
$text = $self->_DoStrikethroughs($text);
|
||||
|
||||
$text = $self->_DoAutoLinks($text);
|
||||
$text = $self->_EncodeAmpsAndAngles($text);
|
||||
$text = $self->_DoItalicsAndBold($text);
|
||||
|
||||
$text =~ s/\n/<br$self->{empty_element_suffix}\n/g;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
# Override to check for HTML-escaped <>" chars.
|
||||
sub _StripLinkDefinitions {
|
||||
#
|
||||
# Strips link definitions from text, stores the URLs and titles in
|
||||
# hash references.
|
||||
#
|
||||
my ($self, $text) = @_;
|
||||
my $less_than_tab = $self->{tab_width} - 1;
|
||||
|
||||
# Link defs are in the form: ^[id]: url "optional title"
|
||||
while ($text =~ s{
|
||||
^[ ]{0,$less_than_tab}\[(.+)\]: # id = \$1
|
||||
[ \t]*
|
||||
\n? # maybe *one* newline
|
||||
[ \t]*
|
||||
(?:<)?<a\s+href="(.+?)">\2</a>(?:>)? # url = \$2
|
||||
[ \t]*
|
||||
\n? # maybe one newline
|
||||
[ \t]*
|
||||
(?:
|
||||
(?<=\s) # lookbehind for whitespace
|
||||
(?:"|\()
|
||||
(.+?) # title = \$3
|
||||
(?:"|\))
|
||||
[ \t]*
|
||||
)? # title is optional
|
||||
(?:\n+|\Z)
|
||||
}{}omx) {
|
||||
$self->{_urls}{lc $1} = $self->_EncodeAmpsAndAngles( $2 ); # Link IDs are case-insensitive
|
||||
if ($3) {
|
||||
$self->{_titles}{lc $1} = $3;
|
||||
$self->{_titles}{lc $1} =~ s/"/"/g;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
# We need to look for HTML-escaped '<' and '>' (i.e. < and >).
|
||||
# We also remove Email linkification from the original implementation
|
||||
# as it is already done in Bugzilla's quoteUrls().
|
||||
sub _DoAutoLinks {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text =~ s{(?:<|<)((?:https?|ftp):[^'">\s]+?)(?:>|>)}{<a href="$1">$1</a>}gi;
|
||||
return $text;
|
||||
}
|
||||
|
||||
# The main reasons for overriding this method are
|
||||
# resolving URL conflicts with Bugzilla's quoteUrls()
|
||||
# and also changing '"' to '"' in regular expressions wherever needed.
|
||||
sub _DoAnchors {
|
||||
#
|
||||
# Turn Markdown link shortcuts into <a> tags.
|
||||
#
|
||||
my ($self, $text) = @_;
|
||||
|
||||
# We revert linkifications of non-email links and only
|
||||
# those links whose URL and title are the same because
|
||||
# this way we can be sure that link is generated by quoteUrls()
|
||||
$text =~ s@<a \s+ href="(?! mailto ) (.+?)">\1</a>@$1@xmg;
|
||||
|
||||
#
|
||||
# First, handle reference-style links: [link text] [id]
|
||||
#
|
||||
$text =~ s{
|
||||
( # wrap whole match in $1
|
||||
\[
|
||||
($g_nested_brackets) # link text = $2
|
||||
\]
|
||||
|
||||
[ ]? # one optional space
|
||||
(?:\n[ ]*)? # one optional newline followed by spaces
|
||||
|
||||
\[
|
||||
(.*?) # id = $3
|
||||
\]
|
||||
)
|
||||
}{
|
||||
my $whole_match = $1;
|
||||
my $link_text = $2;
|
||||
my $link_id = lc $3;
|
||||
|
||||
if ($link_id eq "") {
|
||||
$link_id = lc $link_text; # for shortcut links like [this][].
|
||||
}
|
||||
|
||||
$link_id =~ s{[ ]*\n}{ }g; # turn embedded newlines into spaces
|
||||
|
||||
$self->_GenerateAnchor($whole_match, $link_text, $link_id);
|
||||
}xsge;
|
||||
|
||||
#
|
||||
# Next, inline-style links: [link text](url "optional title")
|
||||
#
|
||||
$text =~ s{
|
||||
( # wrap whole match in $1
|
||||
\[
|
||||
($g_nested_brackets) # link text = $2
|
||||
\]
|
||||
\( # literal paren
|
||||
[ \t]*
|
||||
($g_nested_parens) # href = $3
|
||||
[ \t]*
|
||||
( # $4
|
||||
("|') # quote char = $5
|
||||
(.*?) # Title = $6
|
||||
\5 # matching quote
|
||||
[ \t]* # ignore any spaces/tabs between closing quote and )
|
||||
)? # title is optional
|
||||
\)
|
||||
)
|
||||
}{
|
||||
my $result;
|
||||
my $whole_match = $1;
|
||||
my $link_text = $2;
|
||||
my $url = $3;
|
||||
my $title = $6;
|
||||
|
||||
# Remove Bugzilla quoteUrls() linkification
|
||||
if ($url =~ /^a href="/ && $url =~ m|</a$|) {
|
||||
$url =~ s/^[^>]+>//;
|
||||
$url =~ s@</a$@@;
|
||||
}
|
||||
|
||||
# Limit URL to HTTP/HTTPS links
|
||||
$url = "http://$url" unless $url =~ m!^https?://!i;
|
||||
|
||||
$self->_GenerateAnchor($whole_match, $link_text, undef, $url, $title);
|
||||
}xsge;
|
||||
|
||||
#
|
||||
# Last, handle reference-style shortcuts: [link text]
|
||||
# These must come last in case you've also got [link test][1]
|
||||
# or [link test](/foo)
|
||||
#
|
||||
$text =~ s{
|
||||
( # wrap whole match in $1
|
||||
\[
|
||||
([^\[\]]+) # link text = $2; can't contain '[' or ']'
|
||||
\]
|
||||
)
|
||||
}{
|
||||
my $result;
|
||||
my $whole_match = $1;
|
||||
my $link_text = $2;
|
||||
(my $link_id = lc $2) =~ s{[ ]*\n}{ }g; # lower-case and turn embedded newlines into spaces
|
||||
|
||||
$self->_GenerateAnchor($whole_match, $link_text, $link_id);
|
||||
}xsge;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
# The purpose of overriding this function is to add support
|
||||
# for a Github Flavored Markdown (GFM) feature called 'Multiple
|
||||
# underscores in words'. The standard markdown specification
|
||||
# specifies the underscore for making the text emphasized/bold.
|
||||
# However, some variable names in programming languages contain underscores
|
||||
# and we do not want a part of those variables to look emphasized/bold.
|
||||
# Instead, we render them as the way they originally are.
|
||||
sub _DoItalicsAndBold {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
# Handle at beginning of lines:
|
||||
$text =~ s{ (^__ (?=\S) (.+?[*_]*) (?<=\S) __ (?!\S)) }
|
||||
{
|
||||
my $result = _has_multiple_underscores($2) ? $1 : "<strong>$2</strong>";
|
||||
$result;
|
||||
}gsxe;
|
||||
|
||||
$text =~ s{ ^\*\* (?=\S) (.+?[*_]*) (?<=\S) \*\* }{<strong>$1</strong>}gsx;
|
||||
|
||||
$text =~ s{ (^_ (?=\S) (.+?) (?<=\S) _ (?!\S)) }
|
||||
{
|
||||
my $result = _has_multiple_underscores($2) ? $1 : "<em>$2</em>";
|
||||
$result;
|
||||
}gsxe;
|
||||
|
||||
$text =~ s{ ^\* (?=\S) (.+?) (?<=\S) \* }{<em>$1</em>}gsx;
|
||||
|
||||
# <strong> must go first:
|
||||
$text =~ s{ ( (?<=\W) __ (?=\S) (.+?[*_]*) (?<=\S) __ (?!\S) ) }
|
||||
{
|
||||
my $result = _has_multiple_underscores($2) ? $1 : "<strong>$2</strong>";
|
||||
$result;
|
||||
}gsxe;
|
||||
|
||||
|
||||
$text =~ s{ (?<=\W) \*\* (?=\S) (.+?[*_]*) (?<=\S) \*\* }{<strong>$1</strong>}gsx;
|
||||
|
||||
$text =~ s{ ( (?<=\W) _ (?=\S) (.+?) (?<=\S) _ (?!\S) ) }
|
||||
{
|
||||
my $result = _has_multiple_underscores($2) ? $1 : "<em>$2</em>";
|
||||
$result;
|
||||
}gsxe;
|
||||
|
||||
$text =~ s{ (?<=\W) \* (?=\S) (.+?) (?<=\S) \* }{<em>$1</em>}gsx;
|
||||
|
||||
# And now, a second pass to catch nested strong and emphasis special cases
|
||||
$text =~ s{ ( (?<=\W) __ (?=\S) (.+?[*_]*) (?<=\S) __ (\S*) ) }
|
||||
{
|
||||
my $result = _has_multiple_underscores($3) ? $1 : "<strong>$2</strong>$3";
|
||||
$result;
|
||||
}gsxe;
|
||||
|
||||
$text =~ s{ (?<=\W) \*\* (?=\S) (.+?[*_]*) (?<=\S) \*\* }{<strong>$1</strong>}gsx;
|
||||
$text =~ s{ ( (?<=\W) _ (?=\S) (.+?) (?<=\S) _ (\S*) ) }
|
||||
{
|
||||
my $result = _has_multiple_underscores($3) ? $1 : "<em>$2</em>$3";
|
||||
$result;
|
||||
}gsxe;
|
||||
|
||||
$text =~ s{ (?<=\W) \* (?=\S) (.+?) (?<=\S) \* }{<em>$1</em>}gsx;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub _DoStrikethroughs {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text =~ s{ ^ ~~ (?=\S) ([^~]+?) (?<=\S) ~~ (?!~) }{<del>$1</del>}gsx;
|
||||
$text =~ s{ (?<=_|[^~\w]) ~~ (?=\S) ([^~]+?) (?<=\S) ~~ (?!~) }{<del>$1</del>}gsx;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
# The original _DoCodeSpans() uses the 's' modifier in its regex
|
||||
# which prevents _DoCodeBlocks() to match GFM fenced code blocks.
|
||||
# We copy the code from the original implementation and remove the
|
||||
# 's' modifier from it.
|
||||
sub _DoCodeSpans {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text =~ s@
|
||||
(?<!\\) # Character before opening ` can't be a backslash
|
||||
(`+) # $1 = Opening run of `
|
||||
(.+?) # $2 = The code block
|
||||
(?<!`)
|
||||
\1 # Matching closer
|
||||
(?!`)
|
||||
@
|
||||
my $c = "$2";
|
||||
$c =~ s/^[ \t]*//g; # leading whitespace
|
||||
$c =~ s/[ \t]*$//g; # trailing whitespace
|
||||
$c = $self->_EncodeCode($c);
|
||||
"<code>$c</code>";
|
||||
@egx;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
# Override to add GFM Fenced Code Blocks
|
||||
sub _DoCodeBlocks {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text =~ s{
|
||||
^ `{3,} [\s\t]* \n
|
||||
( # $1 = the entire code block
|
||||
(?: .* \n+)+?
|
||||
)
|
||||
`{3,} [\s\t]* $
|
||||
}{
|
||||
my $codeblock = $1;
|
||||
my $result;
|
||||
|
||||
$codeblock = $self->_EncodeCode($codeblock);
|
||||
$codeblock = $self->_Detab($codeblock);
|
||||
$codeblock =~ s/\n\z//; # remove the trailing newline
|
||||
|
||||
$result = "\n\n<pre><code>" . $codeblock . "</code></pre>\n\n";
|
||||
$result;
|
||||
}egmx;
|
||||
|
||||
# And now do the standard code blocks
|
||||
$text = $self->SUPER::_DoCodeBlocks($text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub _DoBlockQuotes {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text =~ s{
|
||||
( # Wrap whole match in $1
|
||||
(?:
|
||||
^[ \t]*>[ \t]? # '>' at the start of a line
|
||||
.+\n # rest of the first line
|
||||
(?:.+\n)* # subsequent consecutive lines
|
||||
\n* # blanks
|
||||
)+
|
||||
)
|
||||
}{
|
||||
my $bq = $1;
|
||||
$bq =~ s/^[ \t]*>[ \t]?//gm; # trim one level of quoting
|
||||
$bq =~ s/^[ \t]+$//mg; # trim whitespace-only lines
|
||||
$bq = $self->_RunBlockGamut($bq, {wrap_in_p_tags => 1}); # recurse
|
||||
$bq =~ s/^/ /mg;
|
||||
# These leading spaces screw with <pre> content, so we need to fix that:
|
||||
$bq =~ s{(\s*<pre>.+?</pre>)}{
|
||||
my $pre = $1;
|
||||
$pre =~ s/^ //mg;
|
||||
$pre;
|
||||
}egs;
|
||||
"<blockquote>\n$bq\n</blockquote>\n\n";
|
||||
}egmx;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub _EncodeCode {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
# We need to unescape the escaped HTML characters in code blocks.
|
||||
# These are the reverse of the escapings done in Bugzilla::Util::html_quote()
|
||||
$text =~ s/</</g;
|
||||
$text =~ s/>/>/g;
|
||||
$text =~ s/"/"/g;
|
||||
$text =~ s/@/@/g;
|
||||
# '&' substitution must be the last one, otherwise a literal like '>'
|
||||
# will turn to '>' because '&' is already changed to '&' in Bugzilla::Util::html_quote().
|
||||
# In other words, html_quote() will change '>' to '&gt;' and then we will
|
||||
# change '&gt' -> '>' -> '>' if we write this substitution as the first one.
|
||||
$text =~ s/&/&/g;
|
||||
$text =~ s{<a \s+ href="(?:mailto:)? (.+?)"> \1 </a>}{$1}xmgi;
|
||||
$text = $self->SUPER::_EncodeCode($text);
|
||||
$text =~ s/~/$g_escape_table{'~'}/go;
|
||||
# Encode '<' to prevent URLs from getting linkified in code spans
|
||||
$text =~ s/</$g_escape_table{'<'}/go;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub _EncodeBackslashEscapes {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text = $self->SUPER::_EncodeBackslashEscapes($text);
|
||||
$text =~ s/\\~/$g_escape_table{'~'}/go;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
sub _UnescapeSpecialChars {
|
||||
my ($self, $text) = @_;
|
||||
|
||||
$text = $self->SUPER::_UnescapeSpecialChars($text);
|
||||
$text =~ s/$g_escape_table{'~'}/~/go;
|
||||
$text =~ s/$g_escape_table{'<'}/</go;
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
# Check if the passed string is of the form multiple_underscores_in_a_word.
|
||||
# To check that, we first need to make sure that the string does not contain
|
||||
# any white-space. Then, if the string is composed of non-space chunks which
|
||||
# are bound together with underscores, the string has the desired form.
|
||||
sub _has_multiple_underscores {
|
||||
my $string = shift;
|
||||
return 0 unless defined($string) && length($string);
|
||||
return 0 if $string =~ /[\t\s]+/;
|
||||
return 1 if scalar (split /_/, $string) > 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Bugzilla::Markdown - Generates HTML output from structured plain-text input.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Bugzilla::Markdown;
|
||||
|
||||
my $markdown = Bugzilla::Markdown->new();
|
||||
print $markdown->markdown($text);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Bugzilla::Markdown implements a Markdown engine that produces
|
||||
an HTML-based output from a given plain-text input.
|
||||
|
||||
The majority of the implementation is done by C<Text::Markdown>
|
||||
CPAN module. It also applies the linkifications done in L<Bugzilla::Template>
|
||||
to the input resulting in an output which is a combination of both Markdown
|
||||
structures and those defined by Bugzilla itself.
|
||||
|
||||
=head2 Accessors
|
||||
|
||||
=over
|
||||
|
||||
=item C<markdown>
|
||||
|
||||
C<string> Produces an HTML-based output string based on the structures
|
||||
and format defined in the given plain-text input.
|
||||
|
||||
=over
|
||||
|
||||
=item B<Params>
|
||||
|
||||
=over
|
||||
|
||||
=item C<text>
|
||||
|
||||
C<string> A plain-text string which includes Markdown structures.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
@ -254,13 +254,10 @@ sub _get {
|
||||
elsif (ref($value) eq 'ARRAY') {
|
||||
foreach my $value (@$value) {
|
||||
next unless defined $value;
|
||||
# arrays of hashes and arrays are common
|
||||
# arrays of hashes are common
|
||||
if (ref($value) eq 'HASH') {
|
||||
_detaint_hashref($value);
|
||||
}
|
||||
elsif (ref($value) eq 'ARRAY') {
|
||||
_detaint_arrayref($value);
|
||||
}
|
||||
elsif (!ref($value)) {
|
||||
trick_taint($value);
|
||||
}
|
||||
@ -281,15 +278,6 @@ sub _detaint_hashref {
|
||||
}
|
||||
}
|
||||
|
||||
sub _detaint_arrayref {
|
||||
my ($arrayref) = @_;
|
||||
foreach my $value (@$arrayref) {
|
||||
if (defined($value) && !ref($value)) {
|
||||
trick_taint($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _delete {
|
||||
my ($self, $key) = @_;
|
||||
$key = $self->_encode_key($key)
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Migrate;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Attachment;
|
||||
use Bugzilla::Bug qw(LogActivityEntry);
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Migrate::Gnats;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Migrate);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Milestone;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Object);
|
||||
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Object;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Bugzilla::Constants;
|
||||
use Bugzilla::Hook;
|
||||
|
||||
@ -9,7 +9,6 @@ package Bugzilla::Product;
|
||||
|
||||
use 5.10.1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use parent qw(Bugzilla::Field::ChoiceInterface Bugzilla::Object);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user