Bug 149504 Permit a reference to a URL to be treated as an attachment
Patch by Joel Peshkin <bugreport@peshkin.net> r=lpsolit, a=justdave git-svn-id: svn://10.0.0.236/trunk@182543 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
ce09a63d4e
commit
d146ce820a
@ -91,6 +91,7 @@ sub _retrieve {
|
|||||||
'%Y.%m.%d %H:%i') . " AS attached",
|
'%Y.%m.%d %H:%i') . " AS attached",
|
||||||
'attachments.filename AS filename',
|
'attachments.filename AS filename',
|
||||||
'attachments.ispatch AS ispatch',
|
'attachments.ispatch AS ispatch',
|
||||||
|
'attachments.isurl AS isurl',
|
||||||
'attachments.isobsolete AS isobsolete',
|
'attachments.isobsolete AS isobsolete',
|
||||||
'attachments.isprivate AS isprivate'
|
'attachments.isprivate AS isprivate'
|
||||||
);
|
);
|
||||||
|
|||||||
@ -40,6 +40,11 @@ $Bugzilla::Config::Attachment::sortkey = "025";
|
|||||||
sub get_param_list {
|
sub get_param_list {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my @param_list = (
|
my @param_list = (
|
||||||
|
{
|
||||||
|
name => 'allow_attach_url',
|
||||||
|
type => 'b',
|
||||||
|
default => 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name => 'maxpatchsize',
|
name => 'maxpatchsize',
|
||||||
type => 't',
|
type => 't',
|
||||||
|
|||||||
@ -313,6 +313,8 @@ use constant ABSTRACT_SCHEMA => {
|
|||||||
DEFAULT => 'FALSE'},
|
DEFAULT => 'FALSE'},
|
||||||
isprivate => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
isprivate => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
||||||
DEFAULT => 'FALSE'},
|
DEFAULT => 'FALSE'},
|
||||||
|
isurl => {TYPE => 'BOOLEAN', NOTNULL => 1,
|
||||||
|
DEFAULT => 'FALSE'},
|
||||||
],
|
],
|
||||||
INDEXES => [
|
INDEXES => [
|
||||||
attachments_bug_id_idx => ['bug_id'],
|
attachments_bug_id_idx => ['bug_id'],
|
||||||
|
|||||||
@ -911,13 +911,31 @@ sub insert
|
|||||||
ValidateBugID($bugid);
|
ValidateBugID($bugid);
|
||||||
validateCanChangeBug($bugid);
|
validateCanChangeBug($bugid);
|
||||||
ValidateComment(scalar $cgi->param('comment'));
|
ValidateComment(scalar $cgi->param('comment'));
|
||||||
my $filename = validateFilename();
|
my $attachurl = $cgi->param('attachurl') || '';
|
||||||
|
my $data;
|
||||||
|
my $filename;
|
||||||
|
my $contenttype;
|
||||||
|
my $isurl;
|
||||||
validateIsPatch();
|
validateIsPatch();
|
||||||
validateDescription();
|
validateDescription();
|
||||||
# need to validate content type before data as
|
|
||||||
# we now check the content type for image/bmp in validateData()
|
if (($attachurl =~ /^(http|https|ftp):\/\/\S+/)
|
||||||
validateContentType() unless $cgi->param('ispatch');
|
&& !(defined $cgi->upload('data'))) {
|
||||||
my $data = validateData();
|
$filename = '';
|
||||||
|
$data = $attachurl;
|
||||||
|
$isurl = 1;
|
||||||
|
$contenttype = SqlQuote('text/plain');
|
||||||
|
$cgi->param('ispatch', 0);
|
||||||
|
$cgi->delete('bigfile');
|
||||||
|
} else {
|
||||||
|
$filename = validateFilename();
|
||||||
|
# need to validate content type before data as
|
||||||
|
# we now check the content type for image/bmp in validateData()
|
||||||
|
validateContentType() unless $cgi->param('ispatch');
|
||||||
|
$data = validateData();
|
||||||
|
$contenttype = SqlQuote($cgi->param('contenttype'));
|
||||||
|
$isurl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
my @obsolete_ids = ();
|
my @obsolete_ids = ();
|
||||||
@obsolete_ids = validateObsolete() if $cgi->param('obsolete');
|
@obsolete_ids = validateObsolete() if $cgi->param('obsolete');
|
||||||
@ -946,7 +964,6 @@ sub insert
|
|||||||
# Escape characters in strings that will be used in SQL statements.
|
# Escape characters in strings that will be used in SQL statements.
|
||||||
my $sql_filename = SqlQuote($filename);
|
my $sql_filename = SqlQuote($filename);
|
||||||
my $description = SqlQuote($cgi->param('description'));
|
my $description = SqlQuote($cgi->param('description'));
|
||||||
my $contenttype = SqlQuote($cgi->param('contenttype'));
|
|
||||||
my $isprivate = $cgi->param('isprivate') ? 1 : 0;
|
my $isprivate = $cgi->param('isprivate') ? 1 : 0;
|
||||||
|
|
||||||
# Figure out when the changes were made.
|
# Figure out when the changes were made.
|
||||||
@ -956,10 +973,10 @@ sub insert
|
|||||||
# Insert the attachment into the database.
|
# Insert the attachment into the database.
|
||||||
my $sth = $dbh->prepare("INSERT INTO attachments
|
my $sth = $dbh->prepare("INSERT INTO attachments
|
||||||
(bug_id, creation_ts, filename, description,
|
(bug_id, creation_ts, filename, description,
|
||||||
mimetype, ispatch, isprivate, submitter_id)
|
mimetype, ispatch, isurl, isprivate, submitter_id)
|
||||||
VALUES ($bugid, $sql_timestamp, $sql_filename,
|
VALUES ($bugid, $sql_timestamp, $sql_filename,
|
||||||
$description, $contenttype, " . $cgi->param('ispatch') . ",
|
$description, $contenttype, " . $cgi->param('ispatch') . ",
|
||||||
$isprivate, $userid)");
|
$isurl, $isprivate, $userid)");
|
||||||
$sth->execute();
|
$sth->execute();
|
||||||
# Retrieve the ID of the newly created attachment record.
|
# Retrieve the ID of the newly created attachment record.
|
||||||
my $attachid = $dbh->bz_last_key('attachments', 'attach_id');
|
my $attachid = $dbh->bz_last_key('attachments', 'attach_id');
|
||||||
@ -1096,14 +1113,20 @@ sub edit
|
|||||||
my ($attach_id) = validateID();
|
my ($attach_id) = validateID();
|
||||||
|
|
||||||
# Retrieve the attachment from the database.
|
# Retrieve the attachment from the database.
|
||||||
SendSQL("SELECT description, mimetype, filename, bug_id, ispatch, isobsolete, isprivate, LENGTH(thedata)
|
SendSQL("SELECT description, mimetype, filename, bug_id, ispatch, isurl,
|
||||||
|
isobsolete, isprivate, LENGTH(thedata)
|
||||||
FROM attachments
|
FROM attachments
|
||||||
INNER JOIN attach_data
|
INNER JOIN attach_data
|
||||||
ON id = attach_id
|
ON id = attach_id
|
||||||
WHERE attach_id = $attach_id");
|
WHERE attach_id = $attach_id");
|
||||||
my ($description, $contenttype, $filename, $bugid, $ispatch, $isobsolete, $isprivate, $datasize) = FetchSQLData();
|
my ($description, $contenttype, $filename, $bugid, $ispatch, $isurl, $isobsolete, $isprivate, $datasize) = FetchSQLData();
|
||||||
|
|
||||||
my $isviewable = isViewable($contenttype);
|
my $isviewable = !$isurl && isViewable($contenttype);
|
||||||
|
my $thedata;
|
||||||
|
if ($isurl) {
|
||||||
|
SendSQL("SELECT thedata FROM attach_data WHERE id = $attach_id");
|
||||||
|
($thedata) = FetchSQLData();
|
||||||
|
}
|
||||||
|
|
||||||
# Retrieve a list of attachments for this bug as well as a summary of the bug
|
# Retrieve a list of attachments for this bug as well as a summary of the bug
|
||||||
# to use in a navigation bar across the top of the screen.
|
# to use in a navigation bar across the top of the screen.
|
||||||
@ -1135,9 +1158,11 @@ sub edit
|
|||||||
$vars->{'bugid'} = $bugid;
|
$vars->{'bugid'} = $bugid;
|
||||||
$vars->{'bugsummary'} = $bugsummary;
|
$vars->{'bugsummary'} = $bugsummary;
|
||||||
$vars->{'ispatch'} = $ispatch;
|
$vars->{'ispatch'} = $ispatch;
|
||||||
|
$vars->{'isurl'} = $isurl;
|
||||||
$vars->{'isobsolete'} = $isobsolete;
|
$vars->{'isobsolete'} = $isobsolete;
|
||||||
$vars->{'isprivate'} = $isprivate;
|
$vars->{'isprivate'} = $isprivate;
|
||||||
$vars->{'datasize'} = $datasize;
|
$vars->{'datasize'} = $datasize;
|
||||||
|
$vars->{'thedata'} = $thedata;
|
||||||
$vars->{'isviewable'} = $isviewable;
|
$vars->{'isviewable'} = $isviewable;
|
||||||
$vars->{'attachments'} = \@bugattachments;
|
$vars->{'attachments'} = \@bugattachments;
|
||||||
$vars->{'GetBugLink'} = \&GetBugLink;
|
$vars->{'GetBugLink'} = \&GetBugLink;
|
||||||
|
|||||||
@ -1742,6 +1742,7 @@ AddFDef("content", "Content", 0);
|
|||||||
|
|
||||||
$dbh->do("DELETE FROM fielddefs WHERE name='attachments.thedata'");
|
$dbh->do("DELETE FROM fielddefs WHERE name='attachments.thedata'");
|
||||||
AddFDef("attach_data.thedata", "Attachment data", 0);
|
AddFDef("attach_data.thedata", "Attachment data", 0);
|
||||||
|
AddFDef("attachments.isurl", "Attachment is a URL", 0);
|
||||||
|
|
||||||
###########################################################################
|
###########################################################################
|
||||||
# Detect changed local settings
|
# Detect changed local settings
|
||||||
@ -4033,6 +4034,9 @@ if ($dbh->bz_column_info("series", "public")) {
|
|||||||
$dbh->bz_rename_column('series', 'public', 'is_public');
|
$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});
|
||||||
|
|
||||||
# If you had to change the --TABLE-- definition in any way, then add your
|
# If you had to change the --TABLE-- definition in any way, then add your
|
||||||
# differential change code *** A B O V E *** this comment.
|
# differential change code *** A B O V E *** this comment.
|
||||||
|
|||||||
@ -25,6 +25,9 @@
|
|||||||
%]
|
%]
|
||||||
|
|
||||||
[% param_descs = {
|
[% param_descs = {
|
||||||
|
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 " _
|
maxpatchsize => "The maximum size (in kilobytes) of patches. $terms.Bugzilla will not " _
|
||||||
"accept patches greater than this number of kilobytes in size. " _
|
"accept patches greater than this number of kilobytes in size. " _
|
||||||
"To accept patches of any size (subject to the limitations of " _
|
"To accept patches of any size (subject to the limitations of " _
|
||||||
|
|||||||
@ -17,6 +17,8 @@
|
|||||||
# Rights Reserved.
|
# Rights Reserved.
|
||||||
#
|
#
|
||||||
# Contributor(s): Myk Melez <myk@mozilla.org>
|
# Contributor(s): Myk Melez <myk@mozilla.org>
|
||||||
|
# Joel Peshkin <bugreport@peshkin.net>
|
||||||
|
# Erik Stambaugh <erik@dasbistro.com>
|
||||||
#%]
|
#%]
|
||||||
|
|
||||||
[% PROCESS global/variables.none.tmpl %]
|
[% PROCESS global/variables.none.tmpl %]
|
||||||
@ -53,6 +55,58 @@
|
|||||||
onload="setContentTypeDisabledState();"
|
onload="setContentTypeDisabledState();"
|
||||||
%]
|
%]
|
||||||
|
|
||||||
|
[% IF Param("allow_attach_url") %]
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
function URLFieldHandler() {
|
||||||
|
var field_attachurl = document.getElementById("attachurl");
|
||||||
|
var greyfields = new Array("data", "ispatch", "autodetect",
|
||||||
|
"list", "manual", "bigfile",
|
||||||
|
"contenttypeselection",
|
||||||
|
"contenttypeentry");
|
||||||
|
var i;
|
||||||
|
if (field_attachurl.value.match(/^\s*$/)) {
|
||||||
|
for (i = 0; i < greyfields.length; i++) {
|
||||||
|
thisfield = document.getElementById(greyfields[i]);
|
||||||
|
if (thisfield) {
|
||||||
|
thisfield.removeAttribute("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < greyfields.length; i++) {
|
||||||
|
thisfield = document.getElementById(greyfields[i]);
|
||||||
|
if (thisfield) {
|
||||||
|
thisfield.setAttribute("disabled", "disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function DataFieldHandler() {
|
||||||
|
var field_data = document.getElementById("data");
|
||||||
|
var greyfields = new Array("attachurl");
|
||||||
|
if (field_data.value.match(/^\s*$/)) {
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < greyfields.length; i++) {
|
||||||
|
thisfield = document.getElementById(greyfields[i]);
|
||||||
|
if (thisfield) {
|
||||||
|
thisfield.removeAttribute("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < greyfields.length; i++) {
|
||||||
|
thisfield = document.getElementById(greyfields[i]);
|
||||||
|
if (thisfield) {
|
||||||
|
thisfield.setAttribute("disabled", "disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
[% END %]
|
||||||
|
|
||||||
|
|
||||||
<form name="entryform" method="post" action="attachment.cgi" enctype="multipart/form-data">
|
<form name="entryform" method="post" action="attachment.cgi" enctype="multipart/form-data">
|
||||||
<input type="hidden" name="bugid" value="[% bugid %]">
|
<input type="hidden" name="bugid" value="[% bugid %]">
|
||||||
<input type="hidden" name="action" value="insert">
|
<input type="hidden" name="action" value="insert">
|
||||||
@ -62,7 +116,11 @@
|
|||||||
<th><label for="data">File:</label></th>
|
<th><label for="data">File:</label></th>
|
||||||
<td>
|
<td>
|
||||||
<em>Enter the path to the file on your computer.</em><br>
|
<em>Enter the path to the file on your computer.</em><br>
|
||||||
<input type="file" id="data" name="data" size="50">
|
<input type="file" id="data" name="data" size="50"
|
||||||
|
[% IF Param("allow_attach_url") %]
|
||||||
|
onchange="DataFieldHandler()"
|
||||||
|
[% END %]
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
[% IF Param("maxlocalattachment") %]
|
[% IF Param("maxlocalattachment") %]
|
||||||
@ -77,6 +135,17 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
[% END %]
|
[% END %]
|
||||||
|
[% IF Param("allow_attach_url") %]
|
||||||
|
<tr>
|
||||||
|
<th><label for="attachurl">AttachURL:</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()">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
[% END %]
|
||||||
<tr>
|
<tr>
|
||||||
<th><label for="description">Description:</label></th>
|
<th><label for="description">Description:</label></th>
|
||||||
<td>
|
<td>
|
||||||
@ -104,14 +173,15 @@
|
|||||||
<input type="radio" id="list"
|
<input type="radio" id="list"
|
||||||
name="contenttypemethod" value="list">
|
name="contenttypemethod" value="list">
|
||||||
<label for="list">select from list:</label>
|
<label for="list">select from list:</label>
|
||||||
<select name="contenttypeselection"
|
<select name="contenttypeselection" id="contenttypeselection"
|
||||||
onchange="this.form.contenttypemethod[1].checked = true;">
|
onchange="this.form.contenttypemethod[1].checked = true;">
|
||||||
[% PROCESS "attachment/content-types.html.tmpl" %]
|
[% PROCESS "attachment/content-types.html.tmpl" %]
|
||||||
</select><br>
|
</select><br>
|
||||||
<input type="radio" id="manual"
|
<input type="radio" id="manual"
|
||||||
name="contenttypemethod" value="manual">
|
name="contenttypemethod" value="manual">
|
||||||
<label for="manual">enter manually:</label>
|
<label for="manual">enter manually:</label>
|
||||||
<input type="text" name="contenttypeentry" size="30" maxlength="200"
|
<input type="text" name="contenttypeentry" id="contenttypeentry"
|
||||||
|
size="30" maxlength="200"
|
||||||
onchange="if (this.value) this.form.contenttypemethod[2].checked = true;">
|
onchange="if (this.value) this.form.contenttypemethod[2].checked = true;">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -209,16 +209,21 @@
|
|||||||
<b>Description:</b><br>
|
<b>Description:</b><br>
|
||||||
<textarea rows="3" cols="25" name="description" wrap="soft">[% description FILTER html %]</textarea><br>
|
<textarea rows="3" cols="25" name="description" wrap="soft">[% description FILTER html %]</textarea><br>
|
||||||
|
|
||||||
<b>Filename:</b><br>
|
[% IF isurl %]
|
||||||
<input type="text" size="20" name="filename" value="[% filename FILTER html %]"><br>
|
<input type="hidden" name="filename" value="[% filename FILTER html %]"><br>
|
||||||
<b>Size: </b>[% datasize FILTER unitconvert %]<br>
|
<input type="hidden" name="contenttypeentry" value="[% contenttype FILTER html %]"><br>
|
||||||
|
[% ELSE %]
|
||||||
|
<b>Filename:</b><br>
|
||||||
|
<input type="text" size="20" name="filename" value="[% filename FILTER html %]"><br>
|
||||||
|
<b>Size: </b>[% datasize FILTER unitconvert %]<br>
|
||||||
|
|
||||||
<b>MIME Type:</b><br>
|
<b>MIME Type:</b><br>
|
||||||
<input type="text" size="20" name="contenttypeentry" value="[% contenttype FILTER html %]"><br>
|
<input type="text" size="20" name="contenttypeentry" value="[% contenttype FILTER html %]"><br>
|
||||||
|
|
||||||
<input type="checkbox" id="ispatch" name="ispatch" value="1"
|
<input type="checkbox" id="ispatch" name="ispatch" value="1"
|
||||||
[% 'checked="checked"' IF ispatch %]>
|
[% 'checked="checked"' IF ispatch %]>
|
||||||
<label for="ispatch">patch</label>
|
<label for="ispatch">patch</label>
|
||||||
|
[% END %]
|
||||||
<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>
|
||||||
@ -237,7 +242,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="submit" value="Submit"><br><br>
|
<input type="submit" value="Submit"><br><br>
|
||||||
<strong>Actions:</strong> <a href="attachment.cgi?id=[% attachid %]">View</a>
|
<strong>Actions:</strong>
|
||||||
|
<a href="attachment.cgi?id=[% attachid %]">View</a>
|
||||||
[% IF ispatch && patchviewerinstalled %]
|
[% IF ispatch && patchviewerinstalled %]
|
||||||
| <a href="attachment.cgi?id=[% attachid %]&action=diff">Diff</a>
|
| <a href="attachment.cgi?id=[% attachid %]&action=diff">Diff</a>
|
||||||
[% END %]
|
[% END %]
|
||||||
@ -268,6 +274,18 @@
|
|||||||
//-->
|
//-->
|
||||||
</script>
|
</script>
|
||||||
</td>
|
</td>
|
||||||
|
[% ELSIF isurl %]
|
||||||
|
<td width="75%">
|
||||||
|
<a href="[% thedata FILTER html %]">
|
||||||
|
[% IF datasize < 120 %]
|
||||||
|
[% thedata FILTER html %]
|
||||||
|
[% ELSE %]
|
||||||
|
[% thedata FILTER truncate(80) FILTER html %]
|
||||||
|
...
|
||||||
|
[% thedata.match(".*(.{20})$").0 FILTER html %]
|
||||||
|
[% END %]
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
<td id="noview" width="50%">
|
<td id="noview" width="50%">
|
||||||
<p><b>
|
<p><b>
|
||||||
|
|||||||
@ -43,6 +43,8 @@
|
|||||||
<td valign="top">
|
<td valign="top">
|
||||||
[% IF attachment.ispatch %]
|
[% IF attachment.ispatch %]
|
||||||
<i>patch</i>
|
<i>patch</i>
|
||||||
|
[% ELSIF attachment.isurl %]
|
||||||
|
<i>url</i>
|
||||||
[% ELSE %]
|
[% ELSE %]
|
||||||
[% attachment.contenttype FILTER html %]
|
[% attachment.contenttype FILTER html %]
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user