aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin H. Johnson <robbat2@gentoo.org>2015-12-28 12:30:49 -0800
committerRobin H. Johnson <robbat2@gentoo.org>2015-12-28 12:30:56 -0800
commit18927a43465e7662b8558cf2d276d5f0bccd1e50 (patch)
tree0af3669d198ba4bd52eb2c6c8bdf0b33cb906e93
parentThere's currently no loadbalancing (diff)
parentBug 1235415: Use "AllowOverride All" everywhere (diff)
downloadbugzilla-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>
-rw-r--r--.htaccess7
-rw-r--r--Bugzilla.pm18
-rw-r--r--Bugzilla/BugMail.pm23
-rw-r--r--Bugzilla/Config.pm8
-rw-r--r--Bugzilla/Config/Common.pm5
-rw-r--r--Bugzilla/Constants.pm2
-rw-r--r--Bugzilla/DB.pm92
-rw-r--r--Bugzilla/DB/Pg.pm69
-rw-r--r--Bugzilla/Group.pm16
-rw-r--r--Bugzilla/Install/DB.pm27
-rw-r--r--Bugzilla/Install/Filesystem.pm59
-rw-r--r--Bugzilla/MIME.pm132
-rw-r--r--Bugzilla/Mailer.pm73
-rw-r--r--Bugzilla/Object.pm20
-rw-r--r--Bugzilla/Search.pm24
-rw-r--r--Bugzilla/Template.pm3
-rw-r--r--Bugzilla/User.pm5
-rw-r--r--Bugzilla/User/Setting.pm2
-rw-r--r--Bugzilla/WebService/BugUserLastVisit.pm28
-rw-r--r--Bugzilla/WebService/FlagType.pm10
-rw-r--r--Bugzilla/WebService/Product.pm12
-rw-r--r--Bugzilla/WebService/Server/XMLRPC.pm8
-rw-r--r--Bugzilla/WebService/Util.pm2
-rw-r--r--docs/en/rst/api/core/v1/comment.rst5
-rw-r--r--docs/en/rst/installing/apache-windows.rst142
-rw-r--r--docs/en/rst/installing/apache.rst2
-rw-r--r--docs/en/rst/installing/essential-post-install-config.rst4
-rw-r--r--docs/en/rst/installing/iis.rst26
-rw-r--r--docs/en/rst/installing/linux.rst8
-rw-r--r--docs/en/rst/installing/quick-start.rst2
-rw-r--r--docs/en/rst/installing/windows.rst60
-rwxr-xr-xeditgroups.cgi8
-rw-r--r--mod_perl.pl2
-rwxr-xr-xshowdependencygraph.cgi13
-rw-r--r--skins/standard/global.css5
-rw-r--r--t/011pod.t1
-rw-r--r--template/en/default/admin/admin.html.tmpl6
-rw-r--r--template/en/default/admin/groups/list.html.tmpl4
-rw-r--r--template/en/default/admin/params/common.html.tmpl4
-rw-r--r--template/en/default/admin/table.html.tmpl2
-rw-r--r--template/en/default/pages/release-notes.html.tmpl36
-rw-r--r--template/en/default/whine/header.txt.tmpl (renamed from template/en/default/whine/multipart-mime.txt.tmpl)20
-rwxr-xr-xwhine.pl51
43 files changed, 646 insertions, 400 deletions
diff --git a/.htaccess b/.htaccess
index e8bebeddc..6d47416c7 100644
--- a/.htaccess
+++ b/.htaccess
@@ -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 %]--
diff --git a/whine.pl b/whine.pl
index a7e3ee1cf..39c9aeed2 100755
--- a/whine.pl
+++ b/whine.pl
@@ -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