Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
bugzilla
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ivan Ivlev
bugzilla
Commits
30a52319
Commit
30a52319
authored
Feb 21, 2005
by
bugreport%peshkin.net
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bug 252272: Allow extremely large attachments to be stored locally
r=wurblzap.a=justdave
parent
c1d16e42
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
143 additions
and
16 deletions
+143
-16
Attachment.pm
Bugzilla/Attachment.pm
+12
-0
Config.pm
Bugzilla/Config.pm
+3
-1
attachment.cgi
attachment.cgi
+76
-15
checksetup.pl
checksetup.pl
+20
-0
defparams.pl
defparams.pl
+11
-0
create.html.tmpl
template/en/default/attachment/create.html.tmpl
+12
-0
user-error.html.tmpl
template/en/default/global/user-error.html.tmpl
+9
-0
No files found.
Bugzilla/Attachment.pm
View file @
30a52319
...
...
@@ -33,6 +33,7 @@ package Bugzilla::Attachment;
# Use the Flag module to handle flags.
use
Bugzilla::
Flag
;
use
Bugzilla::
Config
qw(:locations)
;
############################################################################
# Functions
...
...
@@ -92,6 +93,17 @@ sub query
# Retrieve a list of flags for this attachment.
$a
{
'flags'
}
=
Bugzilla::Flag::
match
({
'attach_id'
=>
$a
{
'attachid'
},
'is_active'
=>
1
});
# A zero size indicates that the attachment is stored locally.
if
(
$a
{
'datasize'
}
==
0
)
{
my
$attachid
=
$a
{
'attachid'
};
my
$hash
=
(
$attachid
%
100
)
+
100
;
$hash
=~
s/.*(\d\d)$/group.$1/
;
if
(
open
(
AH
,
"$attachdir/$hash/attachment.$attachid"
))
{
$a
{
'datasize'
}
=
(
stat
(
AH
))[
7
];
close
(
AH
);
}
}
# We will display the edit link if the user can edit the attachment;
# ie the are the submitter, or they have canedit.
...
...
Bugzilla/Config.pm
View file @
30a52319
...
...
@@ -55,6 +55,7 @@ use Bugzilla::Util;
our
$libpath
=
'.'
;
our
$localconfig
=
"$libpath/localconfig"
;
our
$datadir
=
"$libpath/data"
;
our
$attachdir
=
"$datadir/attachments"
;
our
$templatedir
=
"$libpath/template"
;
our
$webdotdir
=
"$datadir/webdot"
;
...
...
@@ -72,7 +73,8 @@ our $webdotdir = "$datadir/webdot";
(
admin
=>
[
qw(GetParamList UpdateParams SetParam WriteParams)
],
db
=>
[
qw($db_driver $db_host $db_port $db_name $db_user $db_pass $db_sock)
],
locations
=>
[
qw($libpath $localconfig $datadir $templatedir $webdotdir)
],
locations
=>
[
qw($libpath $localconfig $attachdir
$datadir $templatedir $webdotdir)
],
);
Exporter::
export_ok_tags
(
'admin'
,
'db'
,
'locations'
);
...
...
attachment.cgi
View file @
30a52319
...
...
@@ -40,6 +40,7 @@ use vars qw(
# Include the Bugzilla CGI and general utility library.
require
"CGI.pl"
;
use
Bugzilla::
Config
qw(:locations)
;
# Use these modules to handle flags.
use
Bugzilla::
Constants
;
...
...
@@ -360,12 +361,18 @@ sub validateData
{
my
$maxsize
=
$::FORM
{
'ispatch'
}
?
Param
(
'maxpatchsize'
)
:
Param
(
'maxattachmentsize'
);
$maxsize
*=
1024
;
# Convert from K
my
$fh
=
$cgi
->
upload
(
'data'
);
my
$fh
;
# Skip uploading into a local variable if the user wants to upload huge
# attachments into local files.
if
(
!
$::FORM
{
'bigfile'
})
{
$fh
=
$cgi
->
upload
(
'data'
);
}
my
$data
;
# We could get away with reading only as much as required, except that then
# we wouldn't have a size to print to the error handler below.
if
(
!
$::FORM
{
'bigfile'
})
{
# enable 'slurp' mode
local
$/
;
...
...
@@ -373,10 +380,11 @@ sub validateData
}
$data
||
(
$::FORM
{
'bigfile'
})
||
ThrowUserError
(
"zero_length_file"
);
# Make sure the attachment does not exceed the maximum permitted size
my
$len
=
length
(
$data
)
;
my
$len
=
$data
?
length
(
$data
)
:
0
;
if
(
$maxsize
&&
$len
>
$maxsize
)
{
my
$vars
=
{
filesize
=>
sprintf
(
"%.0f"
,
$len
/
1024
)
};
if
(
$::FORM
{
'ispatch'
}
)
{
...
...
@@ -504,6 +512,23 @@ sub view
# Return the appropriate HTTP response headers.
$filename
=~
s/^.*[\/\\]//
;
my
$filesize
=
length
(
$thedata
);
# A zero length attachment in the database means the attachment is
# stored in a local file
if
(
$filesize
==
0
)
{
my
$attachid
=
$::FORM
{
'id'
};
my
$hash
=
(
$attachid
%
100
)
+
100
;
$hash
=~
s/.*(\d\d)$/group.$1/
;
if
(
open
(
AH
,
"$attachdir/$hash/attachment.$attachid"
))
{
binmode
AH
;
$filesize
=
(
stat
(
AH
))[
7
];
}
}
if
(
$filesize
==
0
)
{
ThrowUserError
(
"attachment_removed"
);
}
# escape quotes and backslashes in the filename, per RFCs 2045/822
$filename
=~
s/\\/\\\\/g
;
# escape backslashes
...
...
@@ -513,7 +538,15 @@ sub view
-
content_disposition
=>
"inline; filename=\"$filename\""
,
-
content_length
=>
$filesize
);
print
$thedata
;
if
(
$thedata
)
{
print
$thedata
;
}
else
{
while
(
<
AH
>
)
{
print
$_
;
}
close
(
AH
);
}
}
sub
interdiff
...
...
@@ -771,7 +804,7 @@ sub viewall
$privacy
=
"AND isprivate < 1 "
;
}
SendSQL
(
"SELECT attach_id, DATE_FORMAT(creation_ts, '%Y.%m.%d %H:%i'),
mimetype, description, ispatch, isobsolete, isprivate,
mimetype, description, ispatch, isobsolete, isprivate,
LENGTH(thedata)
FROM attachments WHERE bug_id = $::FORM{'bugid'} $privacy
ORDER BY attach_id"
);
...
...
@@ -779,7 +812,7 @@ sub viewall
while
(
MoreSQLData
())
{
my
%
a
;
# the attachment hash
(
$a
{
'attachid'
},
$a
{
'date'
},
$a
{
'contenttype'
},
(
$a
{
'attachid'
},
$a
{
'date'
},
$a
{
'contenttype'
},
$a
{
'description'
},
$a
{
'ispatch'
},
$a
{
'isobsolete'
},
$a
{
'isprivate'
},
$a
{
'datasize'
})
=
FetchSQLData
();
$a
{
'isviewable'
}
=
isViewable
(
$a
{
'contenttype'
});
...
...
@@ -889,11 +922,39 @@ sub insert
# Retrieve the ID of the newly created attachment record.
my
$attachid
=
$dbh
->
bz_last_key
(
'attachments'
,
'attach_id'
);
# If the file is to be stored locally, stream the file from the webserver
# to the local file without reading it into a local variable.
if
(
$::FORM
{
'bigfile'
})
{
my
$fh
=
$cgi
->
upload
(
'data'
);
my
$hash
=
(
$attachid
%
100
)
+
100
;
$hash
=~
s/.*(\d\d)$/group.$1/
;
mkdir
"$attachdir/$hash"
,
0770
;
chmod
0770
,
"$attachdir/$hash"
;
open
(
AH
,
">$attachdir/$hash/attachment.$attachid"
);
binmode
AH
;
my
$sizecount
=
0
;
my
$limit
=
(
Param
(
"maxlocalattachment"
)
*
1048576
);
while
(
<
$fh
>
)
{
print
AH
$_
;
$sizecount
+=
length
(
$_
);
if
(
$sizecount
>
$limit
)
{
close
AH
;
close
$fh
;
unlink
"$attachdir/$hash/attachment.$attachid"
;
ThrowUserError
(
"local_file_too_large"
);
}
}
close
AH
;
close
$fh
;
}
# Insert a comment about the new attachment into the database.
my
$comment
=
"Created an attachment (id=$attachid)\n$::FORM{'description'}\n"
;
$comment
.=
(
"\n"
.
$::FORM
{
'comment'
})
if
$::FORM
{
'comment'
};
AppendComment
(
$::FORM
{
'bugid'
},
AppendComment
(
$::FORM
{
'bugid'
},
Bugzilla
->
user
->
login
,
$comment
,
$isprivate
,
...
...
@@ -906,7 +967,7 @@ sub insert
SendSQL
(
"INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($::FORM{'bugid'}, $obsolete_id, $::userid, $sql_timestamp, $fieldid, '0', '1')"
);
# If the obsolete attachment has pending flags, migrate them to the new attachment.
if
(
Bugzilla::Flag::
count
({
'attach_id'
=>
$obsolete_id
,
if
(
Bugzilla::Flag::
count
({
'attach_id'
=>
$obsolete_id
,
'status'
=>
'pending'
,
'is_active'
=>
1
}))
{
Bugzilla::Flag::
migrate
(
$obsolete_id
,
$attachid
,
$timestamp
);
...
...
@@ -1009,11 +1070,11 @@ sub edit
# Get a list of flag types that can be set for this attachment.
SendSQL
(
"SELECT product_id, component_id FROM bugs WHERE bug_id = $bugid"
);
my
(
$product_id
,
$component_id
)
=
FetchSQLData
();
my
$flag_types
=
Bugzilla::FlagType::
match
({
'target_type'
=>
'attachment'
,
'product_id'
=>
$product_id
,
my
$flag_types
=
Bugzilla::FlagType::
match
({
'target_type'
=>
'attachment'
,
'product_id'
=>
$product_id
,
'component_id'
=>
$component_id
});
foreach
my
$flag_type
(
@$flag_types
)
{
$flag_type
->
{
'flags'
}
=
Bugzilla::Flag::
match
({
'type_id'
=>
$flag_type
->
{
'id'
},
$flag_type
->
{
'flags'
}
=
Bugzilla::Flag::
match
({
'type_id'
=>
$flag_type
->
{
'id'
},
'attach_id'
=>
$::FORM
{
'id'
},
'is_active'
=>
1
});
}
...
...
@@ -1087,10 +1148,10 @@ sub update
# Update the attachment record in the database.
# Sets the creation timestamp to itself to avoid it being updated automatically.
SendSQL
(
"UPDATE attachments
SET description = $quoteddescription ,
mimetype = $quotedcontenttype ,
SET description = $quoteddescription ,
mimetype = $quotedcontenttype ,
filename = $quotedfilename ,
ispatch = $::FORM{'ispatch'}
,
ispatch = $::FORM{'ispatch'}
,
isobsolete = $::FORM{'isobsolete'} ,
isprivate = $::FORM{'isprivate'}
WHERE attach_id = $::FORM{'id'}
...
...
@@ -1143,7 +1204,7 @@ sub update
# Unlock all database tables now that we are finished updating the database.
$dbh
->
bz_unlock_tables
();
# If the user submitted a comment while editing the attachment,
# If the user submitted a comment while editing the attachment,
# add the comment to the bug.
if
(
$::FORM
{
'comment'
}
)
{
...
...
checksetup.pl
View file @
30a52319
...
...
@@ -904,6 +904,14 @@ unless (-d $datadir && -e "$datadir/nomail") {
open
FILE
,
'>>'
,
"$datadir/mail"
;
close
FILE
;
}
unless
(
-
d
$attachdir
)
{
print
"Creating local attachments directory ...\n"
;
# permissions for non-webservergroup are fixed later on
mkdir
$attachdir
,
0770
;
}
# 2000-12-14 New graphing system requires a directory to put the graphs in
# This code copied from what happens for the data dir above.
# If the graphs dir is not present, we assume that they have been using
...
...
@@ -1088,6 +1096,17 @@ END
}
}
if
(
!-
e
"$attachdir/.htaccess"
)
{
print
"Creating $attachdir/.htaccess...\n"
;
open
HTACCESS
,
">$attachdir/.htaccess"
;
print
HTACCESS
<<'END';
# nothing in this directory is retrievable unless overriden by an .htaccess
# in a subdirectory;
deny from all
END
close
HTACCESS
;
chmod
$fileperm
,
"$attachdir/.htaccess"
;
}
if
(
!-
e
"Bugzilla/.htaccess"
)
{
print
"Creating Bugzilla/.htaccess...\n"
;
open
HTACCESS
,
'>'
,
'Bugzilla/.htaccess'
;
...
...
@@ -1428,6 +1447,7 @@ if ($^O !~ /MSWin32/i) {
fixPerms
(
"$datadir/duplicates"
,
$<
,
$webservergid
,
027
,
1
);
fixPerms
(
"$datadir/mining"
,
$<
,
$webservergid
,
027
,
1
);
fixPerms
(
"$datadir/template"
,
$<
,
$webservergid
,
007
,
1
);
# webserver will write to these
fixPerms
(
$attachdir
,
$<
,
$webservergid
,
007
,
1
);
# webserver will write to these
fixPerms
(
$webdotdir
,
$<
,
$webservergid
,
007
,
1
);
fixPerms
(
"$webdotdir/.htaccess"
,
$<
,
$webservergid
,
027
);
fixPerms
(
"$datadir/params"
,
$<
,
$webservergid
,
017
);
...
...
defparams.pl
View file @
30a52319
...
...
@@ -1270,6 +1270,17 @@ Reason: %reason%
},
{
name
=>
'maxlocalattachment'
,
desc
=>
'The maximum size (in Megabytes) of attachments identified by '
.
'the user as "Big Files" to be stored locally on the webserver. '
.
'If set to zero, attachments will never be kept on the local '
.
'filesystem.'
,
type
=>
't'
,
default
=>
'0'
,
checker
=>
\&
check_numeric
},
{
name
=>
'chartgroup'
,
desc
=>
'The name of the group of users who can use the "New Charts" '
.
'feature. Administrators should ensure that the public categories '
.
...
...
template/en/default/attachment/create.html.tmpl
View file @
30a52319
...
...
@@ -65,6 +65,18 @@
<input type="file" id="data" name="data" size="50">
</td>
</tr>
[% IF Param("maxlocalattachment") %]
<tr>
<th>BigFile:</th>
<td>
<input type="checkbox" id="bigfile"
name="bigfile" value="bigfile">
<label for="bigfile">
Big File - Stored locally and may be purged
</label>
</td>
</tr>
[% END %]
<tr>
<th><label for="description">Description:</label></th>
<td>
...
...
template/en/default/global/user-error.html.tmpl
View file @
30a52319
...
...
@@ -156,6 +156,10 @@
[% title = "Access Denied" %]
You are not authorized to access this attachment.
[% ELSIF error == "attachment_removed" %]
[% title = "Attachment Removed" %]
The attachment you are attempting to access has been removed.
[% ELSIF error == "bug_access_denied" %]
[% title = "Access Denied" %]
You are not authorized to access [% terms.bug %] #[% bug_id FILTER html %].
...
...
@@ -604,6 +608,11 @@
[% title = "Invalid Keyword Name" %]
You may not use commas or whitespace in a keyword name.
[% ELSIF error == "local_file_too_large" %]
[% title = "Local File Too Large" %]
Local file uploads must not exceed
[% Param('maxlocalattachment') %] MB in size.
[% ELSIF error == "login_needed_for_password_change" %]
[% title = "Login Name Required" %]
You must enter a login name when requesting to change your password.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment