From 246f6778660fe4a878b1f08eee175b1076c5e224 Mon Sep 17 00:00:00 2001 From: "lpsolit%gmail.com" <> Date: Tue, 18 Apr 2006 03:19:35 +0000 Subject: Bug 44595: Implement an interface for administrators to delete attachments - Patch by Frédéric Buclin r=wicked, justdave a=justdave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bugzilla/Attachment.pm | 12 +-- Bugzilla/Config/Attachment.pm | 5 ++ attachment.cgi | 83 ++++++++++++++++++++ .../en/default/admin/params/attachment.html.tmpl | 4 + .../en/default/attachment/confirm-delete.html.tmpl | 91 ++++++++++++++++++++++ .../en/default/attachment/delete_reason.txt.tmpl | 33 ++++++++ template/en/default/attachment/edit.html.tmpl | 16 +++- template/en/default/attachment/list.html.tmpl | 8 +- template/en/default/global/user-error.html.tmpl | 4 + 9 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 template/en/default/attachment/confirm-delete.html.tmpl create mode 100644 template/en/default/attachment/delete_reason.txt.tmpl diff --git a/Bugzilla/Attachment.pm b/Bugzilla/Attachment.pm index 350adfd72..00c7ee470 100644 --- a/Bugzilla/Attachment.pm +++ b/Bugzilla/Attachment.pm @@ -339,16 +339,16 @@ sub datasize { # If we have already retrieved the data, return its size. return length($self->{data}) if exists $self->{data}; - ($self->{datasize}) = + $self->{datasize} = Bugzilla->dbh->selectrow_array("SELECT LENGTH(thedata) FROM attach_data WHERE id = ?", - undef, - $self->{id}); + undef, $self->{id}) || 0; - # If there's no attachment data in the database, the attachment - # is stored in a local file, so retrieve its size from the file. - if ($self->{datasize} == 0) { + # If there's no attachment data in the database, either the attachment + # is stored in a local file, and so retrieve its size from the file, + # or the attachment has been deleted. + unless ($self->{datasize}) { if (open(AH, $self->_get_local_filename())) { binmode AH; $self->{datasize} = (stat(AH))[7]; diff --git a/Bugzilla/Config/Attachment.pm b/Bugzilla/Config/Attachment.pm index 449908528..bbaaaa63d 100644 --- a/Bugzilla/Config/Attachment.pm +++ b/Bugzilla/Config/Attachment.pm @@ -41,6 +41,11 @@ sub get_param_list { my $class = shift; my @param_list = ( { + name => 'allow_attachment_deletion', + type => 'b', + default => 0 + }, + { name => 'allow_attach_url', type => 'b', default => 0 diff --git a/attachment.cgi b/attachment.cgi index c212c6f36..fbe0bd054 100755 --- a/attachment.cgi +++ b/attachment.cgi @@ -49,6 +49,7 @@ use Bugzilla::Util; use Bugzilla::Bug; use Bugzilla::Field; use Bugzilla::Attachment; +use Bugzilla::Token; Bugzilla->login(); @@ -103,6 +104,9 @@ elsif ($action eq "update") Bugzilla->login(LOGIN_REQUIRED); update(); } +elsif ($action eq "delete") { + delete_attachment(); +} else { ThrowCodeError("unknown_action", { action => $action }); @@ -1329,3 +1333,82 @@ sub update $template->process("attachment/updated.html.tmpl", $vars) || ThrowTemplateError($template->error()); } + +# Only administrators can delete attachments. +sub delete_attachment { + my $user = Bugzilla->login(LOGIN_REQUIRED); + my $dbh = Bugzilla->dbh; + + print $cgi->header(); + + $user->in_group('admin') + || ThrowUserError('auth_failure', {group => 'admin', + action => 'delete', + object => 'attachment'}); + + Param('allow_attachment_deletion') + || ThrowUserError('attachment_deletion_disabled'); + + # Make sure the administrator is allowed to edit this attachment. + my ($attach_id, $bug_id) = validateID(); + validateCanEdit($attach_id); + validateCanChangeAttachment($attach_id); + + my $attachment = Bugzilla::Attachment->get($attach_id); + $attachment->datasize || ThrowUserError('attachment_removed'); + + # We don't want to let a malicious URL accidentally delete an attachment. + my $token = trim($cgi->param('token')); + if ($token) { + my ($creator_id, $date, $event) = Bugzilla::Token::GetTokenData($token); + unless ($creator_id + && ($creator_id == $user->id) + && ($event eq "attachment$attach_id")) + { + # The token is invalid. + ThrowUserError('token_inexistent'); + } + + # The token is valid. Delete the content of the attachment. + my $msg; + $vars->{'attachid'} = $attach_id; + $vars->{'bugid'} = $bug_id; + $vars->{'date'} = $date; + $vars->{'reason'} = clean_text($cgi->param('reason') || ''); + $vars->{'mailrecipients'} = { 'changer' => $user->login }; + + $template->process("attachment/delete_reason.txt.tmpl", $vars, \$msg) + || ThrowTemplateError($template->error()); + + $dbh->bz_lock_tables('attachments WRITE', 'attach_data WRITE', 'flags WRITE'); + $dbh->do('DELETE FROM attach_data WHERE id = ?', undef, $attach_id); + $dbh->do('UPDATE attachments SET mimetype = ?, ispatch = ?, isurl = ? + WHERE attach_id = ?', undef, ('text/plain', 0, 0, $attach_id)); + $dbh->do('DELETE FROM flags WHERE attach_id = ?', undef, $attach_id); + $dbh->bz_unlock_tables; + + # If the attachment is stored locally, remove it. + if (-e $attachment->_get_local_filename) { + unlink $attachment->_get_local_filename; + } + + # Now delete the token. + Bugzilla::Token::DeleteToken($token); + + # Paste the reason provided by the admin into a comment. + AppendComment($bug_id, $user->id, $msg); + + $template->process("attachment/updated.html.tmpl", $vars) + || ThrowTemplateError($template->error()); + } + else { + # Create a token. + $token = Bugzilla::Token::IssueSessionToken('attachment' . $attach_id); + + $vars->{'a'} = $attachment; + $vars->{'token'} = $token; + + $template->process("attachment/confirm-delete.html.tmpl", $vars) + || ThrowTemplateError($template->error()); + } +} diff --git a/template/en/default/admin/params/attachment.html.tmpl b/template/en/default/admin/params/attachment.html.tmpl index ef89c4af0..785d91822 100644 --- a/template/en/default/admin/params/attachment.html.tmpl +++ b/template/en/default/admin/params/attachment.html.tmpl @@ -25,9 +25,13 @@ %] [% param_descs = { + allow_attachment_deletion => "If this option is on, administrators will be able to delete " _ + "the content of attachments.", + allow_attach_url => "If this option is on, it will be possible to " _ "specify a URL when creating an attachment and " _ "treat the URL itself as if it were an attachment.", + maxpatchsize => "The maximum size (in kilobytes) of patches. $terms.Bugzilla will not " _ "accept patches greater than this number of kilobytes in size. " _ "To accept patches of any size (subject to the limitations of " _ diff --git a/template/en/default/attachment/confirm-delete.html.tmpl b/template/en/default/attachment/confirm-delete.html.tmpl new file mode 100644 index 000000000..99007e579 --- /dev/null +++ b/template/en/default/attachment/confirm-delete.html.tmpl @@ -0,0 +1,91 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Bug Tracking System. + # + # Contributor(s): Frédéric Buclin + #%] + +[%# INTERFACE: + # a: attachment object; attachment the user wants to delete. + # token: string; The token used to identify the session. + #%] + +[% PROCESS global/variables.none.tmpl %] + +[% title = BLOCK %] + Delete Attachment [% a.id FILTER html %] of + [%+ "$terms.Bug " _ a.bug_id FILTER bug_link(a.bug_id) FILTER none %] +[% END %] + +[% PROCESS global/header.html.tmpl title = title %] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldValue
Attachment ID: + [% a.id FILTER html %] +
File name:[% a.filename FILTER html %]
Description:[% a.description FILTER html %]
Contained in [% terms.Bug %]:[% a.bug_id FILTER bug_link(a.bug_id) FILTER none %]
Creator:[% a.attacher.identity FILTER html %]
Creation Date:[% a.attached FILTER time %]
+ +

Confirmation

+ + + + + +
+ The content of this attachment will be deleted in a irreversible way. +
+ +

Do you really want to delete this attachment?

+ +
+ + +

+ + + + +

+ +

+ No, cancel this deletion and return to + [%+ "$terms.bug " _ a.bug_id FILTER bug_link(a.bug_id) FILTER none %]. +

+ +[% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/attachment/delete_reason.txt.tmpl b/template/en/default/attachment/delete_reason.txt.tmpl new file mode 100644 index 000000000..45879f6ca --- /dev/null +++ b/template/en/default/attachment/delete_reason.txt.tmpl @@ -0,0 +1,33 @@ +[%# 1.0@bugzilla.org %] +[%# 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 Bug Tracking System. + # + # Contributor(s): Frédéric Buclin + #%] + +[%# INTERFACE: + # attachid: ID of the attachment the user wants to delete. + # reason: string; The reason provided by the user. + # date: the date when the request to delete the attachment was made. + #%] + +The content of attachment [% attachid %] has been deleted by + [%+ user.identity %] +[% IF reason %] +who provided the following reason: + +[%+ reason %] +[% ELSE %] +without providing any reason. +[% END %] + +The token used to delete this attachment was generated at [% date FILTER time %]. diff --git a/template/en/default/attachment/edit.html.tmpl b/template/en/default/attachment/edit.html.tmpl index b2b5b13e5..2f02aae34 100644 --- a/template/en/default/attachment/edit.html.tmpl +++ b/template/en/default/attachment/edit.html.tmpl @@ -229,7 +229,12 @@ Filename:

- Size: [% attachment.datasize FILTER unitconvert %]
+ Size: + [% IF attachment.datasize %] + [%+ attachment.datasize FILTER unitconvert %] + [% ELSE %] + deleted + [% END %]
MIME Type:
Diff [% END %] + [% IF Param("allow_attachment_deletion") + && user.groups.admin + && attachment.datasize > 0 %] + | Delete + [% END %] - [% IF isviewable %] + [% IF !attachment.datasize %] + The content of this attachment has been deleted. + [% ELSIF isviewable %] [% INCLUDE global/textarea.html.tmpl id = 'editFrame' diff --git a/template/en/default/attachment/list.html.tmpl b/template/en/default/attachment/list.html.tmpl index 03368ce26..0b42c0c3c 100644 --- a/template/en/default/attachment/list.html.tmpl +++ b/template/en/default/attachment/list.html.tmpl @@ -56,7 +56,13 @@ [% attachment.attached FILTER time %] - [% attachment.datasize FILTER unitconvert %] + + [% IF attachment.datasize %] + [% attachment.datasize FILTER unitconvert %] + [% ELSE %] + deleted + [% END %] + [% IF show_attachment_flags %] diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl index 54aa31ee0..c50955db8 100644 --- a/template/en/default/global/user-error.html.tmpl +++ b/template/en/default/global/user-error.html.tmpl @@ -194,6 +194,10 @@ versions [% END %]. + [% ELSIF error == "attachment_deletion_disabled" %] + [% title = "Attachment Deletion Disabled" %] + Attachment deletion is disabled on this installation. + [% ELSIF error == "attachment_removed" %] [% title = "Attachment Removed" %] The attachment you are attempting to access has been removed. -- cgit v1.2.3-24-g4f1b