isobsolete
ispatch
isprivate
- isurl
mimetype
modification_time
submitter_id),
use constant VALIDATORS => {
bug => \&_check_bug,
description => \&_check_description,
+ filename => \&_check_filename,
ispatch => \&Bugzilla::Object::check_boolean,
isprivate => \&_check_is_private,
- isurl => \&_check_is_url,
mimetype => \&_check_content_type,
};
use constant UPDATE_VALIDATORS => {
- filename => \&_check_filename,
isobsolete => \&Bugzilla::Object::check_boolean,
};
=over
-=item C<isurl>
-
-whether or not the attachment is a URL
-
-=back
-
-=cut
-
-sub isurl {
- my $self = shift;
- return $self->{isurl};
-}
-
-=over
-
=item C<isobsolete>
whether or not the attachment is obsolete
sub _check_content_type {
my ($invocant, $content_type) = @_;
- $content_type = 'text/plain' if (ref $invocant && ($invocant->isurl || $invocant->ispatch));
+ $content_type = 'text/plain' if (ref $invocant && $invocant->ispatch);
my $legal_types = join('|', LEGAL_CONTENT_TYPES);
if (!$content_type or $content_type !~ /^($legal_types)\/.+$/) {
ThrowUserError("invalid_content_type", { contenttype => $content_type });
my ($invocant, $params) = @_;
my $data = $params->{data};
- if ($params->{isurl}) {
- ($data && $data =~ m#^(http|https|ftp)://\S+#)
- || ThrowUserError('attachment_illegal_url', { url => $data });
+ $params->{filesize} = ref $data ? -s $data : length($data);
- $params->{mimetype} = 'text/plain';
- $params->{ispatch} = 0;
- $params->{filesize} = length($data);
- }
- else {
- $params->{filesize} = ref $data ? -s $data : length($data);
- }
Bugzilla::Hook::process('attachment_process_data', { data => \$data,
attributes => $params });
}
sub _check_filename {
- my ($invocant, $filename, $is_url) = @_;
-
- $is_url = $invocant->isurl if ref $invocant;
- # No file is attached, so it has no name.
- return '' if $is_url;
+ my ($invocant, $filename) = @_;
$filename = trim($filename);
$filename || ThrowUserError('file_not_specified');
return $is_private;
}
-sub _check_is_url {
- my ($invocant, $is_url) = @_;
-
- if ($is_url && !Bugzilla->params->{'allow_attach_url'}) {
- ThrowCodeError('attachment_url_disabled');
- }
- return $is_url ? 1 : 0;
-}
-
=pod
=head2 Class Methods
attachment is a patch.
C<isprivate> - boolean (optional, default false) - true if
the attachment is private.
- C<isurl> - boolean (optional, default false) - true if the
- attachment is a URL pointing to some external ressource.
Returns: The new attachment object.
$params->{data} = $class->_check_data($params);
$params = $class->SUPER::run_create_validators($params);
- $params->{filename} = $class->_check_filename($params->{filename}, $params->{isurl});
$params->{creation_ts} ||= Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
$params->{modification_time} = $params->{creation_ts};
$params->{submitter_id} = Bugzilla->user->id || ThrowCodeError('invalid_user');
$dbh->bz_start_transaction();
$dbh->do('DELETE FROM flags WHERE attach_id = ?', undef, $self->id);
$dbh->do('DELETE FROM attach_data WHERE id = ?', undef, $self->id);
- $dbh->do('UPDATE attachments SET mimetype = ?, ispatch = ?, isurl = ?, isobsolete = ?
- WHERE attach_id = ?', undef, ('text/plain', 0, 0, 1, $self->id));
+ $dbh->do('UPDATE attachments SET mimetype = ?, ispatch = ?, isobsolete = ?
+ WHERE attach_id = ?', undef, ('text/plain', 0, 1, $self->id));
$dbh->bz_commit_transaction();
}
sub get_content_type {
my $cgi = Bugzilla->cgi;
- return 'text/plain' if ($cgi->param('ispatch') || $cgi->param('attachurl'));
+ return 'text/plain' if ($cgi->param('ispatch') || $cgi->param('attach_text'));
my $content_type;
if (!defined $cgi->param('contenttypemethod')) {
type => 'b',
default => 0
},
- {
- name => 'allow_attach_url',
- type => 'b',
- default => 0
- },
{
name => 'maxattachmentsize',
DEFAULT => 'FALSE'},
isprivate => {TYPE => 'BOOLEAN', NOTNULL => 1,
DEFAULT => 'FALSE'},
- isurl => {TYPE => 'BOOLEAN', NOTNULL => 1,
- DEFAULT => 'FALSE'},
],
INDEXES => [
attachments_bug_id_idx => ['bug_id'],
buglist => 1},
{name => 'content', desc => 'Content'},
{name => 'attach_data.thedata', desc => 'Attachment data'},
- {name => 'attachments.isurl', desc => 'Attachment is a URL'},
{name => "owner_idle_time", desc => "Time Since Assignee Touched"},
{name => 'see_also', desc => "See Also",
type => FIELD_TYPE_BUG_URLS},
# PUBLIC is a reserved word in Oracle.
$dbh->bz_rename_column('series', 'public', 'is_public');
- # 2005-09-28 bugreport@peshkin.net Bug 149504
- $dbh->bz_add_column('attachments', 'isurl',
- {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0});
-
# 2005-10-21 LpSolit@gmail.com - Bug 313020
$dbh->bz_add_column('namedqueries', 'query_type',
{TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 0});
$dbh->bz_alter_column('products', 'allows_unconfirmed',
{ TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'TRUE' });
+ # 2010-07-18 LpSolit@gmail.com - Bug 119703
+ _remove_attachment_isurl();
+
################################################################
# New --TABLE-- changes should go *** A B O V E *** this point #
################################################################
}
}
+sub _remove_attachment_isurl {
+ my $dbh = Bugzilla->dbh;
+
+ if ($dbh->bz_column_info('attachments', 'isurl')) {
+ # Now all attachments must have a filename.
+ $dbh->do('UPDATE attachments SET filename = ? WHERE isurl = 1',
+ undef, 'url.txt');
+ $dbh->bz_drop_column('attachments', 'isurl');
+ $dbh->do("DELETE FROM fielddefs WHERE name='attachments.isurl'");
+ }
+}
+
1;
__END__
mimetype => $params->{content_type},
ispatch => $params->{is_patch},
isprivate => $params->{is_private},
- isurl => $params->{is_url},
});
my $comment = $params->{comment} || '';
$attachment->bug->add_comment($comment,
content_type => $self->type('string', $attach->contenttype),
is_private => $self->type('int', $attach->isprivate),
is_obsolete => $self->type('int', $attach->isobsolete),
- is_url => $self->type('int', $attach->isurl),
is_patch => $self->type('int', $attach->ispatch),
creator => $self->type('string', $attach->attacher->login),
attacher => $self->type('string', $attach->attacher->login),
C<boolean> True if the attachment is obsolete, False otherwise.
-=item C<is_url>
-
-C<boolean> True if the attachment is a URL instead of actual data,
-False otherwise. Note that such attachments only happen when the
-Bugzilla installation has at some point had the C<allow_attach_url>
-parameter enabled.
-
=item C<is_patch>
C<boolean> True if the attachment is a patch, False otherwise.
=item In Bugzilla B<4.0>, the C<description> return value was renamed to
C<summary>.
+=item In Bugzilla B<4.2>, the C<is_url> return value was removed
+(this attribute no longer exists for attachments).
+
=back
=back
Defaults to False if not specified.
-=item C<is_url>
-
-C<boolean> True if the attachment is just a URL, pointing to data elsewhere.
-If so, the C<data> item should just contain the URL.
-
-Defaults to False if not specified.
-
=back
=item B<Returns>
You specified a C<content_type> argument that was blank, not a valid
MIME type, or not a MIME type that Bugzilla accepts for attachments.
-=item 602 (Illegal URL)
-
-You specified C<is_url> as True, but the data that you attempted
-to attach was not a valid URL.
-
=item 603 (File Name Not Specified)
You did not specify a valid for the C<file_name> argument.
You did not specify a value for the C<summary> argument.
-=item 605 (URL Attaching Disabled)
+=back
+
+=item B<History>
+
+=over
+
+=item Added in Bugzilla B<4.0>.
-You attempted to attach a URL, setting C<is_url> to True,
-but this Bugzilla does not support attaching URLs.
+=item The C<is_url> parameter was removed in Bugzilla B<4.2>.
=back
# Attachment errors are 600-700.
file_too_large => 600,
invalid_content_type => 601,
- attachment_illegal_url => 602,
+ # Error 602 attachment_illegal_url no longer exists.
file_not_specified => 603,
missing_attachment_description => 604,
- attachment_url_disabled => 605,
+ # Error 605 attachment_url_disabled no longer exists.
# Errors thrown by the WebService itself. The ones that are negative
# conform to http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
my $attachment = Bugzilla::Attachment->create(
{bug => $bug,
creation_ts => $timestamp,
- data => scalar $cgi->param('attachurl') || $cgi->upload('data'),
+ data => scalar $cgi->param('attach_text') || $cgi->upload('data'),
description => scalar $cgi->param('description'),
- filename => $cgi->param('attachurl') ? '' : scalar $cgi->upload('data'),
+ filename => $cgi->param('attach_text') ? 'attachment.txt' : scalar $cgi->upload('data'),
ispatch => scalar $cgi->param('ispatch'),
isprivate => scalar $cgi->param('isprivate'),
- isurl => scalar $cgi->param('attachurl'),
mimetype => $content_type,
});
isobsolete (0|1) #IMPLIED
ispatch (0|1) #IMPLIED
isprivate (0|1) #IMPLIED
- isurl (0|1) #IMPLIED
>
<!ELEMENT attachid (#PCDATA)>
<!ELEMENT date (#PCDATA)>
</para>
<para>
- Also, if the administrator turned on the <quote>allow_attach_url</quote>
- parameter, you can enter the URL pointing to the attachment instead of
+ Also, you can enter the URL pointing to the attachment instead of
uploading the attachment itself. For example, this is useful if you want to
point to an external application, a website or a very large file. Note that
there is no guarantee that the source file will always be available, nor
that its content will remain unchanged.
</para>
+ <para>
+ Another way to attach data is to paste text directly in the text field,
+ and Bugzilla will convert it into an attachment. This is pretty useful
+ when you do copy and paste, and you don't want to put the text in a temporary
+ file first.
+ </para>
+
<section id="patchviewer">
<title>Patch Viewer</title>
form.contenttypeentry.disabled = isdisabled;
}
-function URLFieldHandler() {
- var field_attachurl = document.getElementById("attachurl");
+function TextFieldHandler() {
+ var field_text = document.getElementById("attach_text");
var greyfields = new Array("data", "ispatch", "autodetect",
"list", "manual", "contenttypeselection",
"contenttypeentry");
var i, thisfield;
- if (field_attachurl.value.match(/^\s*$/)) {
+ if (field_text.value.match(/^\s*$/)) {
for (i = 0; i < greyfields.length; i++) {
thisfield = document.getElementById(greyfields[i]);
if (thisfield) {
function DataFieldHandler() {
var field_data = document.getElementById("data");
- var greyfields = new Array("attachurl");
+ var greyfields = new Array("attach_text");
var i, thisfield;
if (field_data.value.match(/^\s*$/)) {
for (i = 0; i < greyfields.length; i++) {
document.getElementById('data').value = '';
DataFieldHandler();
- if ((element = document.getElementById('attachurl'))) {
+ if ((element = document.getElementById('attach_text'))) {
element.value = '';
- URLFieldHandler();
+ TextFieldHandler();
}
document.getElementById('description').value = '';
/* Fire onchange so that the disabled state of the content-type
# after the bug is filed.
# Add an attachment if requested.
-if (defined($cgi->upload('data')) || $cgi->param('attachurl')) {
+if (defined($cgi->upload('data')) || $cgi->param('attach_text')) {
$cgi->param('isprivate', $cgi->param('commentprivacy'));
# Must be called before create() as it may alter $cgi->param('ispatch').
$attachment = Bugzilla::Attachment->create(
{bug => $bug,
creation_ts => $timestamp,
- data => scalar $cgi->param('attachurl') || $cgi->upload('data'),
+ data => scalar $cgi->param('attach_text') || $cgi->upload('data'),
description => scalar $cgi->param('description'),
- filename => $cgi->param('attachurl') ? '' : scalar $cgi->upload('data'),
+ filename => $cgi->param('attach_text') ? 'attachment.txt' : scalar $cgi->upload('data'),
ispatch => scalar $cgi->param('ispatch'),
isprivate => scalar $cgi->param('isprivate'),
- isurl => scalar $cgi->param('attachurl'),
mimetype => $content_type,
});
};
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.",
-
maxattachmentsize => "The maximum size (in kilobytes) of attachments to be stored " _
"in the database. If a file larger than this size is attached " _
"to ${terms.abug}, $terms.Bugzilla will look at the " _
header = header
subheader = subheader
style_urls = [ 'skins/standard/attachment.css' ]
- javascript_urls = [ "js/attachment.js", "js/util.js" ]
+ javascript_urls = [ "js/attachment.js", "js/util.js", "js/TUI.js" ]
doc_section = "attachments.html"
%]
+<script type="text/javascript">
+<!--
+TUI_hide_default('attachment_text_field');
+-->
+</script>
+
<form name="entryform" method="post" action="attachment.cgi"
enctype="multipart/form-data"
onsubmit="return validateAttachmentForm(this)">
# Marc Schumann <wurblzap@gmail.com>
#%]
-<tr>
+<tr class="attachment_data">
<th><label for="data">File</label>:</th>
<td>
- <em>Enter the path to the file on your computer.</em><br>
- <input type="file" id="data" name="data" size="50"
- [% IF Param("allow_attach_url") %]
- onchange="DataFieldHandler()"
- [% END %]
- >
+ <em>Enter the path to the file on your computer</em> (or
+ <a id="attachment_data_controller" href="javascript:TUI_toggle_class('attachment_text_field');
+ javascript:TUI_toggle_class('attachment_data')"
+ >paste text as attachment</a>).<br>
+ <input type="file" id="data" name="data" size="50" onchange="DataFieldHandler()">
</td>
</tr>
-[% IF Param("allow_attach_url") %]
-<tr class="expert_fields">
- <th><label for="attachurl">AttachURL</label>:</th>
+<tr class="attachment_text_field">
+ <th><label for="attach_text">File</label>:</th>
<td>
- <em>URL to be attached instead.</em><br>
- <input type="text" id="attachurl" name="attachurl" size="60"
- maxlength="2000"
- onkeyup="URLFieldHandler()" onblur="URLFieldHandler()">
+ <em>Paste the text to be added as an attachment</em> (or
+ <a id="attachment_text_field_controller" href="javascript:TUI_toggle_class('attachment_text_field');
+ javascript:TUI_toggle_class('attachment_data')"
+ >attach a file</a>).<br>
+ <textarea id="attach_text" name="attach_text" cols="80" rows="15"
+ onkeyup="TextFieldHandler()" onblur="TextFieldHandler()"></textarea>
</td>
</tr>
-</tbody>
-[% END %]
<tr>
<th><label for="description">Description</label>:</th>
<td>
<span class="bz_edit">(<a href="javascript:toggle_attachment_details_visibility()">edit</a>)</span>
[% END %]
</div>
- [% IF NOT attachment.isurl %]
- <div class="details">
- [% attachment.filename FILTER html %] ([% attachment.contenttype FILTER html %])
- [% IF attachment.datasize %]
- [%+ attachment.datasize FILTER unitconvert %]
- [% ELSE %]
- <em>deleted</em>
- [% END %], created by [%+ INCLUDE global/user.html.tmpl who = attachment.attacher %]
- [% IF attachment.isprivate %]
- <span class="bz_private">Only visible to <strong>[% Param('insidergroup') FILTER html %]</strong></span>
- [% END %]
- </div>
- [% END %]
+ <div class="details">
+ [% attachment.filename FILTER html %] ([% attachment.contenttype FILTER html %])
+ [% IF attachment.datasize %]
+ [%+ attachment.datasize FILTER unitconvert %]
+ [% ELSE %]
+ <em>deleted</em>
+ [% END %], created by [%+ INCLUDE global/user.html.tmpl who = attachment.attacher %]
+ [% IF attachment.isprivate %]
+ <span class="bz_private">Only visible to <strong>[% Param('insidergroup') FILTER html %]</strong></span>
+ [% END %]
+ </div>
</div>
<div id="attachment_information_edit">
<span class="bz_hide">
%]
</div>
- [% IF attachment.isurl %]
- <input type="hidden" name="filename"
- value="[% attachment.filename FILTER html %]">
- <input type="hidden" name="contenttypeentry"
- value="[% attachment.contenttype FILTER html %]">
- [% ELSE %]
<div id="attachment_filename">
<label for="filename">Filename:</label>
<input type="text" size="20" class="text block[% editable_or_hide %]"
[%+ 'checked="checked"' IF attachment.ispatch %]>
<label for="ispatch">patch</label>
</div>
- [% END %]
+
<div class="readonly">
<div class="checkboxes">
<div id="attachment_isobsolete">
<div id="attachment_view_window">
[% IF !attachment.datasize %]
<div><b>The content of this attachment has been deleted.</b></div>
- [% ELSIF attachment.isurl %]
- <div>
- <a href="[% attachment.data FILTER html %]">
- [% IF attachment.datasize < 120 %]
- [% attachment.data FILTER html %]
- [% ELSE %]
- [% attachment.data FILTER truncate(80) FILTER html %]
- ...
- [% attachment.data.match(".*(.{20})$").0 FILTER html %]
- [% END %]
- </a>
- </div>
[% ELSIF !Param("allow_attachment_display") %]
<div id="view_disabled" >
<p><b>
[% obsolete_attachments = obsolete_attachments + 1 %]
[% END %]
<tr id="a[% count %]" class="[% "bz_contenttype_" _ attachment.contenttype
- FILTER css_class_quote UNLESS attachment.isurl %]
+ FILTER css_class_quote %]
[% " bz_patch" IF attachment.ispatch %]
- [% " bz_url" IF attachment.isurl %]
[% " bz_private" IF attachment.isprivate %]
[% " bz_tr_obsolete bz_default_hidden"
IF attachment.isobsolete %]">
([% attachment.datasize FILTER unitconvert %],
[% IF attachment.ispatch %]
patch)
- [% ELSIF attachment.isurl %]
- url)
[% ELSE %]
[%+ attachment.contenttype FILTER html %])
[% END %]
// Hide the Advanced Fields by default, unless the user has a cookie
// that specifies otherwise.
TUI_hide_default('expert_fields');
-
+// Also hide the "Paste text as attachment" textarea by default.
+TUI_hide_default('attachment_text_field');
-->
</script>
isobsolete="[% a.isobsolete FILTER xml %]"
ispatch="[% a.ispatch FILTER xml %]"
isprivate="[% a.isprivate FILTER xml %]"
- isurl="[% a.isurl FILTER xml %]"
>
<attachid>[% a.id %]</attachid>
<date>[% a.attached FILTER time("%Y-%m-%d %T %z") FILTER xml %]</date>
[% DEFAULT title = "Internal Error" %]
[% error_message = BLOCK %]
- [% IF error == "attachment_url_disabled" %]
- [% title = "Attachment URL Disabled" %]
- You cannot attach a URL. This feature is currently disabled.
-
- [% ELSIF error == "auth_invalid_email" %]
+ [% IF error == "auth_invalid_email" %]
[% title = "Invalid Email Address" %]
We received an email address (<b>[% addr FILTER html %]</b>)
that didn't pass our syntax checking for a legal email address,
"attachments.ispatch" => "Attachment is patch",
"attachments.isobsolete" => "Attachment is obsolete",
"attachments.isprivate" => "Attachment is private",
- "attachments.isurl" => "Attachment is a URL",
"attachments.submitter" => "Attachment creator",
"blocked" => "Blocks",
"bug_file_loc" => "URL",
[% title = "Attachment Deletion Disabled" %]
Attachment deletion is disabled on this installation.
- [% ELSIF error == "attachment_illegal_url" %]
- [% title = "Illegal Attachment URL" %]
- <em>[% url FILTER html %]</em> is not a legal URL for attachments.
- It must start either with http://, https:// or ftp://.
-
[% ELSIF error == "attachment_removed" %]
[% title = "Attachment Removed" %]
The attachment you are attempting to access has been removed.
[%# Hack to get the max value between both limits %]
[%+ max_limit.nsort.last FILTER html %] KB. <br>
We recommend that you store your attachment elsewhere
- [% IF Param("allow_attach_url") %]
- and then specify the URL to this file on the attachment
- creation page in the <b>AttachURL</b> field.
- [% ELSE %]
- and then insert the URL to it in a comment, or in the URL field
- for this [% terms.bug %].
- [% END %]
+ and then paste the URL to this file on the attachment
+ creation page in the appropriate text field.
<br>Alternately, if your attachment is an image, you could convert
it to a compressible format like JPG or PNG and try again.
# These are fields that we don't test. Test::More will mark these
# "TODO & SKIP", and not run tests for them at all.
#
-# attachments.isurl can't easily be supported by us, but it's basically
-# identical to isprivate and isobsolete for searching, so that's not a big
-# loss.
-#
# We don't support days_elapsed or owner_idle_time yet.
use constant SKIP_FIELDS => qw(
- attachments.isurl
owner_idle_time
days_elapsed
);
'attachments.isobsolete' => { db_skip => ['Pg'] },
'attachments.ispatch' => { db_skip => ['Pg'] },
'attachments.isprivate' => { db_skip => ['Pg'] },
- 'attachments.isurl' => { db_skip => ['Pg'] },
blocked => { db_skip => ['Pg'] },
bug_id => { db_skip => ['Pg'] },
cclist_accessible => { db_skip => ['Pg'] },