diff --git a/updown/lang/en b/updown/lang/en
index 6145b4990..0404108d3 100644
--- a/updown/lang/en
+++ b/updown/lang/en
@@ -44,7 +44,7 @@ index_email2=Send email when uploads are done?
upload_title=Upload Files
upload_direct=Write files directly to disk?
upload_err=Failed to upload files
-upload_emove=Failed to move uploaded file from $1 to $2
+upload_emove=Failed to move uploaded file from $1 to $2 : $3
upload_edir=Missing directory to upload to
upload_euser=Missing or invalid username
upload_egroup=Missing or invalid group name
diff --git a/updown/upload.cgi b/updown/upload.cgi
index 4b514669f..01d58a0d4 100755
--- a/updown/upload.cgi
+++ b/updown/upload.cgi
@@ -6,18 +6,19 @@ require './updown-lib.pl';
&error_setup($text{'upload_err'});
&ReadParse(\%getin, "GET");
$upid = $getin{'id'};
-$direct_upload = $getin{'direct'};
-my $tmp;
-# $ENV{'WEBMIN_VAR'} is trully horrible choice to store temporary files
-# but it's only used here for current compatibility with
-# "read_parse_mime_callback". We should fix it right away, on the next commit!!
-$tmp = $ENV{'WEBMIN_VAR'} if ($direct_upload);
-if ($can_mode == 3 && &supports_users()) {
- # User is fixed
- @uinfo = getpwnam($remote_user);
- $tmp = "$uinfo[7]/.tmp" if ($direct_upload);
+
+if ($getin{'direct'}) {
+ # Create a temp directory for the uploaded files for ReadParseMime
+ $direct_dir = &transname();
+ &make_dir($direct_dir, 0711);
}
-&ReadParseMime($upload_max, \&read_parse_mime_callback, [ $upid ], 1, $tmp);
+
+if ($can_mode == 3 && &supports_users()) {
+ # User to upload as is set in the ACL
+ @uinfo = getpwnam($remote_user);
+ }
+&ReadParseMime($upload_max, \&read_parse_mime_callback, [ $upid ], 1,
+ $direct_dir);
foreach my $k (keys %in) {
$in{$k} = $in{$k}->[0] if ($k !~ /^upload\d+/);
}
@@ -51,6 +52,13 @@ $found || &error($text{'upload_enone'});
&can_write_file($in{'dir'}) ||
&error(&text('upload_eaccess', "$in{'dir'}", $!));
+# If in direct mode, the uploaded files need to be readable by the user we're
+# going to write files as
+if ($direct_dir) {
+ &set_ownership_permissions($uinfo[2], $uinfo[3], undef,
+ $direct_dir, glob("$direct_dir/*"));
+ }
+
# Switch to the upload user
&switch_uid_to($uinfo[2], scalar(@ginfo) ? $ginfo[2] : $uinfo[3]);
@@ -68,10 +76,18 @@ for($i=0; defined($in{"upload$i"}); $i++) {
$d = $in{"upload${i}"}->[$j];
$f = $in{"upload${i}_filename"}->[$j];
next if (!$f);
+
+ # Work out the short name of the uploaded file, and
+ # where it is stored if in direct mode
+ $f =~ /([^\\\/]+)$/;
+ my $fname = $1;
my $mpath;
+ if ($direct_dir) {
+ $mpath = $direct_dir."/".$fname;
+ }
+
+ # Work out were the uploaded file is being written to
if (-d $in{'dir'}) {
- $f =~ /([^\\\/]+)$/;
- $mpath = "$tmp/$1" if ($tmp);
$path = "$in{'dir'}/$1";
}
else {
@@ -79,27 +95,17 @@ for($i=0; defined($in{"upload$i"}); $i++) {
}
print &text('upload_saving',
"".&html_escape($path).""),"
\n";
- # Move file we already have it in disk
+
if ($mpath) {
- if (-w $in{'dir'}) {
- # Switch back to chown the file
- &switch_uid_back();
- chown($uinfo[2], scalar(@ginfo)
- ? $ginfo[2]
- : $uinfo[3],
- $mpath);
- # Alway move the file as effective user
- &switch_uid_to($uinfo[2], scalar(@ginfo)
- ? $ginfo[2]
- : $uinfo[3]);
- if (!rename($mpath, $path)) {
- &error(&text('upload_emove',
- "$mpath",
- "$path", $!));
- }
- }
+ # Move file as we already have it in disk
+ rename($mpath, $path) ||
+ &move_source_dest($mpath, $path) ||
+ &error(&text('upload_emove',
+ "".&html_escape($mpath)."",
+ "".&html_escape($path)."", $!));
}
else {
+ # Write uploaded data to the destination file
if (!&open_tempfile(FILE, ">$path", 1)) {
&error(&text('upload_eopen', "$path",
$!));
@@ -121,7 +127,6 @@ for($i=0; defined($in{"upload$i"}); $i++) {
local $qdir = quotemeta($dir);
local $qpath = quotemeta($path);
local @files;
- &switch_uid_back();
if ($path =~ /\.zip$/i) {
# ZIP file
if (!&has_command("unzip")) {
@@ -203,8 +208,6 @@ for($i=0; defined($in{"upload$i"}); $i++) {
# Doesn't look possible
$err = $text{'upload_notcomp'};
}
- &switch_uid_to($uinfo[2],
- scalar(@ginfo) ? $ginfo[2] : $uinfo[3]);
if (!$err) {
my $jn = join("
",
map { " $_" }