diff options
author | mkanat%bugzilla.org <> | 2009-09-30 23:42:49 +0000 |
---|---|---|
committer | mkanat%bugzilla.org <> | 2009-09-30 23:42:49 +0000 |
commit | aef9ce78eca5f7a0dae98d67af8fb72ebd1fafb7 (patch) | |
tree | f8104317e1417fe7544d682a1544802591046cfc | |
parent | 58787923c838e5a1fc90d3f98e27a443bb1e1122 (diff) | |
download | bugs-aef9ce78eca5f7a0dae98d67af8fb72ebd1fafb7.tar bugs-aef9ce78eca5f7a0dae98d67af8fb72ebd1fafb7.tar.gz bugs-aef9ce78eca5f7a0dae98d67af8fb72ebd1fafb7.tar.bz2 bugs-aef9ce78eca5f7a0dae98d67af8fb72ebd1fafb7.tar.xz bugs-aef9ce78eca5f7a0dae98d67af8fb72ebd1fafb7.zip |
Bug 364254: Add hook to Bugzilla::Template::quoteUrls
Patch by Max Kanat-Alexander <mkanat@bugzilla.org> r=dkl, a=mkanat
-rw-r--r-- | Bugzilla/Hook.pm | 65 | ||||
-rw-r--r-- | Bugzilla/Template.pm | 31 | ||||
-rw-r--r-- | extensions/example/code/bug-format_comment.pl | 45 | ||||
-rw-r--r-- | extensions/example/lib/Bugzilla/ExampleHook.pm | 43 | ||||
-rw-r--r-- | template/en/default/bug/comments.html.tmpl | 2 | ||||
-rw-r--r-- | template/en/default/bug/edit.html.tmpl | 2 |
6 files changed, 181 insertions, 7 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 +"&".) + +=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 diff --git a/extensions/example/code/bug-format_comment.pl b/extensions/example/code/bug-format_comment.pl new file mode 100644 index 000000000..c11e8cac2 --- /dev/null +++ b/extensions/example/code/bug-format_comment.pl @@ -0,0 +1,45 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Example Plugin. +# +# The Initial Developer of the Original Code is Canonical Ltd. +# Portions created by Canonical Ltd. are Copyright (C) 2009 +# Canonical Ltd. All Rights Reserved. +# +# Contributor(s): +# Max Kanat-Alexander <mkanat@bugzilla.org> + + +use strict; +use warnings; +use Bugzilla; +use Bugzilla::ExampleHook qw(replace_bar); + +# This replaces every occurrence of the word "foo" with the word +# "bar" + +my $regexes = Bugzilla->hook_args->{'regexes'}; +push(@$regexes, { match => qr/\bfoo\b/, replace => 'bar' }); + +# And this links every occurrence of the word "bar" to example.com, +# but it won't affect "foo"s that have already been turned into "bar" +# above (because each regex is run in order, and later regexes don't modify +# earlier matches, due to some cleverness in Bugzilla's internals). +# +# For example, the phrase "foo bar" would become: +# bar <a href="http://example.com/bar">bar</a> +# +# See lib/Bugzilla/ExampleHook.pm in this extension for the code of +# "replace_bar". +my $bar_match = qr/\b(bar)\b/; +push(@$regexes, { match => $bar_match, replace => \&replace_bar }); diff --git a/extensions/example/lib/Bugzilla/ExampleHook.pm b/extensions/example/lib/Bugzilla/ExampleHook.pm new file mode 100644 index 000000000..6452e8fef --- /dev/null +++ b/extensions/example/lib/Bugzilla/ExampleHook.pm @@ -0,0 +1,43 @@ +# -*- Mode: perl; indent-tabs-mode: nil -*- +# +# The contents of this file are subject to the Mozilla Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is the Bugzilla Example Plugin. +# +# The Initial Developer of the Original Code is Everything Solved, Inc. +# Portions created by the Initial Developer are Copyright (C) 2009 the +# Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Max Kanat-Alexander <mkanat@bugzilla.org> + +package Bugzilla::ExampleHook; +use strict; +use base qw(Exporter); +our @EXPORT_OK = qw( + replace_bar +); + +use Bugzilla::Util qw(html_quote); + +# Used by bug-format_comment--see its code for an explanation. +sub replace_bar { + my $params = shift; + # $match is the first parentheses match in the $bar_match regex + # in bug-format_comment.pl. We get up to 10 regex matches as + # arguments to this function. + my $match = $params->{matches}->[0]; + # Remember, you have to HTML-escape any data that you are returning! + $match = html_quote($match); + return qq{<a href="http://example.com/">$match</a>}; +}; + +1; diff --git a/template/en/default/bug/comments.html.tmpl b/template/en/default/bug/comments.html.tmpl index 177c6f985..2f9eeebf6 100644 --- a/template/en/default/bug/comments.html.tmpl +++ b/template/en/default/bug/comments.html.tmpl @@ -222,7 +222,7 @@ [% END %] <pre class="bz_comment_text" [% ' id="comment_text_' _ count _ '"' IF mode == "edit" %]> - [%- wrapped_comment FILTER quoteUrls(bug.bug_id, comment.already_wrapped) -%] + [%- wrapped_comment FILTER quoteUrls(bug, comment) -%] </pre> </div> [% END %] diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl index e050ee64c..d8a7fa4d7 100644 --- a/template/en/default/bug/edit.html.tmpl +++ b/template/en/default/bug/edit.html.tmpl @@ -312,7 +312,7 @@ (<span id="alias_nonedit_display">[% bug.alias FILTER html %]</span>) [% END %] [% END %] - <span id="short_desc_nonedit_display">[% bug.short_desc FILTER quoteUrls(bug.bug_id) %]</span> + <span id="short_desc_nonedit_display">[% bug.short_desc FILTER quoteUrls(bug) %]</span> [% IF bug.check_can_change_field('short_desc', 0, 1) || bug.check_can_change_field('alias', 0, 1) %] <small class="editme">(<a href="#" id="editme_action">edit</a>)</small> |