Commit 9c0a26d3 authored by gerv%gerv.net's avatar gerv%gerv.net

Bug 143286 - Add support for Insiders, Private comments, Private Attachments.…

Bug 143286 - Add support for Insiders, Private comments, Private Attachments. Patch by bugreport@peshkin.net; r=gerv.
parent e6fff23f
...@@ -49,7 +49,7 @@ sub query ...@@ -49,7 +49,7 @@ sub query
# of hashes in which each hash represents a single attachment. # of hashes in which each hash represents a single attachment.
&::SendSQL(" &::SendSQL("
SELECT attach_id, creation_ts, mimetype, description, ispatch, SELECT attach_id, creation_ts, mimetype, description, ispatch,
isobsolete, submitter_id isobsolete, isprivate, submitter_id
FROM attachments WHERE bug_id = $bugid ORDER BY attach_id FROM attachments WHERE bug_id = $bugid ORDER BY attach_id
"); ");
my @attachments = (); my @attachments = ();
...@@ -57,7 +57,8 @@ sub query ...@@ -57,7 +57,8 @@ sub query
my %a; my %a;
my $submitter_id; my $submitter_id;
($a{'attachid'}, $a{'date'}, $a{'contenttype'}, $a{'description'}, ($a{'attachid'}, $a{'date'}, $a{'contenttype'}, $a{'description'},
$a{'ispatch'}, $a{'isobsolete'}, $submitter_id) = &::FetchSQLData(); $a{'ispatch'}, $a{'isobsolete'}, $a{'isprivate'}, $submitter_id)
= &::FetchSQLData();
# Format the attachment's creation/modification date into a standard # Format the attachment's creation/modification date into a standard
# format (YYYY-MM-DD HH:MM) # format (YYYY-MM-DD HH:MM)
......
...@@ -49,7 +49,7 @@ sub query ...@@ -49,7 +49,7 @@ sub query
# of hashes in which each hash represents a single attachment. # of hashes in which each hash represents a single attachment.
&::SendSQL(" &::SendSQL("
SELECT attach_id, creation_ts, mimetype, description, ispatch, SELECT attach_id, creation_ts, mimetype, description, ispatch,
isobsolete, submitter_id isobsolete, isprivate, submitter_id
FROM attachments WHERE bug_id = $bugid ORDER BY attach_id FROM attachments WHERE bug_id = $bugid ORDER BY attach_id
"); ");
my @attachments = (); my @attachments = ();
...@@ -57,7 +57,8 @@ sub query ...@@ -57,7 +57,8 @@ sub query
my %a; my %a;
my $submitter_id; my $submitter_id;
($a{'attachid'}, $a{'date'}, $a{'contenttype'}, $a{'description'}, ($a{'attachid'}, $a{'date'}, $a{'contenttype'}, $a{'description'},
$a{'ispatch'}, $a{'isobsolete'}, $submitter_id) = &::FetchSQLData(); $a{'ispatch'}, $a{'isobsolete'}, $a{'isprivate'}, $submitter_id)
= &::FetchSQLData();
# Format the attachment's creation/modification date into a standard # Format the attachment's creation/modification date into a standard
# format (YYYY-MM-DD HH:MM) # format (YYYY-MM-DD HH:MM)
......
...@@ -312,6 +312,9 @@ sub init { ...@@ -312,6 +312,9 @@ sub init {
"^long_?desc," => sub { "^long_?desc," => sub {
my $table = "longdescs_$chartid"; my $table = "longdescs_$chartid";
push(@supptables, "longdescs $table"); push(@supptables, "longdescs $table");
if (Param("insidergroup") && !UserInGroup(Param("insidergroup"))) {
push(@wherepart, "$table.isprivate < 1") ;
}
push(@wherepart, "$table.bug_id = bugs.bug_id"); push(@wherepart, "$table.bug_id = bugs.bug_id");
$f = "$table.thetext"; $f = "$table.thetext";
}, },
......
...@@ -937,7 +937,7 @@ sub CheckIfVotedConfirmed { ...@@ -937,7 +937,7 @@ sub CheckIfVotedConfirmed {
} }
AppendComment($id, DBID_to_name($who), AppendComment($id, DBID_to_name($who),
"*** This bug has been confirmed by popular vote. ***"); "*** This bug has been confirmed by popular vote. ***", 0);
$vars->{'type'} = "votes"; $vars->{'type'} = "votes";
$vars->{'id'} = $id; $vars->{'id'} = $id;
......
...@@ -109,6 +109,7 @@ elsif ($action eq "update") ...@@ -109,6 +109,7 @@ elsif ($action eq "update")
validateIsPatch(); validateIsPatch();
validateContentType() unless $::FORM{'ispatch'}; validateContentType() unless $::FORM{'ispatch'};
validateIsObsolete(); validateIsObsolete();
validatePrivate();
validateStatuses(); validateStatuses();
update(); update();
} }
...@@ -125,22 +126,25 @@ exit; ...@@ -125,22 +126,25 @@ exit;
sub validateID sub validateID
{ {
# Validate the value of the "id" form field, which must contain an # Validate the value of the "id" form field, which must contain an
# integer that is the ID of an existing attachment. # integer that is the ID of an existing attachment.
detaint_natural($::FORM{'id'}) detaint_natural($::FORM{'id'})
|| DisplayError("You did not enter a valid attachment number.") || DisplayError("You did not enter a valid attachment number.")
&& exit; && exit;
# Make sure the attachment exists in the database. # Make sure the attachment exists in the database.
SendSQL("SELECT bug_id FROM attachments WHERE attach_id = $::FORM{'id'}"); SendSQL("SELECT bug_id, isprivate FROM attachments WHERE attach_id = $::FORM{'id'}");
MoreSQLData() MoreSQLData()
|| DisplayError("Attachment #$::FORM{'id'} does not exist.") || DisplayError("Attachment #$::FORM{'id'} does not exist.")
&& exit; && exit;
# Make sure the user is authorized to access this attachment's bug. # Make sure the user is authorized to access this attachment's bug.
my ($bugid) = FetchSQLData(); my ($bugid, $isprivate) = FetchSQLData();
ValidateBugID($bugid); ValidateBugID($bugid);
if (($isprivate > 0 ) && Param("insidergroup") && !(UserInGroup(Param("insidergroup")))) {
ThrowUserError("You are not permitted access to this attachment.");
}
} }
sub validateCanEdit sub validateCanEdit
...@@ -244,6 +248,14 @@ sub validateIsObsolete ...@@ -244,6 +248,14 @@ sub validateIsObsolete
$::FORM{'isobsolete'} = $::FORM{'isobsolete'} ? 1 : 0; $::FORM{'isobsolete'} = $::FORM{'isobsolete'} ? 1 : 0;
} }
sub validatePrivate
{
# Set the isprivate flag to zero if it is undefined, since the UI uses
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# do not get sent in HTML requests.
$::FORM{'isprivate'} = $::FORM{'isprivate'} ? 1 : 0;
}
sub validateStatuses sub validateStatuses
{ {
# Get a list of attachment statuses that are valid for this attachment. # Get a list of attachment statuses that are valid for this attachment.
...@@ -354,16 +366,16 @@ sub validateObsolete ...@@ -354,16 +366,16 @@ sub validateObsolete
sub view sub view
{ {
# Display an attachment. # Display an attachment.
# Retrieve the attachment content and its content type from the database. # Retrieve the attachment content and its content type from the database.
SendSQL("SELECT mimetype, thedata FROM attachments WHERE attach_id = $::FORM{'id'}"); SendSQL("SELECT mimetype, thedata FROM attachments WHERE attach_id = $::FORM{'id'}");
my ($contenttype, $thedata) = FetchSQLData(); my ($contenttype, $thedata) = FetchSQLData();
# Return the appropriate HTTP response headers. # Return the appropriate HTTP response headers.
print "Content-Type: $contenttype\n\n"; print "Content-Type: $contenttype\n\n";
print $thedata; print $thedata;
} }
...@@ -373,14 +385,20 @@ sub viewall ...@@ -373,14 +385,20 @@ sub viewall
# Retrieve the attachments from the database and write them into an array # Retrieve the attachments from the database and write them into an array
# of hashes where each hash represents one attachment. # of hashes where each hash represents one attachment.
SendSQL("SELECT attach_id, creation_ts, mimetype, description, ispatch, isobsolete my $privacy = "";
FROM attachments WHERE bug_id = $::FORM{'bugid'} ORDER BY attach_id"); if (Param("insidergroup") && !(UserInGroup(Param("insidergroup")))) {
$privacy = "AND isprivate < 1 ";
}
SendSQL("SELECT attach_id, creation_ts, mimetype, description,
ispatch, isobsolete, isprivate
FROM attachments WHERE bug_id = $::FORM{'bugid'} $privacy
ORDER BY attach_id");
my @attachments; # the attachments array my @attachments; # the attachments array
while (MoreSQLData()) while (MoreSQLData())
{ {
my %a; # the attachment hash my %a; # the attachment hash
($a{'attachid'}, $a{'date'}, $a{'contenttype'}, ($a{'attachid'}, $a{'date'}, $a{'contenttype'},
$a{'description'}, $a{'ispatch'}, $a{'isobsolete'}) = FetchSQLData(); $a{'description'}, $a{'ispatch'}, $a{'isobsolete'}, $a{'isprivate'}) = FetchSQLData();
# Flag attachments as to whether or not they can be viewed (as opposed to # Flag attachments as to whether or not they can be viewed (as opposed to
# being downloaded). Currently I decide they are viewable if their MIME type # being downloaded). Currently I decide they are viewable if their MIME type
...@@ -432,7 +450,7 @@ sub enter ...@@ -432,7 +450,7 @@ sub enter
if (!UserInGroup("editbugs")) { if (!UserInGroup("editbugs")) {
$canEdit = "AND submitter_id = $::userid"; $canEdit = "AND submitter_id = $::userid";
} }
SendSQL("SELECT attach_id, description SendSQL("SELECT attach_id, description, isprivate
FROM attachments FROM attachments
WHERE bug_id = $::FORM{'bugid'} WHERE bug_id = $::FORM{'bugid'}
AND isobsolete = 0 $canEdit AND isobsolete = 0 $canEdit
...@@ -440,7 +458,7 @@ sub enter ...@@ -440,7 +458,7 @@ sub enter
my @attachments; # the attachments array my @attachments; # the attachments array
while ( MoreSQLData() ) { while ( MoreSQLData() ) {
my %a; # the attachment hash my %a; # the attachment hash
($a{'id'}, $a{'description'}) = FetchSQLData(); ($a{'id'}, $a{'description'}, $a{'isprivate'}) = FetchSQLData();
# Add the hash representing the attachment to the array of attachments. # Add the hash representing the attachment to the array of attachments.
push @attachments, \%a; push @attachments, \%a;
...@@ -473,10 +491,11 @@ sub insert ...@@ -473,10 +491,11 @@ sub insert
my $description = SqlQuote($::FORM{'description'}); my $description = SqlQuote($::FORM{'description'});
my $contenttype = SqlQuote($::FORM{'contenttype'}); my $contenttype = SqlQuote($::FORM{'contenttype'});
my $thedata = SqlQuote($::FORM{'data'}); my $thedata = SqlQuote($::FORM{'data'});
my $isprivate = $::FORM{'isprivate'} ? 1 : 0;
# Insert the attachment into the database. # Insert the attachment into the database.
SendSQL("INSERT INTO attachments (bug_id, creation_ts, filename, description, mimetype, ispatch, submitter_id, thedata) SendSQL("INSERT INTO attachments (bug_id, creation_ts, filename, description, mimetype, ispatch, isprivate, submitter_id, thedata)
VALUES ($::FORM{'bugid'}, now(), $filename, $description, $contenttype, $::FORM{'ispatch'}, $::userid, $thedata)"); VALUES ($::FORM{'bugid'}, now(), $filename, $description, $contenttype, $::FORM{'ispatch'}, $isprivate, $::userid, $thedata)");
# Retrieve the ID of the newly created attachment record. # Retrieve the ID of the newly created attachment record.
SendSQL("SELECT LAST_INSERT_ID()"); SendSQL("SELECT LAST_INSERT_ID()");
...@@ -493,14 +512,15 @@ sub insert ...@@ -493,14 +512,15 @@ sub insert
AppendComment($::FORM{'bugid'}, AppendComment($::FORM{'bugid'},
$::COOKIE{"Bugzilla_login"}, $::COOKIE{"Bugzilla_login"},
$comment); $comment,
$isprivate);
# Make existing attachments obsolete. # Make existing attachments obsolete.
my $fieldid = GetFieldID('attachments.isobsolete'); my $fieldid = GetFieldID('attachments.isobsolete');
foreach my $attachid (@{$::MFORM{'obsolete'}}) { foreach my $attachid (@{$::MFORM{'obsolete'}}) {
SendSQL("UPDATE attachments SET isobsolete = 1 WHERE attach_id = $attachid"); SendSQL("UPDATE attachments SET isobsolete = 1 WHERE attach_id = $attachid");
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added) SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($::FORM{'bugid'}, $attachid, $::userid, NOW(), $fieldid, '0', '1')"); VALUES ($::FORM{'bugid'}, $attachid, $::userid, NOW(), $fieldid, '0', '1')");
} }
# Send mail to let people know the attachment has been created. Uses a # Send mail to let people know the attachment has been created. Uses a
...@@ -540,9 +560,9 @@ sub edit ...@@ -540,9 +560,9 @@ sub edit
# Users cannot edit the content of the attachment itself. # Users cannot edit the content of the attachment itself.
# Retrieve the attachment from the database. # Retrieve the attachment from the database.
SendSQL("SELECT description, mimetype, bug_id, ispatch, isobsolete SendSQL("SELECT description, mimetype, bug_id, ispatch, isobsolete, isprivate
FROM attachments WHERE attach_id = $::FORM{'id'}"); FROM attachments WHERE attach_id = $::FORM{'id'}");
my ($description, $contenttype, $bugid, $ispatch, $isobsolete) = FetchSQLData(); my ($description, $contenttype, $bugid, $ispatch, $isobsolete, $isprivate) = FetchSQLData();
# Flag attachment as to whether or not it can be viewed (as opposed to # Flag attachment as to whether or not it can be viewed (as opposed to
# being downloaded). Currently I decide it is viewable if its content # being downloaded). Currently I decide it is viewable if its content
...@@ -592,6 +612,7 @@ sub edit ...@@ -592,6 +612,7 @@ sub edit
$vars->{'bugsummary'} = $bugsummary; $vars->{'bugsummary'} = $bugsummary;
$vars->{'ispatch'} = $ispatch; $vars->{'ispatch'} = $ispatch;
$vars->{'isobsolete'} = $isobsolete; $vars->{'isobsolete'} = $isobsolete;
$vars->{'isprivate'} = $isprivate;
$vars->{'isviewable'} = $isviewable; $vars->{'isviewable'} = $isviewable;
$vars->{'statuses'} = \%statuses; $vars->{'statuses'} = \%statuses;
$vars->{'statusdefs'} = \@statusdefs; $vars->{'statusdefs'} = \@statusdefs;
...@@ -619,12 +640,12 @@ sub update ...@@ -619,12 +640,12 @@ sub update
# Lock database tables in preparation for updating the attachment. # Lock database tables in preparation for updating the attachment.
SendSQL("LOCK TABLES attachments WRITE , attachstatuses WRITE , SendSQL("LOCK TABLES attachments WRITE , attachstatuses WRITE ,
attachstatusdefs READ , fielddefs READ , bugs_activity WRITE"); attachstatusdefs READ , fielddefs READ , bugs_activity WRITE");
# Get a copy of the attachment record before we make changes # Get a copy of the attachment record before we make changes
# so we can record those changes in the activity table. # so we can record those changes in the activity table.
SendSQL("SELECT description, mimetype, ispatch, isobsolete SendSQL("SELECT description, mimetype, ispatch, isobsolete, isprivate
FROM attachments WHERE attach_id = $::FORM{'id'}"); FROM attachments WHERE attach_id = $::FORM{'id'}");
my ($olddescription, $oldcontenttype, $oldispatch, $oldisobsolete) = FetchSQLData(); my ($olddescription, $oldcontenttype, $oldispatch, $oldisobsolete,
$oldisprivate ) = FetchSQLData();
# Get the list of old status flags. # Get the list of old status flags.
SendSQL("SELECT attachstatusdefs.name SendSQL("SELECT attachstatusdefs.name
...@@ -672,6 +693,7 @@ sub update ...@@ -672,6 +693,7 @@ sub update
mimetype = $quotedcontenttype , mimetype = $quotedcontenttype ,
ispatch = $::FORM{'ispatch'} , ispatch = $::FORM{'ispatch'} ,
isobsolete = $::FORM{'isobsolete'} isobsolete = $::FORM{'isobsolete'}
isprivate = $::FORM{'isprivate'} ,
WHERE attach_id = $::FORM{'id'} WHERE attach_id = $::FORM{'id'}
"); ");
...@@ -698,6 +720,11 @@ sub update ...@@ -698,6 +720,11 @@ sub update
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added) SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $oldisobsolete, $::FORM{'isobsolete'})"); VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $oldisobsolete, $::FORM{'isobsolete'})");
} }
if ($oldisprivate ne $::FORM{'isprivate'}) {
my $fieldid = GetFieldID('attachments.isprivate');
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $oldisprivate, $::FORM{'isprivate'})");
}
if ($oldstatuslist ne $newstatuslist) { if ($oldstatuslist ne $newstatuslist) {
my ($removed, $added) = DiffStrings($oldstatuslist, $newstatuslist); my ($removed, $added) = DiffStrings($oldstatuslist, $newstatuslist);
my $quotedremoved = SqlQuote($removed); my $quotedremoved = SqlQuote($removed);
...@@ -759,7 +786,7 @@ sub update ...@@ -759,7 +786,7 @@ sub update
my $neverused = $::userid; my $neverused = $::userid;
# Append the comment to the list of comments in the database. # Append the comment to the list of comments in the database.
AppendComment($bugid, $who, $wrappedcomment); AppendComment($bugid, $who, $wrappedcomment, $::FORM{'isprivate'});
} }
......
...@@ -1316,6 +1316,7 @@ $table{attachments} = ...@@ -1316,6 +1316,7 @@ $table{attachments} =
thedata longblob not null, thedata longblob not null,
submitter_id mediumint not null, submitter_id mediumint not null,
isobsolete tinyint not null default 0, isobsolete tinyint not null default 0,
isprivate tinyint not null default 0,
index(bug_id), index(bug_id),
index(creation_ts)'; index(creation_ts)';
...@@ -1414,7 +1415,7 @@ $table{longdescs} = ...@@ -1414,7 +1415,7 @@ $table{longdescs} =
who mediumint not null, who mediumint not null,
bug_when datetime not null, bug_when datetime not null,
thetext mediumtext, thetext mediumtext,
isprivate tinyint not null default 0,
index(bug_id), index(bug_id),
index(who), index(who),
index(bug_when)'; index(bug_when)';
...@@ -1794,6 +1795,7 @@ AddFDef("attachments.thedata", "Attachment data", 0); ...@@ -1794,6 +1795,7 @@ AddFDef("attachments.thedata", "Attachment data", 0);
AddFDef("attachments.mimetype", "Attachment mime type", 0); AddFDef("attachments.mimetype", "Attachment mime type", 0);
AddFDef("attachments.ispatch", "Attachment is patch", 0); AddFDef("attachments.ispatch", "Attachment is patch", 0);
AddFDef("attachments.isobsolete", "Attachment is obsolete", 0); AddFDef("attachments.isobsolete", "Attachment is obsolete", 0);
AddFDef("attachments.isprivate", "Attachment is private", 0);
AddFDef("attachstatusdefs.name", "Attachment Status", 0); AddFDef("attachstatusdefs.name", "Attachment Status", 0);
AddFDef("target_milestone", "Target Milestone", 0); AddFDef("target_milestone", "Target Milestone", 0);
AddFDef("delta_ts", "Last changed date", 0); AddFDef("delta_ts", "Last changed date", 0);
...@@ -2503,6 +2505,12 @@ if (GetFieldDef('bugs_activity', 'field')) { ...@@ -2503,6 +2505,12 @@ if (GetFieldDef('bugs_activity', 'field')) {
DropField('bugs_activity', 'field'); DropField('bugs_activity', 'field');
} }
# 2002-05-10 - enhanchment bug 143826
# Add private comments and private attachments on less-private bugs
AddField('longdescs', 'isprivate', 'tinyint not null default 0');
AddField('attachments', 'isprivate', 'tinyint not null default 0');
# 2000-01-18 New email-notification scheme uses a new field in the bug to # 2000-01-18 New email-notification scheme uses a new field in the bug to
......
...@@ -717,4 +717,10 @@ DefParam("maxattachmentsize" , ...@@ -717,4 +717,10 @@ DefParam("maxattachmentsize" ,
"t" , "t" ,
'1000'); '1000');
DefParam("insidergroup",
"The name of the group of users who can see/change private comments
and attachments.",
"t",
'');
1; 1;
...@@ -323,7 +323,7 @@ sub FetchOneColumn { ...@@ -323,7 +323,7 @@ sub FetchOneColumn {
"status", "resolution", "summary"); "status", "resolution", "summary");
sub AppendComment { sub AppendComment {
my ($bugid,$who,$comment) = (@_); my ($bugid,$who,$comment,$isprivate) = (@_);
$comment =~ s/\r\n/\n/g; # Get rid of windows-style line endings. $comment =~ s/\r\n/\n/g; # Get rid of windows-style line endings.
$comment =~ s/\r/\n/g; # Get rid of mac-style line endings. $comment =~ s/\r/\n/g; # Get rid of mac-style line endings.
if ($comment =~ /^\s*$/) { # Nothin' but whitespace. if ($comment =~ /^\s*$/) { # Nothin' but whitespace.
...@@ -331,9 +331,10 @@ sub AppendComment { ...@@ -331,9 +331,10 @@ sub AppendComment {
} }
my $whoid = DBNameToIdAndCheck($who); my $whoid = DBNameToIdAndCheck($who);
my $privacyval = $isprivate ? 1 : 0 ;
SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) " . SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext, isprivate) " .
"VALUES($bugid, $whoid, now(), " . SqlQuote($comment) . ")"); "VALUES($bugid, $whoid, now(), " . SqlQuote($comment) . ", " .
$privacyval . ")");
SendSQL("UPDATE bugs SET delta_ts = now() WHERE bug_id = $bugid"); SendSQL("UPDATE bugs SET delta_ts = now() WHERE bug_id = $bugid");
} }
...@@ -1137,8 +1138,9 @@ sub GetLongDescriptionAsText { ...@@ -1137,8 +1138,9 @@ sub GetLongDescriptionAsText {
my ($id, $start, $end) = (@_); my ($id, $start, $end) = (@_);
my $result = ""; my $result = "";
my $count = 0; my $count = 0;
my $anyprivate = 0;
my ($query) = ("SELECT profiles.login_name, longdescs.bug_when, " . my ($query) = ("SELECT profiles.login_name, longdescs.bug_when, " .
" longdescs.thetext " . " longdescs.thetext, longdescs.isprivate " .
"FROM longdescs, profiles " . "FROM longdescs, profiles " .
"WHERE profiles.userid = longdescs.who " . "WHERE profiles.userid = longdescs.who " .
"AND longdescs.bug_id = $id "); "AND longdescs.bug_id = $id ");
...@@ -1156,25 +1158,29 @@ sub GetLongDescriptionAsText { ...@@ -1156,25 +1158,29 @@ sub GetLongDescriptionAsText {
$query .= "ORDER BY longdescs.bug_when"; $query .= "ORDER BY longdescs.bug_when";
SendSQL($query); SendSQL($query);
while (MoreSQLData()) { while (MoreSQLData()) {
my ($who, $when, $text) = (FetchSQLData()); my ($who, $when, $text, $isprivate) = (FetchSQLData());
if ($count) { if ($count) {
$result .= "\n\n------- Additional Comments From $who".Param('emailsuffix')." ". $result .= "\n\n------- Additional Comments From $who".Param('emailsuffix')." ".
time2str("%Y-%m-%d %H:%M", str2time($when)) . " -------\n"; time2str("%Y-%m-%d %H:%M", str2time($when)) . " -------\n";
} }
if (($isprivate > 0) && Param("insidergroup")) {
$anyprivate = 1;
}
$result .= $text; $result .= $text;
$count++; $count++;
} }
return $result; return ($result, $anyprivate);
} }
sub GetComments { sub GetComments {
my ($id) = (@_); my ($id) = (@_);
my @comments; my @comments;
SendSQL("SELECT profiles.realname, profiles.login_name, SendSQL("SELECT profiles.realname, profiles.login_name,
date_format(longdescs.bug_when,'%Y-%m-%d %H:%i'), date_format(longdescs.bug_when,'%Y-%m-%d %H:%i'),
longdescs.thetext longdescs.thetext,
isprivate,
date_format(longdescs.bug_when,'%Y%m%d%H%i%s')
FROM longdescs, profiles FROM longdescs, profiles
WHERE profiles.userid = longdescs.who WHERE profiles.userid = longdescs.who
AND longdescs.bug_id = $id AND longdescs.bug_id = $id
...@@ -1182,7 +1188,8 @@ sub GetComments { ...@@ -1182,7 +1188,8 @@ sub GetComments {
while (MoreSQLData()) { while (MoreSQLData()) {
my %comment; my %comment;
($comment{'name'}, $comment{'email'}, $comment{'time'}, $comment{'body'}) = FetchSQLData(); ($comment{'name'}, $comment{'email'}, $comment{'time'}, $comment{'body'},
$comment{'isprivate'}, $comment{'when'}) = FetchSQLData();
$comment{'email'} .= Param('emailsuffix'); $comment{'email'} .= Param('emailsuffix');
$comment{'name'} = $comment{'name'} || $comment{'email'}; $comment{'name'} = $comment{'name'} || $comment{'email'};
......
...@@ -630,6 +630,22 @@ if ( $::FORM{'id'} ) { ...@@ -630,6 +630,22 @@ if ( $::FORM{'id'} ) {
} }
} }
if ($::FORM{'id'} &&
(Param("insidergroup") && UserInGroup(Param("insidergroup")))) {
detaint_natural($::FORM{'id'});
foreach my $field (keys %::FORM) {
if ($field =~ /when-([0-9]+)/) {
my $sequence = $1;
my $private = $::FORM{"isprivate-$sequence"} ? 1 : 0 ;
if ($private != $::FORM{"oisprivate-$sequence"}) {
detaint_natural($::FORM{"$field"});
SendSQL("UPDATE longdescs SET isprivate = $private
WHERE bug_id = $::FORM{'id'} AND bug_when = " . $::FORM{"$field"});
}
}
}
}
my $duplicate = 0; my $duplicate = 0;
...@@ -1098,7 +1114,8 @@ foreach my $id (@idlist) { ...@@ -1098,7 +1114,8 @@ foreach my $id (@idlist) {
$timestamp = FetchOneColumn(); $timestamp = FetchOneColumn();
if (defined $::FORM{'comment'}) { if (defined $::FORM{'comment'}) {
AppendComment($id, $::COOKIE{'Bugzilla_login'}, $::FORM{'comment'}); AppendComment($id, $::COOKIE{'Bugzilla_login'}, $::FORM{'comment'},
$::FORM{'commentprivacy'});
} }
my $removedCcString = ""; my $removedCcString = "";
...@@ -1368,7 +1385,7 @@ foreach my $id (@idlist) { ...@@ -1368,7 +1385,7 @@ foreach my $id (@idlist) {
LogActivityEntry($duplicate,"cc","",DBID_to_name($reporter)); LogActivityEntry($duplicate,"cc","",DBID_to_name($reporter));
SendSQL("INSERT INTO cc (who, bug_id) VALUES ($reporter, " . SqlQuote($duplicate) . ")"); SendSQL("INSERT INTO cc (who, bug_id) VALUES ($reporter, " . SqlQuote($duplicate) . ")");
} }
AppendComment($duplicate, $::COOKIE{'Bugzilla_login'}, "*** Bug $::FORM{'id'} has been marked as a duplicate of this bug. ***"); AppendComment($duplicate, $::COOKIE{'Bugzilla_login'}, "*** Bug $::FORM{'id'} has been marked as a duplicate of this bug. ***", 1);
CheckFormFieldDefined(\%::FORM,'comment'); CheckFormFieldDefined(\%::FORM,'comment');
SendSQL("INSERT INTO duplicates VALUES ($duplicate, $::FORM{'id'})"); SendSQL("INSERT INTO duplicates VALUES ($duplicate, $::FORM{'id'})");
......
...@@ -225,7 +225,7 @@ sub ProcessOneBug { ...@@ -225,7 +225,7 @@ sub ProcessOneBug {
} }
my $newcomments = GetLongDescriptionAsText($id, $start, $end); my ($newcomments, $anyprivate) = GetLongDescriptionAsText($id, $start, $end);
# #
# Start of email filtering code # Start of email filtering code
...@@ -303,7 +303,8 @@ sub ProcessOneBug { ...@@ -303,7 +303,8 @@ sub ProcessOneBug {
\@reasons, \%values, \@reasons, \%values,
\%defmailhead, \%defmailhead,
\%fielddescription, $difftext, \%fielddescription, $difftext,
$newcomments, $start, $id, $newcomments, $anyprivate,
$start, $id,
\@depbugs))) \@depbugs)))
{ {
...@@ -612,9 +613,9 @@ sub filterEmailGroup ($$$) { ...@@ -612,9 +613,9 @@ sub filterEmailGroup ($$$) {
return @recipients; return @recipients;
} }
sub NewProcessOnePerson ($$$$$$$$$$$$) { sub NewProcessOnePerson ($$$$$$$$$$$$$) {
my ($person, $count, $hlRef, $reasonsRef, $valueRef, $dmhRef, $fdRef, $difftext, my ($person, $count, $hlRef, $reasonsRef, $valueRef, $dmhRef, $fdRef, $difftext,
$newcomments, $start, $id, $depbugsRef) = @_; $newcomments, $anyprivate, $start, $id, $depbugsRef) = @_;
my %values = %$valueRef; my %values = %$valueRef;
my @headerlist = @$hlRef; my @headerlist = @$hlRef;
...@@ -650,7 +651,19 @@ sub NewProcessOnePerson ($$$$$$$$$$$$) { ...@@ -650,7 +651,19 @@ sub NewProcessOnePerson ($$$$$$$$$$$$) {
# quietly disappear from their radar. # quietly disappear from their radar.
# #
return unless CanSeeBug($id, $userid, $groupset); return unless CanSeeBug($id, $userid, $groupset);
# Drop any non-insiders if the comment is private
if (Param("insidergroup") && ($anyprivate != 0)) {
ConnectToDatabase();
PushGlobalSQLState();
SendSQL("select (bit & $groupset ) != 0 from groups where name = " . SqlQuote(Param("insidergroup")));
my $bit = FetchOneColumn();
PopGlobalSQLState();
if (!$bit) {
return;
}
}
# We shouldn't send changedmail if this is a dependency mail, and any of # We shouldn't send changedmail if this is a dependency mail, and any of
# the depending bugs is not visible to the user. # the depending bugs is not visible to the user.
foreach my $dep_id (@depbugs) { foreach my $dep_id (@depbugs) {
......
...@@ -94,15 +94,28 @@ ...@@ -94,15 +94,28 @@
onchange="if (this.value) this.form.contenttypemethod[2].checked = true;"> onchange="if (this.value) this.form.contenttypemethod[2].checked = true;">
</td> </td>
</tr> </tr>
[% IF (Param("insidergroup") && UserInGroup(Param("insidergroup"))) %]
<tr>
<th>Privacy:</th>
<td>
<em>If the attachment is private, check the box below.</em><br>
<input type="checkbox" name="isprivate" id="isprivate" value="1">
<label for="isprivate">Private</label>
</td>
</tr>
[% END %]
<tr> <tr>
<th>Obsoletes:</th> <th>Obsoletes:</th>
<td> <td>
<em>(optional) Check each existing attachment made obsolete by your new attachment.</em><br> <em>(optional) Check each existing attachment made obsolete by your new attachment.</em><br>
[% IF attachments.size %] [% IF attachments.size %]
[% FOREACH attachment = attachments %] [% FOREACH attachment = attachments %]
<input type="checkbox" id="[% attachment.id %]" [% IF ((attachment.isprivate == 0) || (Param("insidergroup")
&& UserInGroup(Param("insidergroup")))) %]
<input type="checkbox" id="[% attachment.id %]"
name="obsolete" value="[% attachment.id %]"> name="obsolete" value="[% attachment.id %]">
<a href="attachment.cgi?id=[% attachment.id %]&amp;action=edit">[% attachment.id %]: [% attachment.description FILTER html %]</a><br> <a href="attachment.cgi?id=[% attachment.id %]&amp;action=edit">[% attachment.id %]: [% attachment.description FILTER html %]</a><br>
[% END %]
[% END %] [% END %]
[% ELSE %] [% ELSE %]
[no attachments can be made obsolete] [no attachments can be made obsolete]
......
...@@ -163,6 +163,9 @@ ...@@ -163,6 +163,9 @@
<input type="checkbox" id="isobsolete" name="isobsolete" value="1" <input type="checkbox" id="isobsolete" name="isobsolete" value="1"
[% 'checked="checked"' IF isobsolete %]> [% 'checked="checked"' IF isobsolete %]>
<label for="isobsolete">obsolete</label><br> <label for="isobsolete">obsolete</label><br>
[% IF (Param("insidergroup") && UserInGroup(Param("insidergroup"))) %]
<input type="checkbox" name="isprivate" value="1"[% " checked" IF isprivate %]> private<br><br>
[% END %]
[% IF statusdefs.size %] [% IF statusdefs.size %]
<b>Status:</b><br> <b>Status:</b><br>
......
...@@ -28,9 +28,10 @@ ...@@ -28,9 +28,10 @@
<th bgcolor="#cccccc" align="left">Status</th> <th bgcolor="#cccccc" align="left">Status</th>
<th bgcolor="#cccccc" align="left">Actions</th> <th bgcolor="#cccccc" align="left">Actions</th>
</tr> </tr>
[% canseeprivate = !Param("insidergroup") || UserInGroup(Param("insidergroup")) %]
[% FOREACH attachment = attachments %] [% FOREACH attachment = attachments %]
<tr> [% IF !attachment.isprivate || canseeprivate %]
<tr [% "class=\"bz_private\"" IF attachment.isprivate %]>
<td valign="top"> <td valign="top">
[% IF attachment.isobsolete %] [% IF attachment.isobsolete %]
<strike><a href="attachment.cgi?id=[% attachment.attachid %]&amp;action=view">[% attachment.description FILTER html %]</a></strike> <strike><a href="attachment.cgi?id=[% attachment.attachid %]&amp;action=view">[% attachment.description FILTER html %]</a></strike>
...@@ -67,6 +68,7 @@ ...@@ -67,6 +68,7 @@
[% END %] [% END %]
</td> </td>
</tr> </tr>
[% END %]
[% END %] [% END %]
<tr> <tr>
......
...@@ -19,8 +19,9 @@ ...@@ -19,8 +19,9 @@
# Contributor(s): Gervase Markham <gerv@gerv.net> # Contributor(s): Gervase Markham <gerv@gerv.net>
#%] #%]
[% DEFAULT start_at = 0 %] [% DEFAULT start_at = 0 mode = "show" %]
[% count = 0 %] [% count = 0 %]
[% isinsider = Param("insidergroup") && UserInGroup(Param("insidergroup")) %]
[% FOREACH comment = comments %] [% FOREACH comment = comments %]
[% IF count >= start_at %] [% IF count >= start_at %]
[% PROCESS a_comment %] [% PROCESS a_comment %]
...@@ -35,14 +36,25 @@ ...@@ -35,14 +36,25 @@
[%############################################################################%] [%############################################################################%]
[% BLOCK a_comment %] [% BLOCK a_comment %]
[% IF count > 0 %] [% IF NOT comment.isprivate || isinsider %]
<br> <div [% "class=\"bz_private\"" IF comment.isprivate %]>
<i>------- Additional Comment [% IF count > 0 %]
<a name="c[% count %]" href="#c[% count %]">#[% count %]</a> From <br>
<a href="mailto:[% comment.email FILTER html %]">[% comment.name FILTER html %]</a> <i>------- Additional Comment
[%+ comment.time %] ------- <a name="c[% count %]" href="#c[% count %]">#[% count %]</a> From
</i> <a href="mailto:[% comment.email FILTER html %]">[% comment.name FILTER html %]</a>
[% END %] [%+ comment.time %] -------
</i>
[% END %]
[% IF mode == "edit" && isinsider %]
<i>
<input type=hidden name="oisprivate-[% count %]"
value="[% comment.isprivate %]">
<input type=hidden name="when-[% count %]" value="[% comment.when %]">
<input type=checkbox name="isprivate-[% count %]" value="1"
[% " checked=\"checked\"" IF comment.isprivate %]> Private
</i>
[% END %]
[%# Don't indent the <pre> block, since then the spaces are displayed in the [%# Don't indent the <pre> block, since then the spaces are displayed in the
# generated HTML # generated HTML
...@@ -50,4 +62,6 @@ ...@@ -50,4 +62,6 @@
<pre> <pre>
[%- quoteUrls(comment.body) -%] [%- quoteUrls(comment.body) -%]
</pre> </pre>
</div>
[% END %]
[% END %] [% END %]
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
h2 = filtered_desc h2 = filtered_desc
h3 = "Last modified: $bug.calc_disp_date" h3 = "Last modified: $bug.calc_disp_date"
header_html = navigation_links header_html = navigation_links
style_urls = [ "css/edit_bug.css" ]
%] %]
[% END %] [% END %]
...@@ -310,6 +311,9 @@ ...@@ -310,6 +311,9 @@
<br> <br>
<b>Additional <u>C</u>omments:</b> <b>Additional <u>C</u>omments:</b>
[% IF Param("insidergroup") && UserInGroup(Param("insidergroup")) %]
<input type="checkbox" name="commentprivacy" value="1"> Private
[% END %]
<br> <br>
<textarea wrap="hard" name="comment" rows="10" cols="80" <textarea wrap="hard" name="comment" rows="10" cols="80"
accesskey="c"></textarea> accesskey="c"></textarea>
...@@ -482,7 +486,6 @@ ...@@ -482,7 +486,6 @@
value="[% Param("move-button-text") %]"> value="[% Param("move-button-text") %]">
[% END %] [% END %]
</p> </p>
</form>
[%# *** Additional Comments *** %] [%# *** Additional Comments *** %]
...@@ -502,8 +505,10 @@ ...@@ -502,8 +505,10 @@
[% PROCESS bug/comments.html.tmpl [% PROCESS bug/comments.html.tmpl
comments = bug.comments comments = bug.comments
mode = "edit"
%] %]
</form>
<hr> <hr>
[% PROCESS bug/navigate.html.tmpl %] [% PROCESS bug/navigate.html.tmpl %]
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
[% PROCESS global/header.html.tmpl [% PROCESS global/header.html.tmpl
title = "Full Text Bug Listing" title = "Full Text Bug Listing"
style_urls = [ "css/show_multiple.css" ]
%] %]
[% IF bugs.first %] [% IF bugs.first %]
[% FOREACH bug = bugs %] [% FOREACH bug = bugs %]
[% PROCESS bug_display %] [% PROCESS bug_display %]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment