Index: Bugzilla/Template.pm =================================================================== RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Template.pm,v retrieving revision 1.73 diff -pU10 -r1.73 Bugzilla/Template.pm --- Bugzilla/Template.pm +++ Bugzilla/Template.pm @@ -219,25 +219,27 @@ sub quoteUrls { # Current bug ID this comment belongs to my $current_bugurl = $curr_bugid ? "show_bug.cgi?id=$curr_bugid" : ""; # 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. # Also, we can't use $bug_re?$comment_re? because that will match the # empty string my $bug_word = get_text('term', { term => 'bug' }); my $bug_re = qr/\Q$bug_word\E\s*\#?\s*(\d+)/i; my $comment_re = qr/comment\s*\#?\s*(\d+)/i; - $text =~ s~\b($bug_re(?:\s*,?\s*$comment_re)?|$comment_re) - ~ # We have several choices. $1 here is the link, and $2-4 are set + $text =~ s~\b(($bug_re)(?:(\s*,?\s*)($comment_re))?|$comment_re) + ~ # We have several choices. $1 here is the link, and $2-6 are set # depending on which part matched - (defined($2) ? get_bug_link($2,$1,$3) : - "$1") + (defined($3) ? + (defined($6) ? get_bug_comment_link($3,$6,$2,$4,$5) + : get_bug_link($3,$1,$4)) : + "$1") ~egox; # Old duplicate markers. These don't use $bug_word because they are old # and were never customizable. $text =~ s~(?<=^\*\*\*\ This\ bug\ has\ been\ marked\ as\ a\ duplicate\ of\ ) (\d+) (?=\ \*\*\*\Z) ~get_bug_link($1, $1) ~egmx; @@ -331,20 +333,72 @@ sub get_bug_link { my $linkval = "show_bug.cgi?id=$bug_num"; if (defined $comment_num) { $linkval .= "#c$comment_num"; } return qq{$pre$link_text$post}; } else { return qq{$link_text}; } +} + +# Creates a link to a comment, including its author and timestamp. +# It takes three parameters: +# - The bug number +# - The link text, to place between the .. +# - An comment number + +sub get_comment_link { + my ($bug_num, $link_text, $comment_num) = @_; + my $dbh = Bugzilla->dbh; + + if (!defined($bug_num) || ($bug_num eq "")) { + return "<missing bug number>"; + } + if (!defined($comment_num) || ($comment_num eq "")) { + return "<missing comment number>"; + } + my $quote_bug_num = html_quote($bug_num); + detaint_natural($bug_num) || return "<invalid bug number: $quote_bug_num>"; + my $quote_comment_num = html_quote($comment_num); + detaint_natural($coment_num) || return "<invalid comment number: $quote_comment_num>"; + + my ($bug_state, $bug_res, $bug_desc) = + $dbh->selectrow_array('SELECT bugs.bug_status, resolution, short_desc + FROM bugs WHERE bugs.bug_id = ?', + undef, $bug_num); + my ($commenter_id, $when, $isprivate) = + $dbg->selectrow_array('SELECT who, bug_when + FROM longdescs WHERE bug_id = ? AND comment_id = ?', + undef, $bug_num, $comment_num); + + # Initialize these variables to be "" so that we don't get warnings + # if we don't change them below (which is highly likely). + my $title = ""; + + if (!$isprivate || Bugzilla->user->in_group(Bugzilla->params->{'insidergroup'})) { + my $commenter = new Bugzilla::User($commenter_id); + + # Prevent code injection in the title. + $title = value_quote("by " . $commenter->identity . " on " . $date); + } + + my $linkval = "show_bug.cgi?id=$bug_num#c$comment_num"; + return qq{$link_text}; +} + +sub get_bug_comment_link { + my ($bug_num, $comment_num, $bug_text, $interim_text, $comment_text) = @_; + return get_bug_link($bug_num, $bug_text, $comment_num) + . $interim_text + . get_comment_link($bug_num, $comment_text, $comment_num); } ############################################################################### # Templatization Code # The Template Toolkit throws an error if a loop iterates >1000 times. # We want to raise that limit. # NOTE: If you change this number, you MUST RE-RUN checksetup.pl!!! # If you do not re-run checksetup.pl, the change you make will not apply $Template::Directive::WHILE_MAX = 1000000;