aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Ruppert <idl0r@gentoo.org>2012-02-23 21:41:47 +0100
committerChristian Ruppert <idl0r@gentoo.org>2012-02-23 21:41:47 +0100
commit37a663a5b9827c6cd4ed2c26a61564ea98d078b4 (patch)
tree22071cc4a70210a1aa29a701c37b22293cfae283 /Bugzilla/Template.pm
parentBump to 4.0.4 (diff)
downloadbugzilla-37a663a5b9827c6cd4ed2c26a61564ea98d078b4.tar.gz
bugzilla-37a663a5b9827c6cd4ed2c26a61564ea98d078b4.tar.bz2
bugzilla-37a663a5b9827c6cd4ed2c26a61564ea98d078b4.zip
Update to 4.2.
Diffstat (limited to 'Bugzilla/Template.pm')
-rw-r--r--Bugzilla/Template.pm138
1 files changed, 81 insertions, 57 deletions
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index cc3d00613..527b704b2 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -61,6 +61,17 @@ use Scalar::Util qw(blessed);
use base qw(Template);
+use constant FORMAT_TRIPLE => '%19s|%-28s|%-28s';
+use constant FORMAT_3_SIZE => [19,28,28];
+use constant FORMAT_DOUBLE => '%19s %-55s';
+use constant FORMAT_2_SIZE => [19,55];
+
+# Pseudo-constant.
+sub SAFE_URL_REGEXP {
+ my $safe_protocols = join('|', SAFE_PROTOCOLS);
+ return qr/($safe_protocols):[^\s<>\"]+[\w\/]/i;
+}
+
# Convert the constants in the Bugzilla::Constants module into a hash we can
# pass to the template object for reflection into its "constants" namespace
# (which is like its "variables" namespace, but for constants). To do so, we
@@ -200,12 +211,8 @@ sub quoteUrls {
~egox;
# non-mailto protocols
- my $safe_protocols = join('|', SAFE_PROTOCOLS);
- my $protocol_re = qr/($safe_protocols)/i;
-
- $text =~ s~\b(${protocol_re}: # The protocol:
- [^\s<>\"]+ # Any non-whitespace
- [\w\/]) # so that we end in \w or /
+ my $safe_protocols = SAFE_URL_REGEXP();
+ $text =~ s~\b($safe_protocols)
~($tmp = html_quote($1)) &&
($things[$count++] = "<a href=\"$tmp\">$tmp</a>") &&
("\0\0" . ($count-1) . "\0\0")
@@ -315,44 +322,49 @@ sub get_attachment_link {
sub get_bug_link {
my ($bug, $link_text, $options) = @_;
+ $options ||= {};
my $dbh = Bugzilla->dbh;
- if (!$bug) {
- return html_quote('<missing bug number>');
+ if (defined $bug) {
+ $bug = blessed($bug) ? $bug : new Bugzilla::Bug($bug);
+ return $link_text if $bug->{error};
}
- $bug = blessed($bug) ? $bug : new Bugzilla::Bug($bug);
- return $link_text if $bug->{error};
-
- # Initialize these variables to be "" so that we don't get warnings
- # if we don't change them below (which is highly likely).
- my ($pre, $title, $post) = ("", "", "");
-
- $title = get_text('get_status', { status => $bug->bug_status });
- if ($bug->bug_status eq 'UNCONFIRMED') {
- $pre = "<i>";
- $post = "</i>";
- }
- if ($bug->resolution) {
- $pre .= '<span class="bz_closed">';
- $title .= ' ' . get_text('get_resolution',
- { resolution => $bug->resolution });
- $post .= '</span>';
- }
- if (Bugzilla->user->can_see_bug($bug)) {
- $title .= " - " . $bug->short_desc;
- if ($options->{use_alias} && $link_text =~ /^\d+$/ && $bug->alias) {
- $link_text = $bug->alias;
- }
+ my $template = Bugzilla->template_inner;
+ my $linkified;
+ $template->process('bug/link.html.tmpl',
+ { bug => $bug, link_text => $link_text, %$options }, \$linkified);
+ return $linkified;
+}
+
+# We use this instead of format because format doesn't deal well with
+# multi-byte languages.
+sub multiline_sprintf {
+ my ($format, $args, $sizes) = @_;
+ my @parts;
+ my @my_sizes = @$sizes; # Copy this so we don't modify the input array.
+ foreach my $string (@$args) {
+ my $size = shift @my_sizes;
+ my @pieces = split("\n", wrap_hard($string, $size));
+ push(@parts, \@pieces);
}
- # Prevent code injection in the title.
- $title = html_quote(clean_text($title));
- my $linkval = "show_bug.cgi?id=" . $bug->id;
- if (defined $options->{comment_num}) {
- $linkval .= "#c" . $options->{comment_num};
+ my $formatted;
+ while (1) {
+ # Get the first item of each part.
+ my @line = map { shift @$_ } @parts;
+ # If they're all undef, we're done.
+ last if !grep { defined $_ } @line;
+ # Make any single undef item into ''
+ @line = map { defined $_ ? $_ : '' } @line;
+ # And append a formatted line
+ $formatted .= sprintf($format, @line);
+ # Remove trailing spaces, or they become lots of =20's in
+ # quoted-printable emails.
+ $formatted =~ s/\s+$//;
+ $formatted .= "\n";
}
- return qq{$pre<a href="$linkval" title="$title">$link_text</a>$post};
+ return $formatted;
}
#####################
@@ -595,7 +607,7 @@ sub create {
ABSOLUTE => 1,
RELATIVE => $ENV{MOD_PERL} ? 0 : 1,
- COMPILE_DIR => bz_locations()->{'datadir'} . "/template",
+ COMPILE_DIR => bz_locations()->{'template_cache'},
# Initialize templates (f.e. by loading plugins like Hook).
PRE_PROCESS => ["global/initialize.none.tmpl"],
@@ -645,6 +657,7 @@ sub create {
$var =~ s/\r/\\r/g;
$var =~ s/\@/\\x40/g; # anti-spam for email addresses
$var =~ s/</\\x3c/g;
+ $var =~ s/>/\\x3e/g;
return $var;
},
@@ -678,12 +691,6 @@ sub create {
xml => \&Bugzilla::Util::xml_quote ,
- # This filter escapes characters in a variable or value string for
- # use in a query string. It escapes all characters NOT in the
- # regex set: [a-zA-Z0-9_\-.]. The 'uri' filter should be used for
- # a full URL that may have characters that need encoding.
- url_quote => \&Bugzilla::Util::url_quote ,
-
# This filter is similar to url_quote but used a \ instead of a %
# as prefix. In addition it replaces a ' ' by a '_'.
css_class_quote => \&Bugzilla::Util::css_class_quote ,
@@ -852,6 +859,14 @@ sub create {
# Function to create date strings
'time2str' => \&Date::Format::time2str,
+ # Fixed size column formatting for bugmail.
+ 'format_columns' => sub {
+ my $cols = shift;
+ my $format = ($cols == 3) ? FORMAT_TRIPLE : FORMAT_DOUBLE;
+ my $col_size = ($cols == 3) ? FORMAT_3_SIZE : FORMAT_2_SIZE;
+ return multiline_sprintf($format, \@_, $col_size);
+ },
+
# Generic linear search function
'lsearch' => sub {
my ($array, $item) = @_;
@@ -890,8 +905,8 @@ sub create {
my $url = shift;
return 0 unless $url;
- my $safe_protocols = join('|', SAFE_PROTOCOLS);
- return 1 if $url =~ /^($safe_protocols):[^\s<>\"]+[\w\/]$/i;
+ my $safe_url_regexp = SAFE_URL_REGEXP();
+ return 1 if $url =~ /^$safe_url_regexp$/;
# Pointing to a local file with no colon in its name is fine.
return 1 if $url =~ /^[^\s<>\":]+[\w\/]$/i;
# If we come here, then we cannot guarantee it's safe.
@@ -904,8 +919,8 @@ sub create {
# A way for all templates to get at Field data, cached.
'bug_fields' => sub {
my $cache = Bugzilla->request_cache;
- $cache->{template_bug_fields} ||=
- { map { $_->name => $_ } Bugzilla->get_fields() };
+ $cache->{template_bug_fields} ||=
+ Bugzilla->fields({ by_name => 1 });
return $cache->{template_bug_fields};
},
@@ -929,6 +944,10 @@ sub create {
# expensive, so we generate it once per-language.
'help_html' => sub { return template_var('help_html') },
+ # This way we don't have to load field-descs.none.tmpl in
+ # many templates.
+ 'display_value' => \&Bugzilla::Util::display_value,
+
'install_string' => \&Bugzilla::Install::Util::install_string,
'report_columns' => \&Bugzilla::Search::REPORT_COLUMNS,
@@ -948,6 +967,7 @@ sub create {
}
return \@optional;
},
+ 'default_authorizer' => new Bugzilla::Auth(),
},
};
@@ -970,23 +990,27 @@ sub precompile_templates {
my ($output) = @_;
# Remove the compiled templates.
+ my $cache_dir = bz_locations()->{'template_cache'};
my $datadir = bz_locations()->{'datadir'};
- if (-e "$datadir/template") {
+ if (-e $cache_dir) {
print install_string('template_removing_dir') . "\n" if $output;
# This frequently fails if the webserver made the files, because
# then the webserver owns the directories.
- rmtree("$datadir/template");
+ rmtree($cache_dir);
# Check that the directory was really removed, and if not, move it
# into data/deleteme/.
- if (-e "$datadir/template") {
+ if (-e $cache_dir) {
+ my $deleteme = "$datadir/deleteme";
+
print STDERR "\n\n",
install_string('template_removal_failed',
- { datadir => $datadir }), "\n\n";
- mkpath("$datadir/deleteme");
+ { deleteme => $deleteme,
+ template_cache => $cache_dir }), "\n\n";
+ mkpath($deleteme);
my $random = generate_random_password();
- rename("$datadir/template", "$datadir/deleteme/$random")
+ rename($cache_dir, "$deleteme/$random")
or die "move failed: $!";
}
}
@@ -1052,10 +1076,10 @@ sub _do_template_symlink {
my $abs_root = dirname($abs_path);
my $dir_name = basename($abs_path);
- my $datadir = bz_locations()->{'datadir'};
- my $container = "$datadir/template$abs_root";
+ my $cache_dir = bz_locations()->{'template_cache'};
+ my $container = "$cache_dir$abs_root";
mkpath($container);
- my $target = "$datadir/template/$dir_name";
+ my $target = "$cache_dir/$dir_name";
# Check if the directory exists, because if there are no extensions,
# there won't be an "data/template/extensions" directory to link to.
if (-d $target) {