summaryrefslogtreecommitdiffstats
path: root/Bugzilla
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla')
-rw-r--r--Bugzilla/Hook.pm65
-rw-r--r--Bugzilla/Template.pm31
2 files changed, 91 insertions, 5 deletions
diff --git a/Bugzilla/Hook.pm b/Bugzilla/Hook.pm
index 42f3583c5..2cd99c3e7 100644
--- a/Bugzilla/Hook.pm
+++ b/Bugzilla/Hook.pm
@@ -313,6 +313,71 @@ your column name(s) onto the array.
=back
+=head2 bug-format_comment
+
+Allows you to do custom parsing on comments before they are displayed. You do
+this by returning two regular expressions: one that matches the section you
+want to replace, and then another that says what you want to replace that
+match with.
+
+The matching and replacement will be run with the C</g> switch on the regex.
+
+Params:
+
+=over
+
+=item C<regexes>
+
+An arrayref of hashrefs.
+
+You should push a hashref containing two keys (C<match> and C<replace>)
+in to this array. C<match> is the regular expression that matches the
+text you want to replace, C<replace> is what you want to replace that
+text with. (This gets passed into a regular expression like
+C<s/$match/$replace/>.)
+
+Instead of specifying a regular expression for C<replace> you can also
+return a coderef (a reference to a subroutine). If you want to use
+backreferences (using C<$1>, C<$2>, etc. in your C<replace>), you have to use
+this method--it won't work if you specify C<$1>, C<$2> in a regular expression
+for C<replace>. Your subroutine will get a hashref as its only argument. This
+hashref contains a single key, C<matches>. C<matches> is an arrayref that
+contains C<$1>, C<$2>, C<$3>, etc. in order, up to C<$10>. Your subroutine
+should return what you want to replace the full C<match> with. (See the code
+example for this hook if you want to see how this actually all works in code.
+It's simpler than it sounds.)
+
+B<You are responsible for HTML-escaping your returned data.> Failing to
+do so could open a security hole in Bugzilla.
+
+=item C<text>
+
+A B<reference> to the exact text that you are parsing.
+
+Generally you should not modify this yourself. Instead you should be
+returning regular expressions using the C<regexes> array.
+
+The text has already been word-wrapped, but has not been parsed in any way
+otherwise. (So, for example, it is not HTML-escaped. You get "&", not
+"&amp;".)
+
+=item C<bug>
+
+The L<Bugzilla::Bug> object that this comment is on. Sometimes this is
+C<undef>, meaning that we are parsing text that is not on a bug.
+
+=item C<comment>
+
+A hashref representing the comment you are about to parse, including
+all of the fields that comments contain when they are returned by
+by L<Bugzilla::Bug/longdescs>.
+
+Sometimes this is C<undef>, meaning that we are parsing text that is
+not a bug comment (but could still be some other part of a bug, like
+the summary line).
+
+=back
+
=head2 buglist-columns
This happens in buglist.cgi after the standard columns have been defined and
diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm
index bea1639f3..f94cb2e38 100644
--- a/Bugzilla/Template.pm
+++ b/Bugzilla/Template.pm
@@ -140,7 +140,7 @@ sub get_format {
# If you want to modify this routine, read the comments carefully
sub quoteUrls {
- my ($text, $curr_bugid, $already_wrapped) = (@_);
+ my ($text, $bug, $comment) = (@_);
return $text unless $text;
# We use /g for speed, but uris can have other things inside them
@@ -157,7 +157,8 @@ sub quoteUrls {
# If the comment is already wrapped, we should ignore newlines when
# looking for matching regexps. Else we should take them into account.
- my $s = $already_wrapped ? qr/\s/ : qr/[[:blank:]]/;
+ my $s = ($comment && $comment->{already_wrapped})
+ ? qr/\s/ : qr/[[:blank:]]/;
# However, note that adding the title (for buglinks) can affect things
# In particular, attachment matches go before bug titles, so that titles
@@ -172,6 +173,26 @@ sub quoteUrls {
my $count = 0;
my $tmp;
+ my @hook_regexes;
+ Bugzilla::Hook::process('bug-format_comment',
+ { text => \$text, bug => $bug, regexes => \@hook_regexes,
+ comment => $comment });
+
+ foreach my $re (@hook_regexes) {
+ my ($match, $replace) = @$re{qw(match replace)};
+ if (ref($replace) eq 'CODE') {
+ $text =~ s/$match/($things[$count++] = $replace->({matches => [
+ $1, $2, $3, $4,
+ $5, $6, $7, $8,
+ $9, $10]}))
+ && ("\0\0" . ($count-1) . "\0\0")/egx;
+ }
+ else {
+ $text =~ s/$match/($things[$count++] = $replace)
+ && ("\0\0" . ($count-1) . "\0\0")/egx;
+ }
+ }
+
# Provide tooltips for full bug links (Bug 74355)
my $urlbase_re = '(' . join('|',
map { qr/$_/ } grep($_, Bugzilla->params->{'urlbase'},
@@ -219,7 +240,7 @@ sub quoteUrls {
~egmxi;
# Current bug ID this comment belongs to
- my $current_bugurl = $curr_bugid ? "show_bug.cgi?id=$curr_bugid" : "";
+ my $current_bugurl = $bug ? ("show_bug.cgi?id=" . $bug->id) : "";
# This handles bug a, comment b type stuff. Because we're using /g
# we have to do this in one pattern, and so this is semi-messy.
@@ -541,10 +562,10 @@ sub create {
css_class_quote => \&Bugzilla::Util::css_class_quote ,
quoteUrls => [ sub {
- my ($context, $bug, $already_wrapped) = @_;
+ my ($context, $bug, $comment) = @_;
return sub {
my $text = shift;
- return quoteUrls($text, $bug, $already_wrapped);
+ return quoteUrls($text, $bug, $comment);
};
},
1