diff options
author | 2015-12-28 12:30:49 -0800 | |
---|---|---|
committer | 2015-12-28 12:30:56 -0800 | |
commit | 18927a43465e7662b8558cf2d276d5f0bccd1e50 (patch) | |
tree | 0af3669d198ba4bd52eb2c6c8bdf0b33cb906e93 | |
parent | There's currently no loadbalancing (diff) | |
parent | Bug 1235415: Use "AllowOverride All" everywhere (diff) | |
download | bugzilla-18927a43465e7662b8558cf2d276d5f0bccd1e50.tar.gz bugzilla-18927a43465e7662b8558cf2d276d5f0bccd1e50.tar.bz2 bugzilla-18927a43465e7662b8558cf2d276d5f0bccd1e50.zip |
Merge remote-tracking branch 'upstream/5.0' into bugstest
Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
43 files changed, 646 insertions, 400 deletions
@@ -5,12 +5,7 @@ Deny from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Deny from all - </IfModule> - <IfModule !mod_perl.c> - Require all denied - </IfModule> + Require all denied </IfVersion> </IfModule> <IfModule !mod_version.c> diff --git a/Bugzilla.pm b/Bugzilla.pm index e3184fdb8..aa78f1483 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -82,11 +82,27 @@ sub init_page { } if (${^TAINT}) { + my $path = ''; + if (ON_WINDOWS) { + # On Windows, these paths are tainted, preventing + # File::Spec::Win32->tmpdir from using them. But we need + # a place to temporary store attachments which are uploaded. + foreach my $temp (qw(TMPDIR TMP TEMP)) { + trick_taint($ENV{$temp}) if $ENV{$temp}; + } + # Some DLLs used by Strawberry Perl are also in c\bin, + # see https://rt.cpan.org/Public/Bug/Display.html?id=99104 + if (!ON_ACTIVESTATE) { + my $c_path = $path = dirname($^X); + $c_path =~ s/\bperl\b(?=\\bin)/c/; + $path .= ";$c_path"; + } + } # Some environment variables are not taint safe delete @::ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; # Some modules throw undefined errors (notably File::Spec::Win32) if # PATH is undefined. - $ENV{'PATH'} = ''; + $ENV{'PATH'} = $path; } # Because this function is run live from perl "use" commands of diff --git a/Bugzilla/BugMail.pm b/Bugzilla/BugMail.pm index 9ebf3ea7d..d4a1597ab 100644 --- a/Bugzilla/BugMail.pm +++ b/Bugzilla/BugMail.pm @@ -19,6 +19,7 @@ use Bugzilla::Bug; use Bugzilla::Comment; use Bugzilla::Mailer; use Bugzilla::Hook; +use Bugzilla::MIME; use Date::Parse; use Date::Format; @@ -435,6 +436,7 @@ sub _generate_bugmail { my $user = $vars->{to_user}; my $template = Bugzilla->template_inner($user->setting('lang')); my ($msg_text, $msg_html, $msg_header); + state $use_utf8 = Bugzilla->params->{'utf8'}; $template->process("email/bugmail-header.txt.tmpl", $vars, \$msg_header) || ThrowTemplateError($template->error()); @@ -442,32 +444,35 @@ sub _generate_bugmail { || ThrowTemplateError($template->error()); my @parts = ( - Email::MIME->create( + Bugzilla::MIME->create( attributes => { - content_type => "text/plain", + content_type => 'text/plain', + charset => $use_utf8 ? 'UTF-8' : 'iso-8859-1', + encoding => 'quoted-printable', }, - body => $msg_text, + body_str => $msg_text, ) ); if ($user->setting('email_format') eq 'html') { $template->process("email/bugmail.html.tmpl", $vars, \$msg_html) || ThrowTemplateError($template->error()); - push @parts, Email::MIME->create( + push @parts, Bugzilla::MIME->create( attributes => { - content_type => "text/html", + content_type => 'text/html', + charset => $use_utf8 ? 'UTF-8' : 'iso-8859-1', + encoding => 'quoted-printable', }, - body => $msg_html, + body_str => $msg_html, ); } - # TT trims the trailing newline, and threadingmarker may be ignored. - my $email = new Email::MIME("$msg_header\n"); + my $email = Bugzilla::MIME->new($msg_header); if (scalar(@parts) == 1) { $email->content_type_set($parts[0]->content_type); } else { $email->content_type_set('multipart/alternative'); # Some mail clients need same encoding for each part, even empty ones. - $email->charset_set('UTF-8') if Bugzilla->params->{'utf8'}; + $email->charset_set('UTF-8') if $use_utf8; } $email->parts_set(\@parts); return $email; diff --git a/Bugzilla/Config.pm b/Bugzilla/Config.pm index b4ff803bd..1c02d9dda 100644 --- a/Bugzilla/Config.pm +++ b/Bugzilla/Config.pm @@ -315,7 +315,13 @@ sub read_param_file { } # JSON::XS doesn't detaint data for us. foreach my $key (keys %params) { - trick_taint($params{$key}) if defined $params{$key}; + if (ref($params{$key}) eq "ARRAY") { + foreach my $item (@{$params{$key}}) { + trick_taint($item); + } + } else { + trick_taint($params{$key}) if defined $params{$key}; + } } } elsif ($ENV{'SERVER_SOFTWARE'}) { diff --git a/Bugzilla/Config/Common.pm b/Bugzilla/Config/Common.pm index e8dfe3e9d..bd9b0bf84 100644 --- a/Bugzilla/Config/Common.pm +++ b/Bugzilla/Config/Common.pm @@ -45,7 +45,10 @@ sub check_multi { return ""; } elsif ($param->{'type'} eq 'm' || $param->{'type'} eq 'o') { - foreach my $chkParam (split(',', $value)) { + if (ref($value) ne "ARRAY") { + $value = [split(',', $value)] + } + foreach my $chkParam (@$value) { unless (scalar(grep {$_ eq $chkParam} (@{$param->{'choices'}}))) { return "Invalid choice '$chkParam' for multi-select list param '$param->{'name'}'"; } diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 0a8295eb6..f2fb93297 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -200,7 +200,7 @@ use Memoize; # CONSTANTS # # Bugzilla version -use constant BUGZILLA_VERSION => "5.0.1"; +use constant BUGZILLA_VERSION => "5.0.2+"; # 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. diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 6c9a29ebb..5bc83f9d6 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -363,6 +363,31 @@ sub sql_position { return "POSITION($fragment IN $text)"; } +sub sql_like { + my ($self, $fragment, $column) = @_; + + my $quoted = $self->quote($fragment); + + return $self->sql_position($quoted, $column) . " > 0"; +} + +sub sql_ilike { + my ($self, $fragment, $column) = @_; + + my $quoted = $self->quote($fragment); + + return $self->sql_iposition($quoted, $column) . " > 0"; +} + +sub sql_not_ilike { + my ($self, $fragment, $column) = @_; + + my $quoted = $self->quote($fragment); + + return $self->sql_iposition($quoted, $column) . " = 0"; +} + + sub sql_group_by { my ($self, $needed_columns, $optional_columns) = @_; @@ -2014,6 +2039,73 @@ Formatted SQL for substring search (scalar) Just like L</sql_position>, but case-insensitive. +=item C<sql_like> + +=over + +=item B<Description> + +Outputs SQL to search for an instance of a string (fragment) +in a table column (column). + +Note that the fragment must not be quoted. L</sql_like> will +quote the fragment itself. + +This is a case sensitive search. + +Note: This does not necessarily generate an ANSI LIKE statement, but +could be overridden to do so in a database subclass if required. + +=item B<Params> + +=over + +=item C<$fragment> - the string fragment that we are searching for (scalar) + +=item C<$column> - the column to search + +=back + +=item B<Returns> + +Formatted SQL to return results from columns that contain the fragment. + +=back + +=item C<sql_ilike> + +Just like L</sql_like>, but case-insensitive. + +=item C<sql_not_ilike> + +=over + +=item B<Description> + +Outputs SQL to search for columns (column) that I<do not> contain +instances of the string (fragment). + +Note that the fragment must not be quoted. L</sql_not_ilike> will +quote the fragment itself. + +This is a case insensitive search. + +=item B<Params> + +=over + +=item C<$fragment> - the string fragment that we are searching for (scalar) + +=item C<$column> - the column to search + +=back + +=item B<Returns> + +Formated sql to return results from columns that do not contain the fragment + +=back + =item C<sql_group_by> =over diff --git a/Bugzilla/DB/Pg.pm b/Bugzilla/DB/Pg.pm index a950c575f..cbf8d7af1 100644 --- a/Bugzilla/DB/Pg.pm +++ b/Bugzilla/DB/Pg.pm @@ -126,6 +126,36 @@ sub sql_position { return "POSITION(${fragment}::text IN ${text}::text)"; } +sub sql_like { + my ($self, $fragment, $column, $not) = @_; + $not //= ''; + + return "${column}::text $not LIKE " . $self->sql_like_escape($fragment) . " ESCAPE '|'"; +} + +sub sql_ilike { + my ($self, $fragment, $column, $not) = @_; + $not //= ''; + + return "${column}::text $not ILIKE " . $self->sql_like_escape($fragment) . " ESCAPE '|'"; +} + +sub sql_not_ilike { + return shift->sql_ilike(@_, 'NOT'); +} + +# Escapes any % or _ characters which are special in a LIKE match. +# Also performs a $dbh->quote to escape any quote characters. +sub sql_like_escape { + my ($self, $fragment) = @_; + + $fragment =~ s/\|/\|\|/g; # escape the escape character if it appears + $fragment =~ s/%/\|%/g; # percent and underscore are the special match + $fragment =~ s/_/\|_/g; # characters in SQL. + + return $self->quote("%$fragment%"); +} + sub sql_regexp { my ($self, $expr, $pattern, $nocheck, $real_pattern) = @_; $real_pattern ||= $pattern; @@ -448,6 +478,39 @@ sub bz_table_list_real { 1; +=head2 Functions + +=over + +=item C<sql_like_escape> + +=over + +=item B<Description> + +The postgres versions of the sql_like methods use the ANSI SQL LIKE +statements to perform substring searching. To prevent issues with +users attempting to search for strings containing special characters +associated with LIKE, we escape them out so they don't affect the search +terms. + +=item B<Params> + +=over + +=item C<$fragment> - The string fragment in need of escaping and quoting + +=back + +=item B<Returns> + +The fragment with any pre existing %,_,| characters escaped out, wrapped in +percent characters and quoted. + +=back + +=back + =head1 B<Methods in need of POD> =over @@ -462,6 +525,12 @@ sub bz_table_list_real { =item sql_position +=item sql_like + +=item sql_ilike + +=item sql_not_ilike + =item sql_limit =item sql_not_regexp diff --git a/Bugzilla/Group.pm b/Bugzilla/Group.pm index 07b78e366..f7a50f7f1 100644 --- a/Bugzilla/Group.pm +++ b/Bugzilla/Group.pm @@ -383,6 +383,7 @@ sub create { my $dbh = Bugzilla->dbh; my $silently = delete $params->{silently}; + my $use_in_all_products = delete $params->{use_in_all_products}; if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE and !$silently) { print get_text('install_group_create', { name => $params->{name} }), "\n"; @@ -406,6 +407,14 @@ sub create { $sth->execute($admin->id, $group->id, GROUP_VISIBLE); } + # Permit all existing products to use the new group if requested. + if ($use_in_all_products) { + $dbh->do('INSERT INTO group_control_map + (group_id, product_id, membercontrol, othercontrol) + SELECT ?, products.id, ?, ? FROM products', + undef, ($group->id, CONTROLMAPSHOWN, CONTROLMAPNA)); + } + $group->_rederive_regexp() if $group->user_regexp; Bugzilla::Hook::process('group_end_of_create', { group => $group }); @@ -524,8 +533,11 @@ provides, in addition to any methods documented below. Note that in addition to what L<Bugzilla::Object/create($params)> normally does, this function also makes the new group be inherited -by the C<admin> group. That is, the C<admin> group will automatically -be a member of this group. +by the C<admin> group and optionally inserts access controls for +this group into all existing products. That is, the C<admin> group +will automatically be a member of this group and bugs for all +products may optionally be restricted to this group by group +members. =item C<ValidateGroupName($name, @users)> diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index 96f14ec0f..ed2539251 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -729,6 +729,9 @@ sub update_table_definitions { # 2014-11-10 dkl@mozilla.com - Bug 1093928 $dbh->bz_drop_column('longdescs', 'is_markdown'); + # 2015-12-16 LpSolit@gmail.com - Bug 1232578 + _sanitize_audit_log_table(); + ################################################################ # New --TABLE-- changes should go *** A B O V E *** this point # ################################################################ @@ -3914,6 +3917,30 @@ sub _update_alias { $dbh->bz_drop_column('bugs', 'alias'); } +sub _sanitize_audit_log_table { + my $dbh = Bugzilla->dbh; + + # Replace hashed passwords by a generic comment. + my $class = 'Bugzilla::User'; + my $field = 'cryptpassword'; + + my $hashed_passwd = + $dbh->selectcol_arrayref('SELECT added FROM audit_log WHERE class = ? AND field = ? + AND ' . $dbh->sql_not_ilike('hashed_with_', 'added'), + undef, ($class, $field)); + if (@$hashed_passwd) { + say "Sanitizing hashed passwords stored in the 'audit_log' table..."; + my $sth = $dbh->prepare('UPDATE audit_log SET added = ? + WHERE class = ? AND field = ? AND added = ?'); + + foreach my $passwd (@$hashed_passwd) { + my (undef, $sanitized_passwd) = + Bugzilla::Object::_sanitize_audit_log($class, $field, [undef, $passwd]); + $sth->execute($sanitized_passwd, $class, $field, $passwd); + } + } +} + 1; __END__ diff --git a/Bugzilla/Install/Filesystem.pm b/Bugzilla/Install/Filesystem.pm index 5003047c3..4ed322bc9 100644 --- a/Bugzilla/Install/Filesystem.pm +++ b/Bugzilla/Install/Filesystem.pm @@ -52,12 +52,7 @@ use constant HT_DEFAULT_DENY => <<EOT; Deny from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Deny from all - </IfModule> - <IfModule !mod_perl.c> - Require all denied - </IfModule> + Require all denied </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -359,12 +354,7 @@ EOT Allow from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Allow from all - </IfModule> - <IfModule !mod_perl.c> - Require all granted - </IfModule> + Require all granted </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -378,12 +368,7 @@ EOT Deny from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Deny from all - </IfModule> - <IfModule !mod_perl.c> - Require all denied - </IfModule> + Require all denied </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -403,14 +388,8 @@ EOT Deny from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Allow from 192.20.225.0/24 - Deny from all - </IfModule> - <IfModule !mod_perl.c> - Require ip 192.20.225.0/24 - Require all denied - </IfModule> + Require ip 192.20.225.0/24 + Require all denied </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -426,12 +405,7 @@ EOT Allow from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Allow from all - </IfModule> - <IfModule !mod_perl.c> - Require all granted - </IfModule> + Require all granted </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -445,12 +419,7 @@ EOT Deny from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Deny from all - </IfModule> - <IfModule !mod_perl.c> - Require all denied - </IfModule> + Require all denied </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -467,12 +436,7 @@ EOT Allow from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Allow from all - </IfModule> - <IfModule !mod_perl.c> - Require all granted - </IfModule> + Require all granted </IfVersion> </IfModule> <IfModule !mod_version.c> @@ -486,12 +450,7 @@ EOT Deny from all </IfVersion> <IfVersion >= 2.4> - <IfModule mod_perl.c> - Deny from all - </IfModule> - <IfModule !mod_perl.c> - Require all denied - </IfModule> + Require all denied </IfVersion> </IfModule> <IfModule !mod_version.c> diff --git a/Bugzilla/MIME.pm b/Bugzilla/MIME.pm new file mode 100644 index 000000000..7b5843a78 --- /dev/null +++ b/Bugzilla/MIME.pm @@ -0,0 +1,132 @@ +# 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::MIME; + +use 5.10.1; +use strict; +use warnings; + +use parent qw(Email::MIME); + +use Encode qw(encode); +use Encode::MIME::Header; + +sub new { + my ($class, $msg) = @_; + state $use_utf8 = Bugzilla->params->{'utf8'}; + + # Template-Toolkit trims trailing newlines, which is problematic when + # parsing headers. + $msg =~ s/\n*$/\n/; + + # Because the encoding headers are not present in our email templates, we + # need to treat them as binary UTF-8 when parsing. + my ($in_header, $has_type, $has_encoding, $has_body) = (1); + foreach my $line (split(/\n/, $msg)) { + if ($line eq '') { + $in_header = 0; + next; + } + if (!$in_header) { + $has_body = 1; + last; + } + $has_type = 1 if $line =~ /^Content-Type:/i; + $has_encoding = 1 if $line =~ /^Content-Transfer-Encoding:/i; + } + if ($has_body) { + if (!$has_type && $use_utf8) { + $msg = qq#Content-Type: text/plain; charset="UTF-8"\n# . $msg; + } + if (!$has_encoding) { + $msg = qq#Content-Transfer-Encoding: binary\n# . $msg; + } + } + if ($use_utf8 && utf8::is_utf8($msg)) { + utf8::encode($msg); + } + + # RFC 2822 requires us to have CRLF for our line endings and + # 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 + $msg =~ s/(?:\015+)?\012/\015\012/msg; + + return $class->SUPER::new($msg); +} + +sub as_string { + my $self = shift; + state $use_utf8 = Bugzilla->params->{'utf8'}; + + # We add this header to uniquely identify all email that we + # send as coming from this Bugzilla installation. + # + # We don't use correct_urlbase, because we want this URL to + # *always* be the same for this Bugzilla, in every email, + # even if the admin changes the "ssl_redirect" parameter some day. + $self->header_set('X-Bugzilla-URL', Bugzilla->params->{'urlbase'}); + + # We add this header to mark the mail as "auto-generated" and + # thus to hopefully avoid auto replies. + $self->header_set('Auto-Submitted', 'auto-generated'); + + # MIME-Version must be set otherwise some mailsystems ignore the charset + $self->header_set('MIME-Version', '1.0') if !$self->header('MIME-Version'); + + # Encode the headers correctly in quoted-printable + foreach my $header ($self->header_names) { + my @values = $self->header($header); + # We don't recode headers that happen multiple times. + next if scalar(@values) > 1; + if (my $value = $values[0]) { + utf8::decode($value) unless $use_utf8 && utf8::is_utf8($value); + + # avoid excessive line wrapping done by Encode. + local $Encode::Encoding{'MIME-Q'}->{'bpl'} = 998; + + my $encoded = encode('MIME-Q', $value); + $self->header_set($header, $encoded); + } + } + + # Ensure the character-set and encoding is set correctly on single part + # emails. Multipart emails should have these already set when the parts + # are assembled. + if (scalar($self->parts) == 1) { + $self->charset_set('UTF-8') if $use_utf8; + $self->encoding_set('quoted-printable'); + } + + # Ensure we always return the encoded string + my $value = $self->SUPER::as_string(); + if ($use_utf8 && utf8::is_utf8($value)) { + utf8::encode($value); + } + + return $value; +} + +1; + +__END__ + +=head1 NAME + +Bugzilla::MIME - Wrapper around Email::MIME for unifying MIME related +workarounds. + +=head1 SYNOPSIS + + use Bugzilla::MIME; + my $email = Bugzilla::MIME->new($message); + +=head1 DESCRIPTION + +Bugzilla::MIME subclasses Email::MIME and performs various fixes when parsing +and generating email. diff --git a/Bugzilla/Mailer.pm b/Bugzilla/Mailer.pm index 196c57ec0..7ae81299f 100644 --- a/Bugzilla/Mailer.pm +++ b/Bugzilla/Mailer.pm @@ -17,13 +17,11 @@ use parent qw(Exporter); use Bugzilla::Constants; use Bugzilla::Error; use Bugzilla::Hook; +use Bugzilla::MIME; use Bugzilla::Util; use Date::Format qw(time2str); -use Encode qw(encode); -use Encode::MIME::Header; -use Email::MIME; use Email::Sender::Simple qw(sendmail); use Email::Sender::Transport::SMTP::Persistent; use Bugzilla::Sender::Transport::Sendmail; @@ -43,18 +41,7 @@ sub MessageToMTA { my $dbh = Bugzilla->dbh; - my $email; - if (ref $msg) { - $email = $msg; - } - else { - # RFC 2822 requires us to have CRLF for our line endings and - # 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 - $msg =~ s/(?:\015+)?\012/\015\012/msg; - $email = new Email::MIME($msg); - } + my $email = ref($msg) ? $msg : Bugzilla::MIME->new($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 @@ -71,39 +58,6 @@ sub MessageToMTA { return; } - # We add this header to uniquely identify all email that we - # send as coming from this Bugzilla installation. - # - # We don't use correct_urlbase, because we want this URL to - # *always* be the same for this Bugzilla, in every email, - # even if the admin changes the "ssl_redirect" parameter some day. - $email->header_set('X-Bugzilla-URL', Bugzilla->params->{'urlbase'}); - - # We add this header to mark the mail as "auto-generated" and - # thus to hopefully avoid auto replies. - $email->header_set('Auto-Submitted', 'auto-generated'); - - # MIME-Version must be set otherwise some mailsystems ignore the charset - $email->header_set('MIME-Version', '1.0') if !$email->header('MIME-Version'); - - # Encode the headers correctly in quoted-printable - foreach my $header ($email->header_names) { - my @values = $email->header($header); - # We don't recode headers that happen multiple times. - next if scalar(@values) > 1; - if (my $value = $values[0]) { - if (Bugzilla->params->{'utf8'} && !utf8::is_utf8($value)) { - utf8::decode($value); - } - - # avoid excessive line wrapping done by Encode. - local $Encode::Encoding{'MIME-Q'}->{'bpl'} = 998; - - my $encoded = encode('MIME-Q', $value); - $email->header_set($header, $encoded); - } - } - my $from = $email->header('From'); my $hostname; @@ -148,29 +102,6 @@ sub MessageToMTA { return if $email->header('to') eq ''; - $email->walk_parts(sub { - my ($part) = @_; - return if $part->parts > 1; # Top-level - my $content_type = $part->content_type || ''; - $content_type =~ /charset=['"](.+)['"]/; - # If no charset is defined or is the default us-ascii, - # then we encode the email to UTF-8 if Bugzilla has utf8 enabled. - # XXX - This is a hack to workaround bug 723944. - if (!$1 || $1 eq 'us-ascii') { - my $body = $part->body; - if (Bugzilla->params->{'utf8'}) { - $part->charset_set('UTF-8'); - # encoding_set works only with bytes, not with utf8 strings. - my $raw = $part->body_raw; - if (utf8::is_utf8($raw)) { - utf8::encode($raw); - $part->body_set($raw); - } - } - $part->encoding_set('quoted-printable') if !is_7bit_clean($body); - } - }); - if ($method eq "Test") { my $filename = bz_locations()->{'datadir'} . '/mailer.testfile'; open TESTFILE, '>>', $filename; diff --git a/Bugzilla/Object.pm b/Bugzilla/Object.pm index 8f25e2b20..d43c8ca34 100644 --- a/Bugzilla/Object.pm +++ b/Bugzilla/Object.pm @@ -599,11 +599,29 @@ sub audit_log { foreach my $field (keys %$changes) { # Skip private changes. next if $field =~ /^_/; - my ($from, $to) = @{ $changes->{$field} }; + my ($from, $to) = $self->_sanitize_audit_log($field, $changes->{$field}); $sth->execute($user_id, $class, $self->id, $field, $from, $to); } } +sub _sanitize_audit_log { + my ($self, $field, $changes) = @_; + my $class = ref($self) || $self; + + # Do not store hashed passwords. Only record the algorithm used to encode them. + if ($class eq 'Bugzilla::User' && $field eq 'cryptpassword') { + foreach my $passwd (@$changes) { + next unless $passwd; + my $algorithm = 'unknown_algorithm'; + if ($passwd =~ /{([^}]+)}$/) { + $algorithm = $1; + } + $passwd = "hashed_with_$algorithm"; + } + } + return @$changes; +} + sub flatten_to_hash { my $self = shift; my $class = blessed($self); diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index 8097d5fb8..0785a7e67 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -2126,9 +2126,7 @@ sub _substring_terms { # split each term on spaces and commas anyway. my @words = split(/[\s,]+/, $args->{value}); @words = grep { defined $_ and $_ ne '' } @words; - @words = map { $dbh->quote($_) } @words; - my @terms = map { $dbh->sql_iposition($_, $args->{full_field}) . " > 0" } - @words; + my @terms = map { $dbh->sql_ilike($_, $args->{full_field}) } @words; return @terms; } @@ -3154,28 +3152,26 @@ sub _simple_operator { sub _casesubstring { my ($self, $args) = @_; - my ($full_field, $quoted) = @$args{qw(full_field quoted)}; + my ($full_field, $value) = @$args{qw(full_field value)}; my $dbh = Bugzilla->dbh; - - $args->{term} = $dbh->sql_position($quoted, $full_field) . " > 0"; + + $args->{term} = $dbh->sql_like($value, $full_field); } sub _substring { my ($self, $args) = @_; - my ($full_field, $quoted) = @$args{qw(full_field quoted)}; + my ($full_field, $value) = @$args{qw(full_field value)}; my $dbh = Bugzilla->dbh; - - # XXX This should probably be changed to just use LIKE - $args->{term} = $dbh->sql_iposition($quoted, $full_field) . " > 0"; + + $args->{term} = $dbh->sql_ilike($value, $full_field); } sub _notsubstring { my ($self, $args) = @_; - my ($full_field, $quoted) = @$args{qw(full_field quoted)}; + my ($full_field, $value) = @$args{qw(full_field value)}; my $dbh = Bugzilla->dbh; - - # XXX This should probably be changed to just use NOT LIKE - $args->{term} = $dbh->sql_iposition($quoted, $full_field) . " = 0"; + + $args->{term} = $dbh->sql_not_ilike($value, $full_field); } sub _regexp { diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index 92c69d483..d5f5034fa 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -880,6 +880,9 @@ sub create { { my ($var) = @_; $var = ' ' . $var if substr($var, 0, 1) eq '='; + # backslash is not special to CSV, but it can be used to confuse some browsers... + # so we do not allow it to happen. We only do this for logged-in users. + $var =~ s/\\/\x{FF3C}/g if Bugzilla->user->id; $var =~ s/\"/\"\"/g; if ($var !~ /^-?(\d+\.)?\d*$/) { $var = "\"$var\""; diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm index 6cfef6db5..77e6cebb0 100644 --- a/Bugzilla/User.pm +++ b/Bugzilla/User.pm @@ -922,9 +922,10 @@ sub groups { } sub last_visited { - my ($self) = @_; + my ($self, $ids) = @_; - return Bugzilla::BugUserLastVisit->match({ user_id => $self->id }); + return Bugzilla::BugUserLastVisit->match({ user_id => $self->id, + $ids ? ( bug_id => $ids ) : () }); } sub is_involved_in_bug { diff --git a/Bugzilla/User/Setting.pm b/Bugzilla/User/Setting.pm index ea3bbfb54..aece3b7de 100644 --- a/Bugzilla/User/Setting.pm +++ b/Bugzilla/User/Setting.pm @@ -127,7 +127,7 @@ sub add_setting { my $exists = _setting_exists($name); return if ($exists && !$force_check); - ($name && $default_value) + ($name && length( $default_value // '' )) || ThrowCodeError("setting_info_invalid"); if ($exists) { diff --git a/Bugzilla/WebService/BugUserLastVisit.pm b/Bugzilla/WebService/BugUserLastVisit.pm index 19a56ff46..56e91ec31 100644 --- a/Bugzilla/WebService/BugUserLastVisit.pm +++ b/Bugzilla/WebService/BugUserLastVisit.pm @@ -36,7 +36,7 @@ sub update { # Cache permissions for bugs. This highly reduces the number of calls to the # DB. visible_bugs() is only able to handle bug IDs, so we have to skip # aliases. - $user->visible_bugs([grep /^[0-9]$/, @$ids]); + $user->visible_bugs([grep /^[0-9]+$/, @$ids]); $dbh->bz_start_transaction(); my @results; @@ -52,7 +52,7 @@ sub update { push( @results, $self->_bug_user_last_visit_to_hash( - $bug, $last_visit_ts, $params + $bug->id, $last_visit_ts, $params )); } $dbh->bz_commit_transaction(); @@ -67,27 +67,23 @@ sub get { $user->login(LOGIN_REQUIRED); + my @last_visits; if ($ids) { # Cache permissions for bugs. This highly reduces the number of calls to # the DB. visible_bugs() is only able to handle bug IDs, so we have to # skip aliases. - $user->visible_bugs([grep /^[0-9]$/, @$ids]); - } - - my @last_visits = @{ $user->last_visited }; + $user->visible_bugs([grep /^[0-9]+$/, @$ids]); - if ($ids) { - # remove bugs that we are not interested in if ids is passed in. - my %id_set = map { ($_ => 1) } @$ids; - @last_visits = grep { $id_set{ $_->bug_id } } @last_visits; + my %last_visit = map { $_->bug_id => $_->last_visit_ts } @{ $user->last_visited($ids) }; + @last_visits = map { $self->_bug_user_last_visit_to_hash($_->id, $last_visit{$_}, $params) } @$ids; + } + else { + @last_visits = map { + $self->_bug_user_last_visit_to_hash($_->bug_id, $_->last_visit_ts, $params) + } @{ $user->last_visited }; } - return [ - map { - $self->_bug_user_last_visit_to_hash($_->bug_id, $_->last_visit_ts, - $params) - } @last_visits - ]; + return \@last_visits; } sub _bug_user_last_visit_to_hash { diff --git a/Bugzilla/WebService/FlagType.pm b/Bugzilla/WebService/FlagType.pm index 9723d4735..9d7cce037 100644 --- a/Bugzilla/WebService/FlagType.pm +++ b/Bugzilla/WebService/FlagType.pm @@ -61,11 +61,9 @@ sub get { sub create { my ($self, $params) = @_; + my $user = Bugzilla->login(LOGIN_REQUIRED); - my $dbh = Bugzilla->dbh; - my $user = Bugzilla->user; - - Bugzilla->user->in_group('editcomponents') + $user->in_group('editcomponents') || scalar(@{$user->get_products_by_permission('editcomponents')}) || ThrowUserError("auth_failure", { group => "editcomponents", action => "add", @@ -121,11 +119,9 @@ sub create { sub update { my ($self, $params) = @_; - my $dbh = Bugzilla->dbh; - my $user = Bugzilla->user; + my $user = Bugzilla->login(LOGIN_REQUIRED); - Bugzilla->login(LOGIN_REQUIRED); $user->in_group('editcomponents') || scalar(@{$user->get_products_by_permission('editcomponents')}) || ThrowUserError("auth_failure", { group => "editcomponents", diff --git a/Bugzilla/WebService/Product.pm b/Bugzilla/WebService/Product.pm index f38972bc1..94348a161 100644 --- a/Bugzilla/WebService/Product.pm +++ b/Bugzilla/WebService/Product.pm @@ -55,8 +55,6 @@ use constant FIELD_MAP => { # Add aliases here for method name compatibility # ################################################## -BEGIN { *get_products = \&get } - # Get the ids of the products the user can search sub get_selectable_products { Bugzilla->switch_to_shadow_db(); @@ -498,8 +496,6 @@ Returns a list of information about the products passed to it. B<Note>: You must at least specify one of C<ids> or C<names>. -B<Note>: Can also be called as "get_products" for compatibilty with Bugzilla 3.0 API. - =item B<REST> To return information about a specific groups of products such as @@ -992,11 +988,3 @@ You must define a default milestone. =back =back - -=head1 B<Methods in need of POD> - -=over - -=item get_products - -=back diff --git a/Bugzilla/WebService/Server/XMLRPC.pm b/Bugzilla/WebService/Server/XMLRPC.pm index 98a0ee405..8deb253ad 100644 --- a/Bugzilla/WebService/Server/XMLRPC.pm +++ b/Bugzilla/WebService/Server/XMLRPC.pm @@ -63,6 +63,12 @@ sub make_response { my $self = shift; my $cgi = Bugzilla->cgi; + # Fix various problems with IIS. + if ($ENV{'SERVER_SOFTWARE'} =~ /IIS/) { + $ENV{CONTENT_LENGTH} = 0; + binmode(STDOUT, ':bytes'); + } + $self->SUPER::make_response(@_); # XMLRPC::Transport::HTTP::CGI doesn't know about Bugzilla carrying around @@ -107,6 +113,8 @@ sub handle_login { if (none { $_ eq $method } $class->PUBLIC_METHODS) { ThrowCodeError('unknown_method', { method => $full_method }); } + + $ENV{CONTENT_LENGTH} = 0 if $ENV{'SERVER_SOFTWARE'} =~ /IIS/; $self->SUPER::handle_login($class, $method, $full_method); return; } diff --git a/Bugzilla/WebService/Util.pm b/Bugzilla/WebService/Util.pm index a0a51a8de..26a6ebbb0 100644 --- a/Bugzilla/WebService/Util.pm +++ b/Bugzilla/WebService/Util.pm @@ -219,7 +219,7 @@ sub validate { # sent any parameters at all, and we're getting @keys where # $params should be. return ($self, undef) if (defined $params and !ref $params); - + # If @keys is not empty then we convert any named # parameters that have scalar values to arrayrefs # that match. diff --git a/docs/en/rst/api/core/v1/comment.rst b/docs/en/rst/api/core/v1/comment.rst index 60fabb93b..946cf79fe 100644 --- a/docs/en/rst/api/core/v1/comment.rst +++ b/docs/en/rst/api/core/v1/comment.rst @@ -122,19 +122,14 @@ To create a comment on a current bug. .. code-block:: js { - "ids" : [123,..], "comment" : "This is an additional comment", "is_private" : false } -``ids`` is optional in the data example above and can be used to specify adding -a comment to more than one bug at the same time. - =========== ======= =========================================================== name type description =========== ======= =========================================================== **id** int The ID or alias of the bug to append a comment to. -ids array List of integer bug IDs to add the comment to. **comment** string The comment to append to the bug. If this is empty or all whitespace, an error will be thrown saying that you did not set the ``comment`` parameter. diff --git a/docs/en/rst/installing/apache-windows.rst b/docs/en/rst/installing/apache-windows.rst index 5e8ac8928..fca8ef5eb 100644 --- a/docs/en/rst/installing/apache-windows.rst +++ b/docs/en/rst/installing/apache-windows.rst @@ -3,29 +3,54 @@ Apache ###### -These instructions require editing the Apache configuration file, which is -at :file:`C:\\Program Files\\Apache Group\\Apache2\\conf\\httpd.conf`. +Bugzilla supports all versions of Apache 2.2.x and 2.4.x. Installing ========== -Download the Apache HTTP Server, version 2.2.x or higher, from -`the Apache website <http://httpd.apache.org/download.cgi>`_. +Download the Apache HTTP Server as a :file:`.zip` archive either from the +`Apache Lounge website <http://www.apachelounge.com/download>`_ or from the +`Apache Haus website <http://www.apachehaus.com/cgi-bin/download.plx>`_. -Apache uses a standard Windows installer. Just follow the prompts, making sure -you "Install for All Users". Be aware the Apache will always install itself -into an :file:`Apache2` directory under what ever path you specify. The -default install path will be displayed as -:file:`C:\\Program Files\\Apache Group`, which will result in Apache being -installed to :file:`C:\\Program Files\\Apache Group\\Apache2`. +Unzip the archive into :file:`C:\\Apache24`. If you move it elsewhere, then +you must edit several variables in :file:`httpd.conf`, including ``ServerRoot`` +and ``DocumentRoot``. -If you are already running IIS on your machine, you must configure Apache to -run on a port other than 80, which IIS is using. However you aren't asked the -port to listen on at install time. Choose "All Users" (which says port 80), -and we'll change the port later. +You must now edit the Apache configuration file :file:`C:\\Apache24\\conf\\httpd.conf` +and do the following steps: -The remainder of this document assumes you have installed Apache into -the default location, :file:`C:\\Program Files\\Apache Group\\Apache2`. +#. Uncomment ``LoadModule cgi_module modules/mod_cgi.so`` at the beginning of the + file to enable CGI support. +#. Uncomment ``AddHandler cgi-script .cgi`` to register :file:`.cgi` files + as CGI scripts. For this handler to work, you must create a key in the + Windows registry named ``HKEY_CLASSES_ROOT\.cgi\Shell\ExecCGI\Command`` with + the default value pointing to the full path of :file:`perl.exe` with a ``-T`` + parameter. For example :file:`C:\\Perl\\bin\\perl.exe -T` if you use ActivePerl, + or :file:`C:\\Strawberry\\perl\\bin\\perl.exe -T` if you use Strawberry Perl. +#. Add an Alias and a Directory for Bugzilla: + +.. code-block:: apache + + Alias "/bugzilla/" "C:/bugzilla/" + <Directory "C:/bugzilla"> + ScriptInterpreterSource Registry-Strict + Options +ExecCGI +FollowSymLinks + DirectoryIndex index.cgi index.html + AllowOverride All + Require all granted + </Directory> + +.. warning:: The above block takes a simple approach to access control and is + correct for Apache 2.4. For Apache 2.2, replace ``Require all granted`` + with ``Allow from all``. If you have other access control + requirements, you may need to make further modifications. + +You now save your changes and start Apache as a service. From the Windows +command line (:file:`cmd.exe`): + +:command:`C:\\Apache24\\bin>httpd.exe -k install` + +That's it! Bugzilla is now accessible from http://localhost/bugzilla. Apache Account Permissions ========================== @@ -40,58 +65,12 @@ and modify access to the following directories and all their subdirectories. Depending on your version of Windows, this access may already be granted. * :file:`C:\\Bugzilla\\data` -* :file:`C:\\Program Files\\Apache Group\\Apache2\\logs` -* :file:`C:\\Temp` +* :file:`C:\\Apache24\\logs` * :file:`C:\\Windows\\Temp` Note that :file:`C:\\Bugzilla\\data` is created the first time you run :file:`checksetup.pl`. -Port and DocumentRoot -===================== - -Edit the Apache configuration file (see above). - -If you need to change the port that Apache runs on (listens on, or binds to), -for example because another web server such as IIS is running on the same -machine, edit the ``Listen`` option and change the value after the colon. - -Change the ``DocumentRoot`` setting to point to :file:`C:/Bugzilla`. There -are two locations in :file:`httpd.conf` that need to be updated (search for -``DocumentRoot``). You need to use ``/`` instead of ``\`` as a path separator. - -Enable CGI Support -================== - -Edit the Apache configuration file (see above). - -To enable CGI support in Apache, you need to enable the CGI handler, by -uncommenting the ``AddHandler cgi-script .cgi`` line. - -Teach Apache About Bugzilla -=========================== - -Edit the Apache configuration file (see above). - -Add the following stanza: - -.. code-block:: apache - - <Directory "C:/Bugzilla"> - ScriptInterpreterSource Registry-Strict - Options +ExecCGI +FollowSymLinks - DirectoryIndex index.cgi index.html - AllowOverride Limit FileInfo Indexes Options - </Directory> - -In order for ``ScriptInterpreterSource Registry-Strict`` to work, you also -need to add an entry to the Registry so Apache will use Perl to execute .cgi -files. - -Create a key ``HKEY_CLASSES_ROOT\.cgi\Shell\ExecCGI\Command`` with the -default value of the full path of :file:`perl.exe` with a ``-T`` parameter. -For example :file:`C:\\Perl\\bin\\perl.exe -T`. - Logging ======= @@ -118,11 +97,40 @@ in its log files. (If you have configured Apache differently, a different log line might apply. Adjust these instructions accordingly.) +Using Apache with SSL +===================== + +If you want to enable SSL with Apache, i.e. access Bugzilla from +https://localhost/bugzilla, you need to do some extra steps: + +#. Edit :file:`C:\\Apache24\\conf\\httpd.conf` and uncomment these lines: + + * ``LoadModule ssl_module modules/mod_ssl.so`` + * ``LoadModule socache_shmcb_module modules/mod_socache_shmcb.so`` + * ``Include conf/extra/httpd-ssl.conf`` + +#. Create your :file:`.key` and :file:`.crt` files using :file:`openssl.exe` + provided with Apache: + + :command:`C:\\Apache24\\bin>openssl.exe req -x509 -nodes -days 730 -newkey rsa:2048 -keyout server.key -out server.crt` + + :file:`openssl.exe` will ask you a few questions about your location and + your company name to populate fields of the certificate. + +#. Once the key and the certificate for your server are generated, move them + into :file:`C:\\Apache24\\conf` so that their location matches the + ``SSLCertificateFile`` and ``SSLCertificateKeyFile`` variables defined in + :file:`C:\\Apache24\\conf\\extra\\httpd-ssl.conf` (which you don't need to + edit). + +.. note:: This process leads to a self-signed certificate which will generate + browser warnings on first visit. If your Bugzilla has a public DNS + name, you can get a cert from a CA which will not have this problem. + Restart Apache ============== -Finally, restart Apache to get it pick up the changes: - -:command:`net stop apache2` +Finally, restart Apache to pick up the changes, either from the Services +console or from the command line: -:command:`net start apache2` +:command:`C:\\Apache24\\bin>httpd.exe -k restart` diff --git a/docs/en/rst/installing/apache.rst b/docs/en/rst/installing/apache.rst index 856512a7f..f98d20df0 100644 --- a/docs/en/rst/installing/apache.rst +++ b/docs/en/rst/installing/apache.rst @@ -68,7 +68,7 @@ mod_cgi, do the following: AddHandler cgi-script .cgi Options +ExecCGI +FollowSymLinks DirectoryIndex index.cgi index.html - AllowOverride Limit FileInfo Indexes Options + AllowOverride All </Directory> These instructions allow Apache to run .cgi files found within the Bugzilla diff --git a/docs/en/rst/installing/essential-post-install-config.rst b/docs/en/rst/installing/essential-post-install-config.rst index c5e9c0bc1..1b9fd6b94 100644 --- a/docs/en/rst/installing/essential-post-install-config.rst +++ b/docs/en/rst/installing/essential-post-install-config.rst @@ -25,9 +25,9 @@ The first set of these are in the :guilabel:`Required Settings` section. this is the SSL URL by which people should access Bugzilla's front page. * :param:`ssl_redirect`: Set this if you want everyone to be redirected to use the SSL version. Recommended if you have set up SSL. -* :param:`cookiebase`: Bugzilla uses cookies to remember who each user is. +* :param:`cookiepath`: Bugzilla uses cookies to remember who each user is. In order to set those cookies in the correct scope, you may need to set a - cookiebase. If your Bugzilla is at the root of your domain, you don't need + cookiepath. If your Bugzilla is at the root of your domain, you don't need to change the default value. You may want to put your email address in the :param:`maintainer` diff --git a/docs/en/rst/installing/iis.rst b/docs/en/rst/installing/iis.rst index 6a1a7ab53..1670db5f5 100644 --- a/docs/en/rst/installing/iis.rst +++ b/docs/en/rst/installing/iis.rst @@ -91,6 +91,29 @@ From the top-level menu, which contains the name of your machine, click :command:`iisreset` +Enable Rewrite Rules for REST +============================= + +REST URLs are usually of the form http://.../bugzilla/rest/version instead of +http://.../bugzilla/rest.cgi/version. To let IIS redirect rest/ URLs to rest.cgi, +you need to download and install the +`URL Rewrite extension for IIS <http://www.iis.net/downloads/microsoft/url-rewrite>`_. +Direct download links are available at the bottom of the page for both x86 and +x64 Windows. + +Once installed, you open the IIS Manager again and go to your Bugzilla +Application. From here, double-click :guilabel:`URL Rewrite`. Then click +:guilabel:`Add Rule(s)` under the :guilabel:`Actions` menu and click +:guilabel:`Blank rule` in the :guilabel:`Inbound rules` section. + +Fill the fields as follows. Other fields do not need to be edited. + +* :guilabel:`Name`: ``REST`` +* :guilabel:`Pattern`: ``^rest/(.*)$`` +* :guilabel:`Rewrite URL`: ``rest.cgi/{R:1}`` + +There is no need to restart IIS. Changes take effect immediately. + Common Problems =============== @@ -104,6 +127,3 @@ Bugzilla runs but it's not possible to log in IIS returns HTTP 502 errors You probably forgot the ``-T`` argument to :file:`perl` when configuring the executable in IIS. - -XMLRPC interface not working with IIS - This is a known issue. See :bug:`708252`. diff --git a/docs/en/rst/installing/linux.rst b/docs/en/rst/installing/linux.rst index 0dad2056e..ff4258e6a 100644 --- a/docs/en/rst/installing/linux.rst +++ b/docs/en/rst/installing/linux.rst @@ -35,11 +35,9 @@ The following command will install Red Hat's packaged version of Bugzilla: :command:`yum install bugzilla httpd mysql-server` -However, if you go this route, you need to read :bug:`415605`, which details -some problems with the Email::Send package. Then, you can skip to -:ref:`configuring your database <linux-config-database>`. It may be useful to -know that Fedora stores the Bugzilla files in :file:`/usr/share/bugzilla`, so -that's where you'll run :file:`checksetup.pl`. +Then, you can skip to :ref:`configuring your database <linux-config-database>`. +It may be useful to know that Fedora stores the Bugzilla files in +:file:`/usr/share/bugzilla`, so that's where you'll run :file:`checksetup.pl`. If you want to install a version of Bugzilla from the Bugzilla project, you will instead need: diff --git a/docs/en/rst/installing/quick-start.rst b/docs/en/rst/installing/quick-start.rst index c9c7b2d26..c2da8da23 100644 --- a/docs/en/rst/installing/quick-start.rst +++ b/docs/en/rst/installing/quick-start.rst @@ -117,7 +117,7 @@ Paste in the following and save: AddHandler cgi-script .cgi Options +ExecCGI DirectoryIndex index.cgi index.html - AllowOverride Limit FileInfo Indexes Options + AllowOverride All </Directory> :command:`a2ensite bugzilla` diff --git a/docs/en/rst/installing/windows.rst b/docs/en/rst/installing/windows.rst index bf33ca330..ef1a1f6f4 100644 --- a/docs/en/rst/installing/windows.rst +++ b/docs/en/rst/installing/windows.rst @@ -3,28 +3,34 @@ Windows ####### -Making Bugzilla work on Windows is more difficult than making it work on Unix, -fewer Bugzilla developers use it and so it's less well supported. We would -particularly recommend against doing it for a large site. However, if -you are still determined to go ahead, here's how. +Making Bugzilla work on Windows is not more difficult than making it work on +Linux. However, fewer developers use Windows to test Bugzilla and so we would +still recommend using Linux for large sites to get better support. .. windows-install-perl: -ActiveState Perl -================ +Perl +==== -ActiveState make a popular distribution of Perl for Windows. +You have two main choices to install Perl on Windows: ActivePerl and Strawberry +Perl. -Download the ActiveState Perl 5.12.4 or higher MSI installer from the +The ActivePerl Windows Installer can be downloaded from the `ActiveState website <http://www.activestate.com/activeperl/downloads>`_. - -ActiveState Perl uses a standard Windows Installer. Install, sticking with -the defaults, which will install Perl into :file:`C:\\Perl`. It is not +Perl will be installed by default into :file:`C:\\Perl`. It is not recommended to install Perl into a directory containing a space, such as -:file:`C:\\Program Files`. +:file:`C:\\Program Files`. Once the install has completed, log out and log in +again to pick up the changes to the ``PATH`` environment variable. + +The Strawberry Perl Windows Installer can be downloaded from the +`Strawberry Perl website <http://strawberryperl.com>`_. Perl will be installed +by default into :file:`C:\\Strawberry`. -Once the install has completed, log out and log in again to pick up the -changes to the ``PATH`` environment variable. +One big advantage of Strawberry Perl over ActivePerl is that with Strawberry +Perl, you can use the usual tools available on other OSes to install missing +Perl modules directly from CPAN, whereas ActivePerl requires you to use its own +:file:`ppm` tool to download pre-compiled Perl modules from ActiveState. +The modules in the ActivePerl repository may be a bit older than those on CPAN. .. _windows-install-bzfiles: @@ -37,7 +43,7 @@ git from the `git website <http://git-scm.com/download>`_, and then run: :command:`git clone --branch release-X.X-stable https://git.mozilla.org/bugzilla/bugzilla C:\\bugzilla` where "X.X" is the 2-digit version number of the stable release of Bugzilla -that you want (e.g. 4.4). +that you want (e.g. 5.0). The rest of this documentation assumes you have installed Bugzilla into :file:`C:\\bugzilla`. Adjust paths appropriately if not. @@ -53,16 +59,17 @@ which any competent Windows archiving tool should be able to open. Perl Modules ============ -Bugzilla requires a number of perl modules to be installed. They are -available in the ActiveState repository, and are installed with the -:file:`ppm` tool. You can either use it on the command line, as below, -or just type :command:`ppm`, and you will get a GUI. +Bugzilla requires a number of Perl modules to be installed. Some of them are +mandatory, and some others, which enable additional features, are optional. +If you are using ActivePerl, these modules are available in the ActiveState +repository, and are installed with the :file:`ppm` tool. You can either use it +on the command line as below, or just type :command:`ppm`, and you will get a GUI. If you use a proxy server or a firewall you may have trouble running PPM. This is covered in the `ActivePerl FAQ <http://aspn.activestate.com/ASPN/docs/ActivePerl/faq/ActivePerl-faq2.html#ppm_and_proxies>`_. -Install the following modules with: +Install the following mandatory modules with: :command:`ppm install <modulename>` @@ -120,12 +127,15 @@ installed: * File-Copy-Recursive * GraphViz -.. warning:: These lists have been extracted from Bugzilla's source code and - have not been tested. Please let us know if you find errors in it - of any sort. +If you are using Strawberry Perl, you should use the :file:`install-module.pl` +script to install modules, which is the same script used for Linux. Some of +the required modules are already installed by default. The remaining ones can +be installed using the command: + +:command:`perl install-module.pl <modulename>` -.. note:: The :file:`install-module.pl` script doesn't work with ActivePerl - on Windows. +The list of modules to install will be displayed by :file:`checksetup.pl`; see +below. .. _windows-config-webserver: diff --git a/editgroups.cgi b/editgroups.cgi index 287ac1114..35989b954 100755 --- a/editgroups.cgi +++ b/editgroups.cgi @@ -194,15 +194,9 @@ if ($action eq 'new') { isactive => scalar $cgi->param('isactive'), icon_url => scalar $cgi->param('icon_url'), isbuggroup => 1, + use_in_all_products => scalar $cgi->param('insertnew'), }); - # Permit all existing products to use the new group if makeproductgroups. - if ($cgi->param('insertnew')) { - $dbh->do('INSERT INTO group_control_map - (group_id, product_id, membercontrol, othercontrol) - SELECT ?, products.id, ?, ? FROM products', - undef, ($group->id, CONTROLMAPSHOWN, CONTROLMAPNA)); - } delete_token($token); $vars->{'message'} = 'group_created'; diff --git a/mod_perl.pl b/mod_perl.pl index 5c5ed82ff..80dff2304 100644 --- a/mod_perl.pl +++ b/mod_perl.pl @@ -76,7 +76,7 @@ PerlChildInitHandler "sub { Bugzilla::RNG::srand(); srand(); }" PerlCleanupHandler Apache2::SizeLimit Bugzilla::ModPerl::CleanupHandler PerlOptions +ParseHeaders Options +ExecCGI - AllowOverride Limit FileInfo Indexes Options + AllowOverride All DirectoryIndex index.cgi index.html </Directory> EOT diff --git a/showdependencygraph.cgi b/showdependencygraph.cgi index e3e54c4d8..476df1e8e 100755 --- a/showdependencygraph.cgi +++ b/showdependencygraph.cgi @@ -61,7 +61,7 @@ sub CreateImagemap { # Pick up bugid from the mapdata label field. Getting the title from # bugtitle hash instead of mapdata allows us to get the summary even # when showsummary is off, and also gives us status and resolution. - my $bugtitle = html_quote(clean_text($bugtitles{$bugid})); + my $bugtitle = $bugtitles{$bugid}; $map .= qq{<area alt="bug $bugid" name="bug$bugid" shape="rect" } . qq{title="$bugtitle" href="$url" } . qq{coords="$leftx,$topy,$rightx,$bottomy">\n}; @@ -180,13 +180,16 @@ foreach my $k (@bug_ids) { # Retrieve bug information from the database my ($stat, $resolution, $summary) = $dbh->selectrow_array($sth, undef, $k); - # Resolution and summary are shown only if user can see the bug - if (!$user->can_see_bug($k)) { + $vars->{'short_desc'} = $summary if ($k eq $cgi->param('id')); + + # The bug summary is shown only if the user can see the bug. + if ($user->can_see_bug($k)) { + $summary = html_quote(clean_text($summary)); + } + else { $summary = ''; } - $vars->{'short_desc'} = $summary if ($k eq $cgi->param('id')); - my @params; if ($summary ne "" && $cgi->param('showsummary')) { diff --git a/skins/standard/global.css b/skins/standard/global.css index ab0fc8e30..fea45d1c6 100644 --- a/skins/standard/global.css +++ b/skins/standard/global.css @@ -659,7 +659,7 @@ input.required, select.required, span.required_explanation { list-style-type: none; } -.field_textarea_readonly { +pre.field_textarea_readonly { margin: 2px; padding: 4px; overflow: auto; @@ -667,9 +667,6 @@ input.required, select.required, span.required_explanation { max-width: 30em; max-height: 7em; border: 1px solid #CCC; -} - -.field_textarea_readonly pre { font-family: monospace; white-space: pre-wrap; } diff --git a/t/011pod.t b/t/011pod.t index cba9111d1..8a7f374ce 100644 --- a/t/011pod.t +++ b/t/011pod.t @@ -35,6 +35,7 @@ use constant SUB_WHITELIST => ( 'Bugzilla::JobQueue' => qr/(?:^work_once|work_until_done|subprocess_worker)$/, 'Bugzilla::Search' => qr/^SPECIAL_PARSING$/, 'Bugzilla::Template' => qr/^field_name$/, + 'Bugzilla::MIME' => qr/^as_string$/, ); # These modules do not need to be documented, generally because they diff --git a/template/en/default/admin/admin.html.tmpl b/template/en/default/admin/admin.html.tmpl index 7e3e5a157..ed41d7309 100644 --- a/template/en/default/admin/admin.html.tmpl +++ b/template/en/default/admin/admin.html.tmpl @@ -118,12 +118,6 @@ and time, and get the result of these queries directly per email. This is a good way to create reminders and to keep track of the activity in your installation.</dd> - [% IF Param('use_mailer_queue') %] - [% class = user.in_group('admin') ? "" : "forbidden" %] - <dt id="view_job_queue" class="[% class %]"><a href="view_job_queue.cgi">Job Queue</a></dt> - <dd class="[% class %]">View the queue of undelivered/deferred jobs/emails.</dd> - [% END %] - <dt id="release_notes"> <a href="page.cgi?id=release-notes.html">Release Notes</a></dt> <dd>Detailed information related to this release of Bugzilla.</dd> diff --git a/template/en/default/admin/groups/list.html.tmpl b/template/en/default/admin/groups/list.html.tmpl index 673c053cb..796872e1d 100644 --- a/template/en/default/admin/groups/list.html.tmpl +++ b/template/en/default/admin/groups/list.html.tmpl @@ -40,11 +40,11 @@ } {name => 'is_active_bug_group' heading => "Use For $terms.Bugs" - align => 'center' + class => 'center' } {name => 'type' heading => 'Type' - align => 'center' + class => 'center' } {name => 'action' heading => 'Action' diff --git a/template/en/default/admin/params/common.html.tmpl b/template/en/default/admin/params/common.html.tmpl index db3bde777..fd9fd3ed1 100644 --- a/template/en/default/admin/params/common.html.tmpl +++ b/template/en/default/admin/params/common.html.tmpl @@ -32,7 +32,7 @@ <label for="[% param.name FILTER html %]-off">Off</label> [% ELSIF param.type == "m" %] [% boxSize = 5 %] - [% boxSize = param.choices.size IF param.choices.size < 5 %] + [% SET boxSize = param.choices.size IF param.choices.size < 5 %] <select multiple="multiple" size="[% boxSize FILTER html %]" name="[% param.name FILTER html %]" id="[% param.name FILTER html %]"> @@ -48,7 +48,7 @@ name="[% param.name FILTER html %]" value="[% Param(param.name) FILTER html %]"><br> [% boxSize = 7 %] - [% boxSize = 3 + param.choices.size IF param.choices.size < 7 %] + [% SET boxSize = 3 + param.choices.size IF param.choices.size < 7 %] [% plist = Param(param.name).split(',') %] <table id="table_[% param.name FILTER html %]" class="bz_default_hidden"> diff --git a/template/en/default/admin/table.html.tmpl b/template/en/default/admin/table.html.tmpl index 993181c7f..2c8eb5fe0 100644 --- a/template/en/default/admin/table.html.tmpl +++ b/template/en/default/admin/table.html.tmpl @@ -69,7 +69,7 @@ <tr class="column_header"> [% FOREACH c = columns %] [%# Default to align left for headers %] - <th class="[% (c.align || 'left') FILTER css_class_quote %]"> + <th class="[% (c.class || 'left') FILTER css_class_quote %]"> [% c.heading FILTER html %] </th> [% END %] diff --git a/template/en/default/pages/release-notes.html.tmpl b/template/en/default/pages/release-notes.html.tmpl index e5ccf4d5a..5bd1608d9 100644 --- a/template/en/default/pages/release-notes.html.tmpl +++ b/template/en/default/pages/release-notes.html.tmpl @@ -43,6 +43,33 @@ <h2 id="point">Updates in this 5.0.x Release</h2> +<h3>5.0.2</h3> + +<p>This release fixes two security issues. See the + <a href="https://www.bugzilla.org/security/4.2.15/">Security Advisory</a> + for details.</p> + +<p>This release also contains the following [% terms.bug %] fixes:</p> + +<ul> + <li>mod_perl now works correctly with mod_access_compat turned off on + Apache 2.4. To regenerate the <kbd>.htaccess</kbd> files, you must first + delete all existing ones in subdirectories: + <pre>find . -mindepth 2 -name .htaccess -exec rm -f {} \;</pre> + You must then run <kbd>checksetup.pl</kbd> again to recreate them with + the correct syntax. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1223790">[% terms.Bug %] 1223790</a>)</li> + <li>Emails sent by [% terms.Bugzilla %] are now correctly encoded as UTF-8. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=714724">[% terms.Bug %] 714724</a>)</li> + <li>Strawberry Perl is now fully supported on Windows. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1089448">[% terms.Bug %] 1089448</a> + and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=987742">[% terms.bug %] 987742</a>)</li> + <li>The XML-RPC API now works with IIS on Windows. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=708252">[% terms.Bug %] 708252</a>)</li> + <li>Some queries should now be faster on PostgreSQL. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1184431">[% terms.Bug %] 1184431</a>)</li> +</ul> + <h3>5.0.1</h3> <p>This release fixes one security issue. See the @@ -67,8 +94,6 @@ <li>[% terms.Bugs %] containing a comment with a reference to a [% terms.bug %] ID larger than 2^31 could not be displayed anymore using PostgreSQL. (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1191937">[% terms.Bug %] 1191937</a>)</li> - <li>Emails sent by [% terms.Bugzilla %] are now correctly encoded as UTF-8. - (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=714724">[% terms.Bug %] 714724</a>)</li> <li>The date picker in the "Time Summary" page was broken. (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1181649">[% terms.Bug %] 1181649</a>)</li> <li>If <kbd>Test::Taint</kbd> or any other Perl module required to use the @@ -347,9 +372,10 @@ its members.</li> <li><kbd>FlagType.get</kbd> has been added to get information about valid flag types for a given product and component.</li> - <li>The deprecated <kbd>B[%%]ug.get_bugs</kbd> and <kbd>B[%%]ug.get_history</kbd> - methods are no longer supported. They have been renamed to <kbd>B[%%]ug.get</kbd> - and <kbd>B[%%]ug.history</kbd> respectively.</li> + <li>The deprecated <kbd>B[%%]ug.get_bugs</kbd>, <kbd>B[%%]ug.get_history</kbd> + and <kbd>Product.get_products</kbd> methods are no longer supported. + They have been renamed to <kbd>B[%%]ug.get</kbd>, <kbd>B[%%]ug.history</kbd> + and <kbd>Product.get</kbd> respectively.</li> </ul> <h2 id="code_changes">Code Changes Which May Affect Customizations and Extensions</h2> diff --git a/template/en/default/whine/multipart-mime.txt.tmpl b/template/en/default/whine/header.txt.tmpl index d28f4cea6..4067964f2 100644 --- a/template/en/default/whine/multipart-mime.txt.tmpl +++ b/template/en/default/whine/header.txt.tmpl @@ -8,10 +8,6 @@ [%# INTERFACE: # subject: subject line of message - # alternatives: array of hashes containing: - # type: MIME type - # content: verbatim content - # boundary: a string that has been generated to be a unique boundary # recipient: user object for the intended recipient of the message # from: Bugzilla system email address #%] @@ -19,21 +15,5 @@ From: [% from %] To: [% recipient.email %] Subject: [[% terms.Bugzilla %]] [% subject %] -MIME-Version: 1.0 -Content-Type: multipart/alternative; boundary="[% boundary %]" X-Bugzilla-Type: whine - -This is a MIME multipart message. It is possible that your mail program -doesn't quite handle these properly. Some or all of the information in this -message may be unreadable. - - -[% FOREACH part=alternatives %] - ---[% boundary %] -Content-type: [% part.type +%] - -[%+ part.content %] -[%+ END %] ---[% boundary %]-- @@ -346,53 +346,20 @@ while (my $event = get_next_event) { # - subject Subject line for the message # - recipient user object for the recipient # - author user object of the person who created the whine event -# -# In addition, mail adds two more fields to $args: -# - alternatives array of hashes defining mime multipart types and contents -# - boundary a MIME boundary generated using the process id and time -# sub mail { my $args = shift; - my $addressee = $args->{recipient}; # Don't send mail to someone whose bugmail notification is disabled. - return if $addressee->email_disabled; - - my $template = Bugzilla->template_inner($addressee->setting('lang')); - my $msg = ''; # it's a temporary variable to hold the template output - $args->{'alternatives'} ||= []; - - # put together the different multipart mime segments + return if $args->{recipient}->email_disabled; - $template->process("whine/mail.txt.tmpl", $args, \$msg) - or die($template->error()); - push @{$args->{'alternatives'}}, + $args->{to_user} = $args->{recipient}; + MessageToMTA(generate_email( + $args, { - 'content' => $msg, - 'type' => 'text/plain', - }; - $msg = ''; - - $template->process("whine/mail.html.tmpl", $args, \$msg) - or die($template->error()); - push @{$args->{'alternatives'}}, - { - 'content' => $msg, - 'type' => 'text/html', - }; - $msg = ''; - - # now produce a ready-to-mail mime-encoded message - - $args->{'boundary'} = "----------" . $$ . "--" . time() . "-----"; - - $template->process("whine/multipart-mime.txt.tmpl", $args, \$msg) - or die($template->error()); - - MessageToMTA($msg); - - delete $args->{'boundary'}; - delete $args->{'alternatives'}; - + header => 'whine/header.txt.tmpl', + text => 'whine/mail.txt.tmpl', + html => 'whine/mail.html.tmpl', + } + )); } # run_queries runs all of the queries associated with a schedule ID, adding |